diff --git a/handler/article.go b/handler/article.go index d12e6c2..adbe7f8 100644 --- a/handler/article.go +++ b/handler/article.go @@ -1,11 +1,13 @@ package handler import ( - "github.com/gin-gonic/gin" + "nCovTrack-Backend/global" "nCovTrack-Backend/models" "nCovTrack-Backend/service/article" "nCovTrack-Backend/utils" "strconv" + + "github.com/gin-gonic/gin" ) // SaveArticleHandler save an article @@ -19,7 +21,13 @@ import ( // @Param Token header string true "token" func SaveArticleHandler(c *gin.Context) { jsonMap := bindJson(c) + claims := utils.ClaimsFromHeader(c) + if claims.Role != global.ROLE_ID_MAP["ADMIN"] { + Forbidden(c) + return + } if jsonMap == nil { + RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI}) return } colMap := models.MapJ2c[models.BackArticle](jsonMap, true) @@ -30,7 +38,7 @@ func SaveArticleHandler(c *gin.Context) { utils.Succ(c, jsonMap) } -// GetAllArticlesHandler get all article +// ListPublishedArticlesHandler get all article // @Tags Article // @Accept json // @Produce json @@ -39,9 +47,28 @@ func SaveArticleHandler(c *gin.Context) { // @Success 200 {object} utils.GinResponse{data=[]models.BackArticle} // @Router /article/list [get] // @Param Token header string false "token" -func GetAllArticlesHandler(c *gin.Context) { +func ListPublishedArticlesHandler(c *gin.Context) { // TODO: admin need to show more articles - articles := article.ListAllArticles() + articles := article.ListPublishedArticles() + utils.Succ(c, articles) +} + +func ListArticlesByUser(c *gin.Context) { + published := c.Param("published") + claims := utils.ClaimsFromHeader(c) + if claims.Role != global.ROLE_ID_MAP["ADMIN"] { + Forbidden(c) + return + } + var articles *[]models.ListArtile + if published == "published" { + articles = article.ListPublishedArticlesByUser(claims.ID) + } else if published == "notpublished" { + articles = article.ListNotPublishedArticlesByUser(claims.ID) + } else { + UrlNotFound(c) + return + } utils.Succ(c, articles) } @@ -56,6 +83,11 @@ func GetAllArticlesHandler(c *gin.Context) { // @Param id path string true "id" func DeleteArticleHandler(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) + claims := utils.ClaimsFromHeader(c) + if claims.Role == global.ROLE_ID_MAP["ADMIN"] { + Forbidden(c) + return + } if err != nil { RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI}) return @@ -84,7 +116,6 @@ func GetArticleHandler(c *gin.Context) { return } res := article.GetArticleById(id) - //TODO: if not admin, will not show not published article if res == nil { DataNotFound(c, nil) return @@ -103,6 +134,11 @@ func GetArticleHandler(c *gin.Context) { // @Param id path string true "id" func PublishArticleHandler(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) + claims := utils.ClaimsFromHeader(c) + if claims.Role == global.ROLE_ID_MAP["ADMIN"] { + Forbidden(c) + return + } if err != nil { RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI}) return diff --git a/handler/errors.go b/handler/errors.go index 241bd7a..0fd5a71 100644 --- a/handler/errors.go +++ b/handler/errors.go @@ -12,6 +12,8 @@ const ( BAD_REQUEST = "Bad Request" DATA_NOT_FOUND = "Data not Found" STATUS_DATA_NOT_FOUND = 210 + FORBIDDENT = "FORBIDDENT" + PAGE_NOT_FOUND = "404 page not found" ) func RequestError(c *gin.Context, code int, data interface{}) { @@ -31,3 +33,10 @@ func ServerErr(c *gin.Context, msg interface{}) { func DataNotFound(c *gin.Context, data interface{}) { utils.Success(c, http.StatusOK, STATUS_DATA_NOT_FOUND, DATA_NOT_FOUND, data) } +func Forbidden(c *gin.Context) { + utils.Err(c, http.StatusForbidden, http.StatusForbidden, FORBIDDENT) +} + +func UrlNotFound(c *gin.Context) { + c.String(http.StatusNotFound, PAGE_NOT_FOUND) +} diff --git a/handler/user.go b/handler/user.go index 5c028ea..36c53db 100644 --- a/handler/user.go +++ b/handler/user.go @@ -1,11 +1,13 @@ package handler import ( - "github.com/gin-gonic/gin" + "nCovTrack-Backend/global" "nCovTrack-Backend/models" "nCovTrack-Backend/service/user" "nCovTrack-Backend/utils" "regexp" + + "github.com/gin-gonic/gin" ) //UserRegisterHandler user register @@ -39,12 +41,16 @@ func UserRegisterHandler(c *gin.Context) { // @Param Token header string true "token" // @Param json body models.UserApprove true "json" func UserApproveHandler(c *gin.Context) { - //TODO: auth user is admin or not + claims := utils.ClaimsFromHeader(c) + if claims.Role != global.ROLE_ID_MAP["ADMIN"] { + Forbidden(c) + return + } jsonMap := bindJsonStruct[models.UserApprove](c) if jsonMap == nil { return } - if !user.ApproveRegister(jsonMap["email"].(string), jsonMap["pass"].(bool)) { + if !user.ApproveRegister(claims, jsonMap["email"].(string), jsonMap["pass"].(bool)) { RequestErr(c, "approve failed") return } @@ -79,10 +85,24 @@ func UserLoginHandler(c *gin.Context) { // @Produce json // @Summary list register infos, which is to be approved // @Success 200 {object} utils.GinResponse{} -// @Router /user/registers [get] +// @Router /user/registers/{approved} [get] // @Param Token header string true "token" func ListRegisterUserHandler(c *gin.Context) { - registers := user.ListRegister() + approved := c.Param("approved") + claims := utils.ClaimsFromHeader(c) + if claims.Role != global.ROLE_ID_MAP["ADMIN"] { + Forbidden(c) + return + } + var registers *[]map[string]interface{} + if approved == "notapproved" { + registers = user.ListRegister(claims) + } else if approved == "approved" { + registers = user.ListApprovedRegister(claims) + } else { + UrlNotFound(c) + return + } utils.Succ(c, registers) } diff --git a/initialize/cron.go b/initialize/cron.go index adff2a0..f30fe5e 100644 --- a/initialize/cron.go +++ b/initialize/cron.go @@ -1,14 +1,12 @@ 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/middleware/auth.go b/middleware/auth.go index fd4d0a6..eb61c10 100644 --- a/middleware/auth.go +++ b/middleware/auth.go @@ -1,14 +1,16 @@ package middleware import ( - "fmt" - "github.com/gin-gonic/gin" - "github.com/golang-jwt/jwt/v4" + "encoding/json" "nCovTrack-Backend/global" + "nCovTrack-Backend/models" "nCovTrack-Backend/utils" "net/http" "strconv" "time" + + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" ) const UNAUTH_MSG = "unauthorized" @@ -24,10 +26,15 @@ func Auth() gin.HandlerFunc { } // Write the field of token to request header claims := utils.ParseClaims(oldToken[0]) - c.Request.Header.Set("role", fmt.Sprint(claims["role"])) - c.Request.Header.Set("email", claims["email"].(string)) - c.Request.Header.Set("id", fmt.Sprint(claims["id"])) - c.Request.Header.Set("role", claims["role"].(string)) + tokenClaims := models.TokenClaims{ + ID: int(claims["id"].(float64)), + Username: claims["username"].(string), + Email: claims["email"].(string), + Role: int(claims["role"].(float64)), + Region: claims["region"].(string), + } + claimsByte, _ := json.Marshal(tokenClaims) + c.Request.Header.Add("claims", string(claimsByte)) // renew token, and judge the token's iat is expired or not renewToken := utils.RenewToken(oldToken[0]) diff --git a/middleware/cors.go b/middleware/cors.go index f9c4f5c..289cb0a 100644 --- a/middleware/cors.go +++ b/middleware/cors.go @@ -13,7 +13,7 @@ func Cors() gin.HandlerFunc { c.Header("Access-Control-Allow-Origin", origin) c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id") c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT") - c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") + c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, X-Token, Access-Control-Allow-Headers, Content-Type") c.Header("Access-Control-Allow-Credentials", "true") if method == "OPTIONS" { diff --git a/models/article.go b/models/article.go index 01c3a6f..a903cf7 100644 --- a/models/article.go +++ b/models/article.go @@ -8,9 +8,9 @@ import ( type BackArticle struct { ID int `gorm:"primaryKey;column:id" json:"-"` // 文章id CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 文章新建时间 - CreateUser string `gorm:"column:create_user" json:"createUser"` // 文章创建者id + CreateUser int `gorm:"column:create_user" json:"createUser"` // 文章创建者id ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 文章最后更新时间 - ModifyUser string `gorm:"column:modify_user" json:"modifyUser"` // 文章最后更新者id + ModifyUser int `gorm:"column:modify_user" json:"modifyUser"` // 文章最后更新者id Title string `gorm:"column:title" json:"title"` // 文章标题 Tags string `gorm:"column:tags" json:"tags"` // 文章Tag Resume string `gorm:"column:resume" json:"resume"` // 文章简述 @@ -20,6 +20,17 @@ type BackArticle struct { IsDelete int8 `gorm:"column:is_delete" json:"isDelete"` // 删除标志 } +type ListArtile struct { + ID int `json:"-"` + Username string `json:"username"` + CreateTime time.Time `json:"createTime"` + ModifyTime time.Time `json:"modifyTime"` + Title string `json:"title"` + Tags string `json:"tags"` + Resume string `json:"resume"` + Cover string `json:"cover"` +} + func init() { initJcMap[BackArticle]() } diff --git a/models/investigate.go b/models/investigate.go index 87092ea..4f2df9d 100644 --- a/models/investigate.go +++ b/models/investigate.go @@ -41,3 +41,23 @@ type HotelContactRequest struct { InData FakerDate `json:"in_data"` OutData FakerDate `json:"out_data"` } + +type RailwayContactRequest struct { + Name string `json:"name"` + Age int `json:"age,string"` + Sex int `json:"sex,string"` + Phone int `json:"phone"` + Address string `json:"address"` + Train string `json:"train"` + Launch FakerDate `json:"launch"` + Identification string `json:"identification"` +} + +type PatientRequest struct { + Name string `json:"name"` + Age int `json:"age,string"` + Sex int `json:"sex,string"` + Phone string `json:"phone"` + Address string `json:"address"` + Identification string `json:"identification"` +} diff --git a/models/user.go b/models/user.go index ef34291..17f90ef 100644 --- a/models/user.go +++ b/models/user.go @@ -3,7 +3,7 @@ package models import "time" type BackUser struct { - ID int `gorm:"primaryKey;column:id" json:"-"` // 用户ID + ID int `gorm:"primaryKey;column:id" json:"id"` // 用户ID Username string `gorm:"column:username" json:"username"` // 用户真实姓名 Password string `gorm:"column:password" json:"password"` // 用户密码 Role int `gorm:"column:role" json:"role"` // 用户角色 @@ -14,6 +14,7 @@ type BackUser struct { Approver int `gorm:"column:approver" json:"approver"` // 注册审核人ID ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` IsDelete int8 `gorm:"column:is_delete" json:"isDelete"` // 删除标志 + Region string `gorm:"column:region" json:"region"` // 用户所属地域 } type UserLogin struct { @@ -27,6 +28,8 @@ type UserRegister struct { Email string `json:"email"` Phone string `json:"phone"` Aptitude string `json:"aptitude"` + Region string `json:"region"` + Role int `json:"role"` } type UserChangePwd struct { @@ -40,6 +43,14 @@ type UserApprove struct { Pass bool `json:"pass"` } +type TokenClaims struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Role int `json:"role"` + Region string `json:"region"` +} + func init() { initJcMap[BackUser]() } diff --git a/models/utils.go b/models/utils.go index bd54826..e953838 100644 --- a/models/utils.go +++ b/models/utils.go @@ -93,6 +93,24 @@ func Upsert[T any](colMap map[string]interface{}) (ok bool, rowsAffected int64) return true, tx.RowsAffected } +func Update[T any](queryMap []map[string]interface{}, updateMap map[string]interface{}) (ok bool, rowsAffected int64) { + tx := global.Db.Model(new(T)) + for _, e := range queryMap { + e[IS_DELETE] = 0 + tx = tx.Or(e) + } + return UpdateByOrm(tx, updateMap) +} + +func UpdateByOrm(tx *gorm.DB, updateMap map[string]interface{}) (ok bool, rowsAffected int64) { + tx.Updates(updateMap) + if tx.Error != nil { + fmt.Println(tx.Error) + return false, 0 + } + return true, tx.RowsAffected +} + // DeleteById will delete by id, not delete the record from database, only set the field "is_delete" as 1 func DeleteById[T any](id int) (ok bool, rowsAffected int64) { tx := global.Db.Model(new(T)).Where("id = ?", id).Update("is_delete", 1) diff --git a/router/article.go b/router/article.go index cb62379..589405f 100644 --- a/router/article.go +++ b/router/article.go @@ -10,6 +10,7 @@ func articlePrivateRouter(router *gin.RouterGroup) { { articleRouter.DELETE("/:id", handler.DeleteArticleHandler) articleRouter.POST("/:id/publish", handler.PublishArticleHandler) + articleRouter.GET("/list/:published", handler.ListArticlesByUser) } } @@ -17,7 +18,7 @@ func articlePublicRouter(router *gin.RouterGroup) { articleRouter := router.Group("/article") { articleRouter.POST("", handler.SaveArticleHandler) - articleRouter.GET("/list", handler.GetAllArticlesHandler) + articleRouter.GET("/list", handler.ListPublishedArticlesHandler) articleRouter.GET("/:id", handler.GetArticleHandler) } } diff --git a/router/user.go b/router/user.go index 63c03d7..2dea4e1 100644 --- a/router/user.go +++ b/router/user.go @@ -19,6 +19,6 @@ func userPrivateRouter(router *gin.RouterGroup) { userRouter := router.Group("/user") { userRouter.POST("/approve", handler.UserApproveHandler) - userRouter.GET("/registers", handler.ListRegisterUserHandler) + userRouter.GET("/registers/:approved", handler.ListRegisterUserHandler) } } diff --git a/service/article/article.go b/service/article/article.go index cda04bc..05bbe40 100644 --- a/service/article/article.go +++ b/service/article/article.go @@ -1,26 +1,40 @@ package article import ( + "nCovTrack-Backend/global" "nCovTrack-Backend/models" + "strconv" ) //ListPublishedArticles list the articles published, use to show the articles to all people -func ListPublishedArticles() *[]map[string]interface{} { - article := models.ListField[models.BackArticle]([]map[string]interface{}{{"is_publish": 0}}, true, "content") - if *article == nil { - article = &[]map[string]interface{}{} - } - return article +func ListPublishedArticles() *[]models.ListArtile { + return listArticles(1, 0) } -//ListAllArticles list all articles, will show the articles not published of the user +func ListPublishedArticlesByUser(id int) *[]models.ListArtile { + return listArticles(1, id) +} + +//ListAllArticles list all articles(without not published) // TODO: need only show the user's not published article -func ListAllArticles() *[]map[string]interface{} { - article := models.ListField[models.BackArticle]([]map[string]interface{}{{}}, true, "content") - if *article == nil { - article = &[]map[string]interface{}{} +func ListNotPublishedArticlesByUser(id int) *[]models.ListArtile { + return listArticles(0, id) +} + +func listArticles(isPublish int, createUser int) *[]models.ListArtile { + queryStr := "back_article.is_delete = 0 AND is_publish = " + strconv.Itoa(isPublish) + if createUser != 0 { + queryStr += " AND create_user = " + strconv.Itoa(createUser) } - return article + var res []models.ListArtile + global.Db.Table("back_article"). + Select("back_user.username, back_article.*"). + Joins("join back_user on back_article.create_user=back_user.id"). + Where(queryStr).Find(&res) + if res == nil { + res = []models.ListArtile{} + } + return &res } //SaveArticle save the articles diff --git a/service/investigate/faker.go b/service/investigate/faker.go index 32848d4..b51f816 100644 --- a/service/investigate/faker.go +++ b/service/investigate/faker.go @@ -2,7 +2,6 @@ package investigate import ( "encoding/json" - "fmt" "nCovTrack-Backend/global" "nCovTrack-Backend/models" "nCovTrack-Backend/utils" @@ -16,12 +15,32 @@ func fakerGetRequest(uri string) string { return string(dataStr) } -func QueryHotelContacts() { +func QueryHotelContacts() []models.HotelContactRequest { dataStr := fakerGetRequest("query/contacts/hotel/320581199103182689") var data []models.HotelContactRequest err := json.Unmarshal([]byte(dataStr), &data) if err != nil { panic(err) } - fmt.Println(data) + return data +} + +func QueryRailwayContacts() []models.RailwayContactRequest { + dataStr := fakerGetRequest("query/contacts/railway/320581199103182689") + var data []models.RailwayContactRequest + err := json.Unmarshal([]byte(dataStr), &data) + if err != nil { + panic(err) + } + return data +} + +func QueryPatients() []models.PatientRequest { + dataStr := fakerGetRequest("query/contacts/railway/320581199103182689") + var data []models.PatientRequest + err := json.Unmarshal([]byte(dataStr), &data) + if err != nil { + panic(err) + } + return data } diff --git a/service/statistics/cache.go b/service/statistics/cache.go index f730665..3537ff0 100644 --- a/service/statistics/cache.go +++ b/service/statistics/cache.go @@ -48,7 +48,10 @@ func cacheNCovStatistics() { var nCovRes map[string]string json.Unmarshal([]byte(resp), &nCovRes) var nCovResData map[string]interface{} - json.Unmarshal([]byte(nCovRes["data"]), &nCovResData) + err := json.Unmarshal([]byte(nCovRes["data"]), &nCovResData) + if err != nil { + panic(err) + } if !needToRecache(nCovResData) { return } diff --git a/service/statistics/statistics.go b/service/statistics/statistics.go index 1563d11..c77a99a 100644 --- a/service/statistics/statistics.go +++ b/service/statistics/statistics.go @@ -36,6 +36,7 @@ func GetAllCityData(sort string) []interface{} { } func GetCountryData(child bool) []interface{} { + checkCache() if child { return getEntireRedisList(rds_COUNTRY_LEVEL_CHILD_KEY) } @@ -43,6 +44,7 @@ func GetCountryData(child bool) []interface{} { } func GetChinaNCovStatistic() models.ChinaData { + checkCache() data := models.ChinaData{} json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_ADD_KEY).Val()), &data.ChinaAdd) json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_TOTAL_KEY).Val()), &data.ChinaTotal) diff --git a/service/user/user.go b/service/user/user.go index a091a0b..6d99bf8 100644 --- a/service/user/user.go +++ b/service/user/user.go @@ -1,7 +1,6 @@ package user import ( - "encoding/json" "fmt" "github.com/golang-jwt/jwt/v4" "github.com/google/uuid" @@ -18,6 +17,7 @@ const ( // Login if login success, will return token func Login(user map[string]interface{}) (token string) { + // TODO: need to detect is passed or not account := user["account"].(string) var queryMap []map[string]interface{} if strings.Contains(account, "@") { @@ -29,64 +29,73 @@ func Login(user map[string]interface{}) (token string) { if userInfo == nil { return "" } + if userInfo["approver"].(int) <= 0 { + return "" + } if !utils.PasswordCompare(user["password"].(string), userInfo["password"].(string)) { return "" } claims := jwt.MapClaims{ "id": userInfo["id"], "username": userInfo["username"], - "role": userInfo["role"], "email": userInfo["email"], + "region": userInfo["region"], + "role": userInfo["role"], } return utils.GenerateToken(claims) } // Register user register, user can use account after approved -func Register(user map[string]interface{}) { +func Register(user map[string]interface{}) bool { user["password"] = utils.PasswordEncrypt(user["password"].(string)) - userStr, _ := json.Marshal(user) - // insert into redis, wait for approve - cmd := global.Redis.HMSet(global.REGISTER_REDIS_KEY, map[string]interface{}{user["email"].(string): userStr}) - if cmd.Err() != nil { - panic(cmd.Err()) + user["approver"] = 0 + colMap := models.MapJ2c[models.BackUser](user, false) + ok, rowsAffected := models.Upsert[models.BackUser](colMap) + if !ok || rowsAffected == 0 { + return false } + return true } // ListRegister list the registers in the redis to be approved -func ListRegister() *[]map[string]interface{} { - applyStrMap := global.Redis.HGetAll(global.REGISTER_REDIS_KEY).Val() - var applies []map[string]interface{} - for _, v := range applyStrMap { - var apply map[string]interface{} - _ = json.Unmarshal([]byte(v), &apply) - applies = append(applies, apply) +func ListRegister(claims models.TokenClaims) *[]map[string]interface{} { + registers := []map[string]interface{}{} + tx := global.Db.Model(new(models.BackUser)).Omit("password") + if claims.Region == "" { + // do nothing + } else if !strings.Contains(claims.Region, " ") { + 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 { + 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) } - if applies == nil { - applies = []map[string]interface{}{} - } - return &applies + return ®isters +} + +// ListApprovedRegister list registers approved by the admin +func ListApprovedRegister(claims models.TokenClaims) *[]map[string]interface{} { + approvedRegisters := []map[string]interface{}{} + tx := global.Db.Model(new(models.BackUser)).Omit("password").Where("approver in ? and is_delete = 0", []int{claims.ID, -claims.ID}) + approvedRegisters = *models.ListByOrm(tx) + return &approvedRegisters } // ApproveRegister approve a register -func ApproveRegister(email string, pass bool) bool { - if !pass { - rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val() - return rowsAffected != 0 +func ApproveRegister(claims models.TokenClaims, email string, pass bool) bool { + queryMap := []map[string]interface{}{{"email": email}} + var approver int + if pass { + approver = claims.ID + } else { + approver = -claims.ID } - // if pass, will get the register info from redis, and the insert into mysql, this mean user is register success - applyStr := global.Redis.HGet(global.REGISTER_REDIS_KEY, email).Val() - rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val() - if rowsAffected == 0 { + updateMap := map[string]interface{}{"approver": approver} + ok, rowsAffected := models.Update[models.BackUser](queryMap, updateMap) + if !ok || rowsAffected == 0 { return false } - var apply map[string]interface{} - _ = json.Unmarshal([]byte(applyStr), &apply) - if !NoDuplicatePhoneOrEmail(apply["phone"].(string), apply["email"].(string)) { - return false - } - colMap := models.MapJ2c[models.BackUser](apply, true) - ok, rowsAffected := models.Upsert[models.BackUser](colMap) - return ok && rowsAffected != 0 + return true } // ChangePassword user change password, or user forgot password diff --git a/utils/json.go b/utils/json.go new file mode 100644 index 0000000..83578fc --- /dev/null +++ b/utils/json.go @@ -0,0 +1,10 @@ +package utils + +import ( + "encoding/json" +) + +func Strcut2Map[S any, T *map[string]interface{} | *[]map[string]interface{}](source S, target T) { + jsonByte, _ := json.Marshal(source) + json.Unmarshal(jsonByte, target) +} diff --git a/utils/jwt.go b/utils/jwt.go index 2ba1971..ea149de 100644 --- a/utils/jwt.go +++ b/utils/jwt.go @@ -1,10 +1,13 @@ package utils import ( + "encoding/json" "fmt" "nCovTrack-Backend/global" + "nCovTrack-Backend/models" "time" + "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v4" ) @@ -81,3 +84,9 @@ func ParseClaims(tokenStr string) jwt.MapClaims { } return token.Claims.(jwt.MapClaims) } + +func ClaimsFromHeader(c *gin.Context) models.TokenClaims { + var claims models.TokenClaims + json.Unmarshal([]byte(c.Request.Header.Get("claims")), &claims) + return claims +}