fix: add role limit
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"nCovTrack-Backend/global"
|
||||||
"nCovTrack-Backend/models"
|
"nCovTrack-Backend/models"
|
||||||
"nCovTrack-Backend/service/article"
|
"nCovTrack-Backend/service/article"
|
||||||
"nCovTrack-Backend/utils"
|
"nCovTrack-Backend/utils"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SaveArticleHandler save an article
|
// SaveArticleHandler save an article
|
||||||
@@ -19,7 +21,13 @@ import (
|
|||||||
// @Param Token header string true "token"
|
// @Param Token header string true "token"
|
||||||
func SaveArticleHandler(c *gin.Context) {
|
func SaveArticleHandler(c *gin.Context) {
|
||||||
jsonMap := bindJson(c)
|
jsonMap := bindJson(c)
|
||||||
|
claims := utils.ClaimsFromHeader(c)
|
||||||
|
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||||
|
Forbidden(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
if jsonMap == nil {
|
if jsonMap == nil {
|
||||||
|
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
colMap := models.MapJ2c[models.BackArticle](jsonMap, true)
|
colMap := models.MapJ2c[models.BackArticle](jsonMap, true)
|
||||||
@@ -30,7 +38,7 @@ func SaveArticleHandler(c *gin.Context) {
|
|||||||
utils.Succ(c, jsonMap)
|
utils.Succ(c, jsonMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllArticlesHandler get all article
|
// ListPublishedArticlesHandler get all article
|
||||||
// @Tags Article
|
// @Tags Article
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
@@ -39,9 +47,28 @@ func SaveArticleHandler(c *gin.Context) {
|
|||||||
// @Success 200 {object} utils.GinResponse{data=[]models.BackArticle}
|
// @Success 200 {object} utils.GinResponse{data=[]models.BackArticle}
|
||||||
// @Router /article/list [get]
|
// @Router /article/list [get]
|
||||||
// @Param Token header string false "token"
|
// @Param Token header string false "token"
|
||||||
func GetAllArticlesHandler(c *gin.Context) {
|
func ListPublishedArticlesHandler(c *gin.Context) {
|
||||||
// TODO: admin need to show more articles
|
// 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)
|
utils.Succ(c, articles)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +83,11 @@ func GetAllArticlesHandler(c *gin.Context) {
|
|||||||
// @Param id path string true "id"
|
// @Param id path string true "id"
|
||||||
func DeleteArticleHandler(c *gin.Context) {
|
func DeleteArticleHandler(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
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 {
|
if err != nil {
|
||||||
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
||||||
return
|
return
|
||||||
@@ -84,7 +116,6 @@ func GetArticleHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
res := article.GetArticleById(id)
|
res := article.GetArticleById(id)
|
||||||
//TODO: if not admin, will not show not published article
|
|
||||||
if res == nil {
|
if res == nil {
|
||||||
DataNotFound(c, nil)
|
DataNotFound(c, nil)
|
||||||
return
|
return
|
||||||
@@ -103,6 +134,11 @@ func GetArticleHandler(c *gin.Context) {
|
|||||||
// @Param id path string true "id"
|
// @Param id path string true "id"
|
||||||
func PublishArticleHandler(c *gin.Context) {
|
func PublishArticleHandler(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
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 {
|
if err != nil {
|
||||||
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ const (
|
|||||||
BAD_REQUEST = "Bad Request"
|
BAD_REQUEST = "Bad Request"
|
||||||
DATA_NOT_FOUND = "Data not Found"
|
DATA_NOT_FOUND = "Data not Found"
|
||||||
STATUS_DATA_NOT_FOUND = 210
|
STATUS_DATA_NOT_FOUND = 210
|
||||||
|
FORBIDDENT = "FORBIDDENT"
|
||||||
|
PAGE_NOT_FOUND = "404 page not found"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RequestError(c *gin.Context, code int, data interface{}) {
|
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{}) {
|
func DataNotFound(c *gin.Context, data interface{}) {
|
||||||
utils.Success(c, http.StatusOK, STATUS_DATA_NOT_FOUND, DATA_NOT_FOUND, data)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"nCovTrack-Backend/global"
|
||||||
"nCovTrack-Backend/models"
|
"nCovTrack-Backend/models"
|
||||||
"nCovTrack-Backend/service/user"
|
"nCovTrack-Backend/service/user"
|
||||||
"nCovTrack-Backend/utils"
|
"nCovTrack-Backend/utils"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
//UserRegisterHandler user register
|
//UserRegisterHandler user register
|
||||||
@@ -39,12 +41,16 @@ func UserRegisterHandler(c *gin.Context) {
|
|||||||
// @Param Token header string true "token"
|
// @Param Token header string true "token"
|
||||||
// @Param json body models.UserApprove true "json"
|
// @Param json body models.UserApprove true "json"
|
||||||
func UserApproveHandler(c *gin.Context) {
|
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)
|
jsonMap := bindJsonStruct[models.UserApprove](c)
|
||||||
if jsonMap == nil {
|
if jsonMap == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !user.ApproveRegister(jsonMap["email"].(string), jsonMap["pass"].(bool)) {
|
if !user.ApproveRegister(claims, jsonMap["email"].(string), jsonMap["pass"].(bool)) {
|
||||||
RequestErr(c, "approve failed")
|
RequestErr(c, "approve failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -79,10 +85,24 @@ func UserLoginHandler(c *gin.Context) {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Summary list register infos, which is to be approved
|
// @Summary list register infos, which is to be approved
|
||||||
// @Success 200 {object} utils.GinResponse{}
|
// @Success 200 {object} utils.GinResponse{}
|
||||||
// @Router /user/registers [get]
|
// @Router /user/registers/{approved} [get]
|
||||||
// @Param Token header string true "token"
|
// @Param Token header string true "token"
|
||||||
func ListRegisterUserHandler(c *gin.Context) {
|
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)
|
utils.Succ(c, registers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
package initialize
|
package initialize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"nCovTrack-Backend/service/statistics"
|
|
||||||
|
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initCron() {
|
func initCron() {
|
||||||
c := cron.New()
|
c := cron.New()
|
||||||
//c.AddFunc("@every 10s", func() { global.Redis.Set("OK", time.Now().String(), time.Duration(10*time.Hour)) })
|
//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()
|
c.Start()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
|
||||||
"nCovTrack-Backend/global"
|
"nCovTrack-Backend/global"
|
||||||
|
"nCovTrack-Backend/models"
|
||||||
"nCovTrack-Backend/utils"
|
"nCovTrack-Backend/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
const UNAUTH_MSG = "unauthorized"
|
const UNAUTH_MSG = "unauthorized"
|
||||||
@@ -24,10 +26,15 @@ func Auth() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
// Write the field of token to request header
|
// Write the field of token to request header
|
||||||
claims := utils.ParseClaims(oldToken[0])
|
claims := utils.ParseClaims(oldToken[0])
|
||||||
c.Request.Header.Set("role", fmt.Sprint(claims["role"]))
|
tokenClaims := models.TokenClaims{
|
||||||
c.Request.Header.Set("email", claims["email"].(string))
|
ID: int(claims["id"].(float64)),
|
||||||
c.Request.Header.Set("id", fmt.Sprint(claims["id"]))
|
Username: claims["username"].(string),
|
||||||
c.Request.Header.Set("role", claims["role"].(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
|
// renew token, and judge the token's iat is expired or not
|
||||||
renewToken := utils.RenewToken(oldToken[0])
|
renewToken := utils.RenewToken(oldToken[0])
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func Cors() gin.HandlerFunc {
|
|||||||
c.Header("Access-Control-Allow-Origin", origin)
|
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-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-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")
|
c.Header("Access-Control-Allow-Credentials", "true")
|
||||||
|
|
||||||
if method == "OPTIONS" {
|
if method == "OPTIONS" {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
type BackArticle struct {
|
type BackArticle struct {
|
||||||
ID int `gorm:"primaryKey;column:id" json:"-"` // 文章id
|
ID int `gorm:"primaryKey;column:id" json:"-"` // 文章id
|
||||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 文章新建时间
|
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"` // 文章最后更新时间
|
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"` // 文章标题
|
Title string `gorm:"column:title" json:"title"` // 文章标题
|
||||||
Tags string `gorm:"column:tags" json:"tags"` // 文章Tag
|
Tags string `gorm:"column:tags" json:"tags"` // 文章Tag
|
||||||
Resume string `gorm:"column:resume" json:"resume"` // 文章简述
|
Resume string `gorm:"column:resume" json:"resume"` // 文章简述
|
||||||
@@ -20,6 +20,17 @@ type BackArticle struct {
|
|||||||
IsDelete int8 `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
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() {
|
func init() {
|
||||||
initJcMap[BackArticle]()
|
initJcMap[BackArticle]()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,3 +41,23 @@ type HotelContactRequest struct {
|
|||||||
InData FakerDate `json:"in_data"`
|
InData FakerDate `json:"in_data"`
|
||||||
OutData FakerDate `json:"out_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"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package models
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type BackUser struct {
|
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"` // 用户真实姓名
|
Username string `gorm:"column:username" json:"username"` // 用户真实姓名
|
||||||
Password string `gorm:"column:password" json:"password"` // 用户密码
|
Password string `gorm:"column:password" json:"password"` // 用户密码
|
||||||
Role int `gorm:"column:role" json:"role"` // 用户角色
|
Role int `gorm:"column:role" json:"role"` // 用户角色
|
||||||
@@ -14,6 +14,7 @@ type BackUser struct {
|
|||||||
Approver int `gorm:"column:approver" json:"approver"` // 注册审核人ID
|
Approver int `gorm:"column:approver" json:"approver"` // 注册审核人ID
|
||||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"`
|
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"`
|
||||||
IsDelete int8 `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
IsDelete int8 `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
||||||
|
Region string `gorm:"column:region" json:"region"` // 用户所属地域
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserLogin struct {
|
type UserLogin struct {
|
||||||
@@ -27,6 +28,8 @@ type UserRegister struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
Aptitude string `json:"aptitude"`
|
Aptitude string `json:"aptitude"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
Role int `json:"role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserChangePwd struct {
|
type UserChangePwd struct {
|
||||||
@@ -40,6 +43,14 @@ type UserApprove struct {
|
|||||||
Pass bool `json:"pass"`
|
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() {
|
func init() {
|
||||||
initJcMap[BackUser]()
|
initJcMap[BackUser]()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,24 @@ func Upsert[T any](colMap map[string]interface{}) (ok bool, rowsAffected int64)
|
|||||||
return true, tx.RowsAffected
|
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
|
// 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) {
|
func DeleteById[T any](id int) (ok bool, rowsAffected int64) {
|
||||||
tx := global.Db.Model(new(T)).Where("id = ?", id).Update("is_delete", 1)
|
tx := global.Db.Model(new(T)).Where("id = ?", id).Update("is_delete", 1)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ func articlePrivateRouter(router *gin.RouterGroup) {
|
|||||||
{
|
{
|
||||||
articleRouter.DELETE("/:id", handler.DeleteArticleHandler)
|
articleRouter.DELETE("/:id", handler.DeleteArticleHandler)
|
||||||
articleRouter.POST("/:id/publish", handler.PublishArticleHandler)
|
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 := router.Group("/article")
|
||||||
{
|
{
|
||||||
articleRouter.POST("", handler.SaveArticleHandler)
|
articleRouter.POST("", handler.SaveArticleHandler)
|
||||||
articleRouter.GET("/list", handler.GetAllArticlesHandler)
|
articleRouter.GET("/list", handler.ListPublishedArticlesHandler)
|
||||||
articleRouter.GET("/:id", handler.GetArticleHandler)
|
articleRouter.GET("/:id", handler.GetArticleHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,6 @@ func userPrivateRouter(router *gin.RouterGroup) {
|
|||||||
userRouter := router.Group("/user")
|
userRouter := router.Group("/user")
|
||||||
{
|
{
|
||||||
userRouter.POST("/approve", handler.UserApproveHandler)
|
userRouter.POST("/approve", handler.UserApproveHandler)
|
||||||
userRouter.GET("/registers", handler.ListRegisterUserHandler)
|
userRouter.GET("/registers/:approved", handler.ListRegisterUserHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,40 @@
|
|||||||
package article
|
package article
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"nCovTrack-Backend/global"
|
||||||
"nCovTrack-Backend/models"
|
"nCovTrack-Backend/models"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
//ListPublishedArticles list the articles published, use to show the articles to all people
|
//ListPublishedArticles list the articles published, use to show the articles to all people
|
||||||
func ListPublishedArticles() *[]map[string]interface{} {
|
func ListPublishedArticles() *[]models.ListArtile {
|
||||||
article := models.ListField[models.BackArticle]([]map[string]interface{}{{"is_publish": 0}}, true, "content")
|
return listArticles(1, 0)
|
||||||
if *article == nil {
|
|
||||||
article = &[]map[string]interface{}{}
|
|
||||||
}
|
|
||||||
return article
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ListAllArticles list all articles, will show the articles not published of the user
|
func ListPublishedArticlesByUser(id int) *[]models.ListArtile {
|
||||||
// TODO: need only show the user's not published article
|
return listArticles(1, id)
|
||||||
func ListAllArticles() *[]map[string]interface{} {
|
|
||||||
article := models.ListField[models.BackArticle]([]map[string]interface{}{{}}, true, "content")
|
|
||||||
if *article == nil {
|
|
||||||
article = &[]map[string]interface{}{}
|
|
||||||
}
|
}
|
||||||
return article
|
|
||||||
|
//ListAllArticles list all articles(without not published)
|
||||||
|
// TODO: need only show the user's not published article
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
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
|
//SaveArticle save the articles
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package investigate
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"nCovTrack-Backend/global"
|
"nCovTrack-Backend/global"
|
||||||
"nCovTrack-Backend/models"
|
"nCovTrack-Backend/models"
|
||||||
"nCovTrack-Backend/utils"
|
"nCovTrack-Backend/utils"
|
||||||
@@ -16,12 +15,32 @@ func fakerGetRequest(uri string) string {
|
|||||||
return string(dataStr)
|
return string(dataStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func QueryHotelContacts() {
|
func QueryHotelContacts() []models.HotelContactRequest {
|
||||||
dataStr := fakerGetRequest("query/contacts/hotel/320581199103182689")
|
dataStr := fakerGetRequest("query/contacts/hotel/320581199103182689")
|
||||||
var data []models.HotelContactRequest
|
var data []models.HotelContactRequest
|
||||||
err := json.Unmarshal([]byte(dataStr), &data)
|
err := json.Unmarshal([]byte(dataStr), &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,10 @@ func cacheNCovStatistics() {
|
|||||||
var nCovRes map[string]string
|
var nCovRes map[string]string
|
||||||
json.Unmarshal([]byte(resp), &nCovRes)
|
json.Unmarshal([]byte(resp), &nCovRes)
|
||||||
var nCovResData map[string]interface{}
|
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) {
|
if !needToRecache(nCovResData) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ func GetAllCityData(sort string) []interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetCountryData(child bool) []interface{} {
|
func GetCountryData(child bool) []interface{} {
|
||||||
|
checkCache()
|
||||||
if child {
|
if child {
|
||||||
return getEntireRedisList(rds_COUNTRY_LEVEL_CHILD_KEY)
|
return getEntireRedisList(rds_COUNTRY_LEVEL_CHILD_KEY)
|
||||||
}
|
}
|
||||||
@@ -43,6 +44,7 @@ func GetCountryData(child bool) []interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetChinaNCovStatistic() models.ChinaData {
|
func GetChinaNCovStatistic() models.ChinaData {
|
||||||
|
checkCache()
|
||||||
data := models.ChinaData{}
|
data := models.ChinaData{}
|
||||||
json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_ADD_KEY).Val()), &data.ChinaAdd)
|
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)
|
json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_TOTAL_KEY).Val()), &data.ChinaTotal)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@@ -18,6 +17,7 @@ const (
|
|||||||
|
|
||||||
// Login if login success, will return token
|
// Login if login success, will return token
|
||||||
func Login(user map[string]interface{}) (token string) {
|
func Login(user map[string]interface{}) (token string) {
|
||||||
|
// TODO: need to detect is passed or not
|
||||||
account := user["account"].(string)
|
account := user["account"].(string)
|
||||||
var queryMap []map[string]interface{}
|
var queryMap []map[string]interface{}
|
||||||
if strings.Contains(account, "@") {
|
if strings.Contains(account, "@") {
|
||||||
@@ -29,64 +29,73 @@ func Login(user map[string]interface{}) (token string) {
|
|||||||
if userInfo == nil {
|
if userInfo == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
if userInfo["approver"].(int) <= 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
if !utils.PasswordCompare(user["password"].(string), userInfo["password"].(string)) {
|
if !utils.PasswordCompare(user["password"].(string), userInfo["password"].(string)) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
claims := jwt.MapClaims{
|
claims := jwt.MapClaims{
|
||||||
"id": userInfo["id"],
|
"id": userInfo["id"],
|
||||||
"username": userInfo["username"],
|
"username": userInfo["username"],
|
||||||
"role": userInfo["role"],
|
|
||||||
"email": userInfo["email"],
|
"email": userInfo["email"],
|
||||||
|
"region": userInfo["region"],
|
||||||
|
"role": userInfo["role"],
|
||||||
}
|
}
|
||||||
return utils.GenerateToken(claims)
|
return utils.GenerateToken(claims)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register user register, user can use account after approved
|
// 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))
|
user["password"] = utils.PasswordEncrypt(user["password"].(string))
|
||||||
userStr, _ := json.Marshal(user)
|
user["approver"] = 0
|
||||||
// insert into redis, wait for approve
|
colMap := models.MapJ2c[models.BackUser](user, false)
|
||||||
cmd := global.Redis.HMSet(global.REGISTER_REDIS_KEY, map[string]interface{}{user["email"].(string): userStr})
|
ok, rowsAffected := models.Upsert[models.BackUser](colMap)
|
||||||
if cmd.Err() != nil {
|
if !ok || rowsAffected == 0 {
|
||||||
panic(cmd.Err())
|
return false
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListRegister list the registers in the redis to be approved
|
// ListRegister list the registers in the redis to be approved
|
||||||
func ListRegister() *[]map[string]interface{} {
|
func ListRegister(claims models.TokenClaims) *[]map[string]interface{} {
|
||||||
applyStrMap := global.Redis.HGetAll(global.REGISTER_REDIS_KEY).Val()
|
registers := []map[string]interface{}{}
|
||||||
var applies []map[string]interface{}
|
tx := global.Db.Model(new(models.BackUser)).Omit("password")
|
||||||
for _, v := range applyStrMap {
|
if claims.Region == "" {
|
||||||
var apply map[string]interface{}
|
// do nothing
|
||||||
_ = json.Unmarshal([]byte(v), &apply)
|
} else if !strings.Contains(claims.Region, " ") {
|
||||||
applies = append(applies, apply)
|
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 {
|
return ®isters
|
||||||
applies = []map[string]interface{}{}
|
|
||||||
}
|
}
|
||||||
return &applies
|
|
||||||
|
// 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
|
// ApproveRegister approve a register
|
||||||
func ApproveRegister(email string, pass bool) bool {
|
func ApproveRegister(claims models.TokenClaims, email string, pass bool) bool {
|
||||||
if !pass {
|
queryMap := []map[string]interface{}{{"email": email}}
|
||||||
rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val()
|
var approver int
|
||||||
return rowsAffected != 0
|
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
|
updateMap := map[string]interface{}{"approver": approver}
|
||||||
applyStr := global.Redis.HGet(global.REGISTER_REDIS_KEY, email).Val()
|
ok, rowsAffected := models.Update[models.BackUser](queryMap, updateMap)
|
||||||
rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val()
|
if !ok || rowsAffected == 0 {
|
||||||
if rowsAffected == 0 {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var apply map[string]interface{}
|
return true
|
||||||
_ = 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangePassword user change password, or user forgot password
|
// ChangePassword user change password, or user forgot password
|
||||||
|
|||||||
10
utils/json.go
Normal file
10
utils/json.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"nCovTrack-Backend/global"
|
"nCovTrack-Backend/global"
|
||||||
|
"nCovTrack-Backend/models"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -81,3 +84,9 @@ func ParseClaims(tokenStr string) jwt.MapClaims {
|
|||||||
}
|
}
|
||||||
return token.Claims.(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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user