From 2482141d0f349f02e797d8db3316b18c1e376401 Mon Sep 17 00:00:00 2001 From: fallen-angle <1853633282@qq.com> Date: Sat, 30 Apr 2022 11:30:55 +0800 Subject: [PATCH] comm: swagger doc --- docs/docs.go | 234 ++++++++++++++++++++++++++++++------- docs/swagger.json | 222 +++++++++++++++++++++++++++++------ docs/swagger.yaml | 156 ++++++++++++++++++++----- handler/article.go | 29 +++-- handler/user.go | 9 +- initialize/cron.go | 4 +- initialize/swagger.go | 2 +- service/article/article.go | 4 +- service/user/user.go | 6 + 9 files changed, 538 insertions(+), 128 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index 6fe0310..90c5936 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,10 +1,10 @@ -// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// Package docs GENERATED BY SWAG; DO NOT EDIT // This file was generated by swaggo/swag package docs import "github.com/swaggo/swag" -const docTemplate_swagger = `{ +const docTemplate = `{ "schemes": {{ marshal .Schemes }}, "swagger": "2.0", "info": { @@ -70,7 +70,6 @@ const docTemplate_swagger = `{ }, "/article/list": { "get": { - "description": "Admin can get not published article", "consumes": [ "application/json" ], @@ -81,12 +80,60 @@ const docTemplate_swagger = `{ "Article" ], "summary": "get all articles", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/utils.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.ListArticle" + } + } + } + } + ] + } + } + } + } + }, + "/article/list/{published}": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Article" + ], + "summary": "get user's articles", "parameters": [ { "type": "string", "description": "token", "name": "Token", "in": "header" + }, + { + "enum": [ + "published", + "notpublished" + ], + "type": "string", + "description": "string enums", + "name": "published", + "in": "path", + "required": true } ], "responses": { @@ -126,14 +173,8 @@ const docTemplate_swagger = `{ "tags": [ "Article" ], - "summary": "get all articles", + "summary": "get an articles", "parameters": [ - { - "type": "string", - "description": "token", - "name": "Token", - "in": "header" - }, { "type": "string", "description": "id", @@ -211,7 +252,7 @@ const docTemplate_swagger = `{ "tags": [ "Article" ], - "summary": "get all articles", + "summary": "publish an articles", "parameters": [ { "type": "string", @@ -506,6 +547,34 @@ const docTemplate_swagger = `{ } } }, + "/user/code/{email}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "send verify code", + "parameters": [ + { + "type": "string", + "description": "email", + "name": "email", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/utils.GinResponse" + } + } + } + } + }, "/user/code/{email}/{code}": { "get": { "produces": [ @@ -601,13 +670,25 @@ const docTemplate_swagger = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/utils.GinResponse" + "allOf": [ + { + "$ref": "#/definitions/utils.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/models.BackUser" + } + } + } + ] } } } } }, - "/user/registers": { + "/user/registers/{approved}": { "get": { "produces": [ "application/json" @@ -623,32 +704,15 @@ const docTemplate_swagger = `{ "name": "Token", "in": "header", "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/utils.GinResponse" - } - } - } - } - }, - "/user/{code}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "User" - ], - "summary": "send verify code", - "parameters": [ + }, { + "enum": [ + "approved", + "notapproved" + ], "type": "string", - "description": "email", - "name": "email", + "description": "string enums", + "name": "approved", "in": "path", "required": true } @@ -742,7 +806,7 @@ const docTemplate_swagger = `{ }, "createUser": { "description": "文章创建者id", - "type": "string" + "type": "integer" }, "isDelete": { "description": "删除标志", @@ -758,7 +822,7 @@ const docTemplate_swagger = `{ }, "modifyUser": { "description": "文章最后更新者id", - "type": "string" + "type": "integer" }, "resume": { "description": "文章简述", @@ -774,6 +838,58 @@ const docTemplate_swagger = `{ } } }, + "models.BackUser": { + "type": "object", + "properties": { + "approver": { + "description": "注册审核人ID", + "type": "integer" + }, + "aptitude": { + "description": "用户资质证明(图片URL)", + "type": "string" + }, + "createTime": { + "description": "用户注册时间", + "type": "string" + }, + "email": { + "description": "用户邮箱", + "type": "string" + }, + "id": { + "description": "用户ID", + "type": "integer" + }, + "isDelete": { + "description": "删除标志", + "type": "integer" + }, + "modifyTime": { + "type": "string" + }, + "password": { + "description": "用户密码", + "type": "string" + }, + "phone": { + "description": "用户手机号码", + "type": "string" + }, + "region": { + "description": "用户所属地域", + "type": "string" + }, + "role": { + "description": "用户角色", + "type": "integer" + }, + "username": { + "description": "用户真实姓名", + "type": "string" + } + } + }, "models.ChinaAdd": { "type": "object", "properties": { @@ -870,6 +986,32 @@ const docTemplate_swagger = `{ } } }, + "models.ListArticle": { + "type": "object", + "properties": { + "cover": { + "type": "string" + }, + "createTime": { + "type": "string" + }, + "modifyTime": { + "type": "string" + }, + "resume": { + "type": "string" + }, + "tags": { + "type": "string" + }, + "title": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, "models.UserApprove": { "type": "object", "properties": { @@ -921,6 +1063,12 @@ const docTemplate_swagger = `{ "phone": { "type": "string" }, + "region": { + "type": "string" + }, + "role": { + "type": "integer" + }, "username": { "type": "string" } @@ -939,8 +1087,8 @@ const docTemplate_swagger = `{ } }` -// SwaggerInfo_swagger holds exported Swagger Info so clients can modify it -var SwaggerInfo_swagger = &swag.Spec{ +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ Version: "1.0", Host: "", BasePath: "", @@ -948,9 +1096,9 @@ var SwaggerInfo_swagger = &swag.Spec{ Title: "nCov Tracker", Description: "", InfoInstanceName: "swagger", - SwaggerTemplate: docTemplate_swagger, + SwaggerTemplate: docTemplate, } func init() { - swag.Register(SwaggerInfo_swagger.InstanceName(), SwaggerInfo_swagger) + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) } diff --git a/docs/swagger.json b/docs/swagger.json index 620d5a3..37eb012 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -60,7 +60,6 @@ }, "/article/list": { "get": { - "description": "Admin can get not published article", "consumes": [ "application/json" ], @@ -71,12 +70,60 @@ "Article" ], "summary": "get all articles", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/utils.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.ListArticle" + } + } + } + } + ] + } + } + } + } + }, + "/article/list/{published}": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Article" + ], + "summary": "get user's articles", "parameters": [ { "type": "string", "description": "token", "name": "Token", "in": "header" + }, + { + "enum": [ + "published", + "notpublished" + ], + "type": "string", + "description": "string enums", + "name": "published", + "in": "path", + "required": true } ], "responses": { @@ -116,14 +163,8 @@ "tags": [ "Article" ], - "summary": "get all articles", + "summary": "get an articles", "parameters": [ - { - "type": "string", - "description": "token", - "name": "Token", - "in": "header" - }, { "type": "string", "description": "id", @@ -201,7 +242,7 @@ "tags": [ "Article" ], - "summary": "get all articles", + "summary": "publish an articles", "parameters": [ { "type": "string", @@ -496,6 +537,34 @@ } } }, + "/user/code/{email}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "send verify code", + "parameters": [ + { + "type": "string", + "description": "email", + "name": "email", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/utils.GinResponse" + } + } + } + } + }, "/user/code/{email}/{code}": { "get": { "produces": [ @@ -591,13 +660,25 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/utils.GinResponse" + "allOf": [ + { + "$ref": "#/definitions/utils.GinResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/models.BackUser" + } + } + } + ] } } } } }, - "/user/registers": { + "/user/registers/{approved}": { "get": { "produces": [ "application/json" @@ -613,32 +694,15 @@ "name": "Token", "in": "header", "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/utils.GinResponse" - } - } - } - } - }, - "/user/{code}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "User" - ], - "summary": "send verify code", - "parameters": [ + }, { + "enum": [ + "approved", + "notapproved" + ], "type": "string", - "description": "email", - "name": "email", + "description": "string enums", + "name": "approved", "in": "path", "required": true } @@ -732,7 +796,7 @@ }, "createUser": { "description": "文章创建者id", - "type": "string" + "type": "integer" }, "isDelete": { "description": "删除标志", @@ -748,7 +812,7 @@ }, "modifyUser": { "description": "文章最后更新者id", - "type": "string" + "type": "integer" }, "resume": { "description": "文章简述", @@ -764,6 +828,58 @@ } } }, + "models.BackUser": { + "type": "object", + "properties": { + "approver": { + "description": "注册审核人ID", + "type": "integer" + }, + "aptitude": { + "description": "用户资质证明(图片URL)", + "type": "string" + }, + "createTime": { + "description": "用户注册时间", + "type": "string" + }, + "email": { + "description": "用户邮箱", + "type": "string" + }, + "id": { + "description": "用户ID", + "type": "integer" + }, + "isDelete": { + "description": "删除标志", + "type": "integer" + }, + "modifyTime": { + "type": "string" + }, + "password": { + "description": "用户密码", + "type": "string" + }, + "phone": { + "description": "用户手机号码", + "type": "string" + }, + "region": { + "description": "用户所属地域", + "type": "string" + }, + "role": { + "description": "用户角色", + "type": "integer" + }, + "username": { + "description": "用户真实姓名", + "type": "string" + } + } + }, "models.ChinaAdd": { "type": "object", "properties": { @@ -860,6 +976,32 @@ } } }, + "models.ListArticle": { + "type": "object", + "properties": { + "cover": { + "type": "string" + }, + "createTime": { + "type": "string" + }, + "modifyTime": { + "type": "string" + }, + "resume": { + "type": "string" + }, + "tags": { + "type": "string" + }, + "title": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, "models.UserApprove": { "type": "object", "properties": { @@ -911,6 +1053,12 @@ "phone": { "type": "string" }, + "region": { + "type": "string" + }, + "role": { + "type": "integer" + }, "username": { "type": "string" } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index fd7c92e..4d46eb2 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -51,7 +51,7 @@ definitions: type: string createUser: description: 文章创建者id - type: string + type: integer isDelete: description: 删除标志 type: integer @@ -63,7 +63,7 @@ definitions: type: string modifyUser: description: 文章最后更新者id - type: string + type: integer resume: description: 文章简述 type: string @@ -74,6 +74,44 @@ definitions: description: 文章标题 type: string type: object + models.BackUser: + properties: + approver: + description: 注册审核人ID + type: integer + aptitude: + description: 用户资质证明(图片URL) + type: string + createTime: + description: 用户注册时间 + type: string + email: + description: 用户邮箱 + type: string + id: + description: 用户ID + type: integer + isDelete: + description: 删除标志 + type: integer + modifyTime: + type: string + password: + description: 用户密码 + type: string + phone: + description: 用户手机号码 + type: string + region: + description: 用户所属地域 + type: string + role: + description: 用户角色 + type: integer + username: + description: 用户真实姓名 + type: string + type: object models.ChinaAdd: properties: confirm: @@ -137,6 +175,23 @@ definitions: suspect: type: integer type: object + models.ListArticle: + properties: + cover: + type: string + createTime: + type: string + modifyTime: + type: string + resume: + type: string + tags: + type: string + title: + type: string + username: + type: string + type: object models.UserApprove: properties: email: @@ -170,6 +225,10 @@ definitions: type: string phone: type: string + region: + type: string + role: + type: integer username: type: string type: object @@ -246,10 +305,6 @@ paths: - application/json description: Admin can get not published article parameters: - - description: token - in: header - name: Token - type: string - description: id in: path name: id @@ -267,7 +322,7 @@ paths: data: $ref: '#/definitions/models.BackArticle' type: object - summary: get all articles + summary: get an articles tags: - Article /article/{id}/publish: @@ -292,19 +347,47 @@ paths: description: OK schema: $ref: '#/definitions/utils.GinResponse' - summary: get all articles + summary: publish an articles tags: - Article /article/list: get: consumes: - application/json - description: Admin can get not published article + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/utils.GinResponse' + - properties: + data: + items: + $ref: '#/definitions/models.ListArticle' + type: array + type: object + summary: get all articles + tags: + - Article + /article/list/{published}: + get: + consumes: + - application/json parameters: - description: token in: header name: Token type: string + - description: string enums + enum: + - published + - notpublished + in: path + name: published + required: true + type: string produces: - application/json responses: @@ -319,7 +402,7 @@ paths: $ref: '#/definitions/models.BackArticle' type: array type: object - summary: get all articles + summary: get user's articles tags: - Article /statistics/china: @@ -435,24 +518,6 @@ paths: summary: province statistics tags: - Statistics - /user/{code}: - get: - parameters: - - description: email - in: path - name: email - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/utils.GinResponse' - summary: send verify code - tags: - - User /user/approve: post: consumes: @@ -500,6 +565,24 @@ paths: summary: change user's password tags: - User + /user/code/{email}: + get: + parameters: + - description: email + in: path + name: email + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/utils.GinResponse' + summary: send verify code + tags: + - User /user/code/{email}/{code}: get: parameters: @@ -561,11 +644,16 @@ paths: "200": description: OK schema: - $ref: '#/definitions/utils.GinResponse' + allOf: + - $ref: '#/definitions/utils.GinResponse' + - properties: + data: + $ref: '#/definitions/models.BackUser' + type: object summary: user register account tags: - User - /user/registers: + /user/registers/{approved}: get: parameters: - description: token @@ -573,6 +661,14 @@ paths: name: Token required: true type: string + - description: string enums + enum: + - approved + - notapproved + in: path + name: approved + required: true + type: string produces: - application/json responses: diff --git a/handler/article.go b/handler/article.go index e7e87e5..5306051 100644 --- a/handler/article.go +++ b/handler/article.go @@ -10,7 +10,7 @@ import ( "github.com/gin-gonic/gin" ) -// SaveArticleHandler save an article +//SaveArticleHandler save an article // @Tags Article // @Accept json // @Produce json @@ -38,21 +38,27 @@ func SaveArticleHandler(c *gin.Context) { utils.Succ(c, jsonMap) } -// ListPublishedArticlesHandler get all article +//ListPublishedArticlesHandler get all article // @Tags Article // @Accept json // @Produce json // @Summary get all articles -// @Description Admin can get not published article -// @Success 200 {object} utils.GinResponse{data=[]models.BackArticle} +// @Success 200 {object} utils.GinResponse{data=[]models.ListArticle} // @Router /article/list [get] -// @Param Token header string false "token" func ListPublishedArticlesHandler(c *gin.Context) { - // TODO: admin need to show more articles articles := article.ListPublishedArticles() utils.Succ(c, articles) } +//ListPublishedArticlesHandler get the user's article +// @Tags Article +// @Accept json +// @Produce json +// @Summary get user's articles +// @Success 200 {object} utils.GinResponse{data=[]models.BackArticle} +// @Router /article/list/{published} [get] +// @Param Token header string false "token" +// @Param published path string true "string enums" Enums(published, notpublished) func ListArticlesByUser(c *gin.Context) { published := c.Param("published") claims := utils.ClaimsFromHeader(c) @@ -72,7 +78,7 @@ func ListArticlesByUser(c *gin.Context) { utils.Succ(c, articles) } -// DeleteArticleHandler delete article +//DeleteArticleHandler delete article // @Tags Article // @Accept json // @Produce json @@ -99,15 +105,14 @@ func DeleteArticleHandler(c *gin.Context) { utils.Succ(c, nil) } -// GetArticleHandler get an article +//GetArticleHandler get an article // @Tags Article // @Accept json // @Produce json -// @Summary get all articles +// @Summary get an articles // @Description Admin can get not published article // @Success 200 {object} utils.GinResponse{data=models.BackArticle} // @Router /article/{id} [get] -// @Param Token header string false "token" // @Param id path string true "id" func GetArticleHandler(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) @@ -123,11 +128,11 @@ func GetArticleHandler(c *gin.Context) { utils.Succ(c, res) } -// PublishArticleHandler publish an article +//PublishArticleHandler publish an article // @Tags Article // @Accept json // @Produce json -// @Summary get all articles +// @Summary publish an articles // @Success 200 {object} utils.GinResponse{} // @Router /article/{id}/publish [post] // @Param Token header string true "token" diff --git a/handler/user.go b/handler/user.go index 36c53db..784851a 100644 --- a/handler/user.go +++ b/handler/user.go @@ -15,7 +15,7 @@ import ( // @Accept json // @Produce json // @Summary user register account -// @Success 200 {object} utils.GinResponse{} +// @Success 200 {object} utils.GinResponse{data=models.BackUser} // @Router /user/register [post] // @Param json body models.UserRegister true "json" func UserRegisterHandler(c *gin.Context) { @@ -72,7 +72,9 @@ func UserLoginHandler(c *gin.Context) { } token := user.Login(jsonMap) if token == "" { - // TODO: change to request error + // Login failed reasons as follow: + // 1. account or password incorrect + // 2. account apply not pass utils.Succ(c, map[string]interface{}{"msg": "failed"}) return } @@ -87,6 +89,7 @@ func UserLoginHandler(c *gin.Context) { // @Success 200 {object} utils.GinResponse{} // @Router /user/registers/{approved} [get] // @Param Token header string true "token" +// @Param approved path string true "string enums" Enums(approved, notapproved) func ListRegisterUserHandler(c *gin.Context) { approved := c.Param("approved") claims := utils.ClaimsFromHeader(c) @@ -111,7 +114,7 @@ func ListRegisterUserHandler(c *gin.Context) { // @Produce json // @Summary send verify code // @Success 200 {object} utils.GinResponse{} -// @Router /user/{code} [get] +// @Router /user/code/{email} [get] // @Param email path string true "email" func SendEmailCodeHandler(c *gin.Context) { email := c.Param("email") diff --git a/initialize/cron.go b/initialize/cron.go index f30fe5e..adff2a0 100644 --- a/initialize/cron.go +++ b/initialize/cron.go @@ -1,12 +1,14 @@ package initialize import ( + "nCovTrack-Backend/service/statistics" + "github.com/robfig/cron/v3" ) func initCron() { c := cron.New() //c.AddFunc("@every 10s", func() { global.Redis.Set("OK", time.Now().String(), time.Duration(10*time.Hour)) }) - //c.AddFunc("@every 10m", statistics.CacheNCov) + c.AddFunc("@every 10m", statistics.CacheNCov) c.Start() } diff --git a/initialize/swagger.go b/initialize/swagger.go index 54f7e27..37d0e49 100644 --- a/initialize/swagger.go +++ b/initialize/swagger.go @@ -9,6 +9,6 @@ import ( ) func initSwagger() { - docs.SwaggerInfo_swagger.BasePath = "/api" + global.ServerSettings.UrlPrefix + docs.SwaggerInfo.BasePath = "/api" + global.ServerSettings.UrlPrefix global.RootRouter.GET("/swagger/*any", swagger.WrapHandler(swaggerFile.Handler)) } diff --git a/service/article/article.go b/service/article/article.go index bbc1b30..0530e75 100644 --- a/service/article/article.go +++ b/service/article/article.go @@ -11,15 +11,17 @@ func ListPublishedArticles() *[]models.ListArticle { return listArticles(1, 0) } +//ListPublishedArticlesByUser list the user's published articles func ListPublishedArticlesByUser(id int) *[]models.ListArticle { return listArticles(1, id) } -//ListNotPublishedArticlesByUser list all articles(without not published) +//ListNotPublishedArticlesByUser list the user's not publish articles func ListNotPublishedArticlesByUser(id int) *[]models.ListArticle { return listArticles(0, id) } +//listArticles complex function need to directly use gorm func listArticles(isPublish int, createUser int) *[]models.ListArticle { queryStr := "back_article.is_delete = 0 AND is_publish = " + strconv.Itoa(isPublish) if createUser != 0 { diff --git a/service/user/user.go b/service/user/user.go index 6d99bf8..7015f49 100644 --- a/service/user/user.go +++ b/service/user/user.go @@ -64,9 +64,11 @@ func ListRegister(claims models.TokenClaims) *[]map[string]interface{} { if claims.Region == "" { // do nothing } else if !strings.Contains(claims.Region, " ") { + // Province Admin approve city admin tx.Where("approver = 0 AND is_delete = 0 AND region LIKE ? AND role = ?", claims.Region+" %", global.ROLE_ID_MAP["ADMIN"]) registers = *models.ListByOrm(tx) } else { + // City Admin approve workers and volunteers tx.Where("approver = 0 AND is_delete = 0 AND region = ? AND role in ?", claims.Region, []int{global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}) registers = *models.ListByOrm(tx) } @@ -85,6 +87,10 @@ func ListApprovedRegister(claims models.TokenClaims) *[]map[string]interface{} { func ApproveRegister(claims models.TokenClaims, email string, pass bool) bool { queryMap := []map[string]interface{}{{"email": email}} var approver int + // Approver field status: + // = 0: not approved + // > 0: approver id, and registe successful + // < 0: approver id, and registe failed if pass { approver = claims.ID } else {