diff --git a/cmd/answer/wire_gen.go b/cmd/answer/wire_gen.go index 515efa46..807fd0ef 100644 --- a/cmd/answer/wire_gen.go +++ b/cmd/answer/wire_gen.go @@ -166,7 +166,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, questionActivityRepo) questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, revisionService, metaService, collectionCommon, answerActivityService, dataData) questionController := controller.NewQuestionController(questionService, rankService) - answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService) + answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService) dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData) answerController := controller.NewAnswerController(answerService, rankService, dashboardService) searchParser := search_parser.NewSearchParser(tagCommonService, userCommon) diff --git a/docs/docs.go b/docs/docs.go index 9f73acfa..b9186b54 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -5592,7 +5592,8 @@ const docTemplate = `{ }, "original_text": { "description": "original text", - "type": "string" + "type": "string", + "maxLength": 65536 }, "slug_name": { "description": "slug_name", @@ -5993,14 +5994,6 @@ const docTemplate = `{ "description": "user id", "type": "string" }, - "ip_info": { - "description": "ip info", - "type": "string" - }, - "is_admin": { - "description": "is admin", - "type": "boolean" - }, "last_login_date": { "description": "last login date", "type": "integer" @@ -6484,10 +6477,6 @@ const docTemplate = `{ "description": "ip info", "type": "string" }, - "is_admin": { - "description": "is admin", - "type": "boolean" - }, "language": { "description": "language", "type": "string" @@ -6520,6 +6509,10 @@ const docTemplate = `{ "description": "rank", "type": "integer" }, + "role_id": { + "description": "role id", + "type": "integer" + }, "status": { "description": "user status", "type": "string" @@ -6584,10 +6577,6 @@ const docTemplate = `{ "description": "ip info", "type": "string" }, - "is_admin": { - "description": "is admin", - "type": "boolean" - }, "language": { "description": "language", "type": "string" @@ -6620,6 +6609,10 @@ const docTemplate = `{ "description": "rank", "type": "integer" }, + "role_id": { + "description": "role id", + "type": "integer" + }, "status": { "description": "user status", "type": "string" diff --git a/docs/swagger.json b/docs/swagger.json index 3ebb716e..00170a0a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -5580,7 +5580,8 @@ }, "original_text": { "description": "original text", - "type": "string" + "type": "string", + "maxLength": 65536 }, "slug_name": { "description": "slug_name", @@ -5981,14 +5982,6 @@ "description": "user id", "type": "string" }, - "ip_info": { - "description": "ip info", - "type": "string" - }, - "is_admin": { - "description": "is admin", - "type": "boolean" - }, "last_login_date": { "description": "last login date", "type": "integer" @@ -6472,10 +6465,6 @@ "description": "ip info", "type": "string" }, - "is_admin": { - "description": "is admin", - "type": "boolean" - }, "language": { "description": "language", "type": "string" @@ -6508,6 +6497,10 @@ "description": "rank", "type": "integer" }, + "role_id": { + "description": "role id", + "type": "integer" + }, "status": { "description": "user status", "type": "string" @@ -6572,10 +6565,6 @@ "description": "ip info", "type": "string" }, - "is_admin": { - "description": "is admin", - "type": "boolean" - }, "language": { "description": "language", "type": "string" @@ -6608,6 +6597,10 @@ "description": "rank", "type": "integer" }, + "role_id": { + "description": "role id", + "type": "integer" + }, "status": { "description": "user status", "type": "string" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index e0561059..b64361ca 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -182,6 +182,7 @@ definitions: type: string original_text: description: original text + maxLength: 65536 type: string slug_name: description: slug_name @@ -472,12 +473,6 @@ definitions: id: description: user id type: string - ip_info: - description: ip info - type: string - is_admin: - description: is admin - type: boolean last_login_date: description: last login date type: integer @@ -824,9 +819,6 @@ definitions: ip_info: description: ip info type: string - is_admin: - description: is admin - type: boolean language: description: language type: string @@ -851,6 +843,9 @@ definitions: rank: description: rank type: integer + role_id: + description: role id + type: integer status: description: user status type: string @@ -898,9 +893,6 @@ definitions: ip_info: description: ip info type: string - is_admin: - description: is admin - type: boolean language: description: language type: string @@ -925,6 +917,9 @@ definitions: rank: description: rank type: integer + role_id: + description: role id + type: integer status: description: user status type: string diff --git a/internal/base/middleware/auth.go b/internal/base/middleware/auth.go index a7796c87..b2150e38 100644 --- a/internal/base/middleware/auth.go +++ b/internal/base/middleware/auth.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/answerdev/answer/internal/schema" + "github.com/answerdev/answer/internal/service/role" "github.com/answerdev/answer/internal/service/siteinfo_common" "github.com/answerdev/answer/internal/base/handler" @@ -154,7 +155,7 @@ func GetIsAdminFromContext(ctx *gin.Context) (isAdmin bool) { if userInfo == nil { return false } - return userInfo.IsAdmin + return userInfo.RoleID == role.RoleAdminID } // GetUserInfoFromContext get user info from context diff --git a/internal/controller/activity_controller.go b/internal/controller/activity_controller.go index 917e1634..78140b67 100644 --- a/internal/controller/activity_controller.go +++ b/internal/controller/activity_controller.go @@ -6,6 +6,7 @@ import ( "github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/service/activity" "github.com/answerdev/answer/internal/service/activity_common" + "github.com/answerdev/answer/internal/service/role" "github.com/gin-gonic/gin" ) @@ -40,7 +41,7 @@ func (ac *ActivityController) GetObjectTimeline(ctx *gin.Context) { req.UserID = middleware.GetLoginUserIDFromContext(ctx) if userInfo := middleware.GetUserInfoFromContext(ctx); userInfo != nil { - req.IsAdmin = userInfo.IsAdmin + req.IsAdmin = userInfo.RoleID == role.RoleAdminID } resp, err := ac.activityService.GetObjectTimeline(ctx, req) diff --git a/internal/controller/answer_controller.go b/internal/controller/answer_controller.go index 684988ef..28b61141 100644 --- a/internal/controller/answer_controller.go +++ b/internal/controller/answer_controller.go @@ -51,13 +51,16 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) { } req.UserID = middleware.GetLoginUserIDFromContext(ctx) - req.IsAdmin = middleware.GetIsAdminFromContext(ctx) - can, err := ac.rankService.CheckOperationPermission(ctx, req.UserID, permission.AnswerDelete, req.ID) + objectOwner := ac.rankService.CheckOperationObjectOwner(ctx, req.UserID, req.ID) + canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ + permission.AnswerDelete, + }) if err != nil { handler.HandleResponse(ctx, err, nil) return } - if !can { + req.CanDelete = canList[0] || objectOwner + if !req.CanDelete { handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil) return } diff --git a/internal/entity/auth_user_entity.go b/internal/entity/auth_user_entity.go index f71d79df..a417cd2a 100644 --- a/internal/entity/auth_user_entity.go +++ b/internal/entity/auth_user_entity.go @@ -5,5 +5,5 @@ type UserCacheInfo struct { UserID string `json:"user_id"` UserStatus int `json:"user_status"` EmailStatus int `json:"email_status"` - IsAdmin bool `json:"is_admin"` + RoleID int `json:"role_id"` } diff --git a/internal/schema/answer_schema.go b/internal/schema/answer_schema.go index 7fc6a12d..7efd6e67 100644 --- a/internal/schema/answer_schema.go +++ b/internal/schema/answer_schema.go @@ -10,8 +10,9 @@ type RemoveAnswerReq struct { // answer id ID string `validate:"required" json:"id"` // user id - UserID string `json:"-"` - IsAdmin bool `json:"-"` + UserID string `json:"-"` + // whether user can delete it + CanDelete bool `json:"-"` } const ( diff --git a/internal/schema/user_schema.go b/internal/schema/user_schema.go index 308568c8..cb356584 100644 --- a/internal/schema/user_schema.go +++ b/internal/schema/user_schema.go @@ -66,8 +66,8 @@ type GetUserResp struct { Language string `json:"language"` // access token AccessToken string `json:"access_token"` - // is admin - IsAdmin bool `json:"is_admin"` + // role id + RoleID int `json:"role_id"` // user status Status string `json:"status"` } @@ -159,11 +159,7 @@ type GetOtherUserInfoByUsernameResp struct { // website Website string `json:"website"` // location - Location string `json:"location"` - // ip info - IPInfo string `json:"ip_info"` - // is admin - IsAdmin bool `json:"is_admin"` + Location string `json:"location"` Status string `json:"status"` StatusMsg string `json:"status_msg,omitempty"` } diff --git a/internal/service/answer_service.go b/internal/service/answer_service.go index 974482c9..738e4a55 100644 --- a/internal/service/answer_service.go +++ b/internal/service/answer_service.go @@ -20,6 +20,7 @@ import ( "github.com/answerdev/answer/internal/service/permission" questioncommon "github.com/answerdev/answer/internal/service/question_common" "github.com/answerdev/answer/internal/service/revision_common" + "github.com/answerdev/answer/internal/service/role" usercommon "github.com/answerdev/answer/internal/service/user_common" "github.com/answerdev/answer/pkg/encryption" "github.com/segmentfault/pacman/errors" @@ -39,6 +40,7 @@ type AnswerService struct { AnswerCommon *answercommon.AnswerCommon voteRepo activity_common.VoteRepo emailService *export.EmailService + roleService *role.UserRoleRelService } func NewAnswerService( @@ -53,6 +55,7 @@ func NewAnswerService( answerCommon *answercommon.AnswerCommon, voteRepo activity_common.VoteRepo, emailService *export.EmailService, + roleService *role.UserRoleRelService, ) *AnswerService { return &AnswerService{ answerRepo: answerRepo, @@ -66,6 +69,7 @@ func NewAnswerService( AnswerCommon: answerCommon, voteRepo: voteRepo, emailService: emailService, + roleService: roleService, } } @@ -82,7 +86,11 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, req *schema.RemoveAns if answerInfo.Status == entity.AnswerStatusDeleted { return nil } - if !req.IsAdmin { + roleID, err := as.roleService.GetUserRole(ctx, req.UserID) + if err != nil { + return err + } + if roleID != role.RoleAdminID && roleID != role.RoleModeratorID { if answerInfo.UserID != req.UserID { return errors.BadRequest(reason.AnswerCannotDeleted) } diff --git a/internal/service/auth/auth.go b/internal/service/auth/auth.go index e500f0b9..75f67944 100644 --- a/internal/service/auth/auth.go +++ b/internal/service/auth/auth.go @@ -45,7 +45,7 @@ func (as *AuthService) GetUserCacheInfo(ctx context.Context, accessToken string) log.Debugf("user status updated: %+v", cacheInfo) userCacheInfo.UserStatus = cacheInfo.UserStatus userCacheInfo.EmailStatus = cacheInfo.EmailStatus - userCacheInfo.IsAdmin = cacheInfo.IsAdmin + userCacheInfo.RoleID = cacheInfo.RoleID // update current user cache info err := as.authRepo.SetUserCacheInfo(ctx, accessToken, userCacheInfo) if err != nil { diff --git a/internal/service/tag_common/tag_common.go b/internal/service/tag_common/tag_common.go index 094ce594..6a390a0f 100644 --- a/internal/service/tag_common/tag_common.go +++ b/internal/service/tag_common/tag_common.go @@ -244,6 +244,17 @@ func (ts *TagCommonService) AddTag(ctx context.Context, req *schema.AddTagReq) ( if err != nil { return nil, err } + revisionDTO := &schema.AddRevisionDTO{ + UserID: req.UserID, + ObjectID: tagInfo.ID, + Title: tagInfo.SlugName, + } + tagInfoJson, _ := json.Marshal(tagInfo) + revisionDTO.Content = string(tagInfoJson) + _, err = ts.revisionService.AddRevision(ctx, revisionDTO, true) + if err != nil { + return nil, err + } return &schema.AddTagResp{SlugName: tagInfo.SlugName}, nil } diff --git a/internal/service/user_service.go b/internal/service/user_service.go index e7bd4374..a578f456 100644 --- a/internal/service/user_service.go +++ b/internal/service/user_service.go @@ -81,7 +81,7 @@ func (us *UserService) GetUserInfoByUserID(ctx context.Context, token, userID st resp = &schema.GetUserToSetShowResp{} resp.GetFromUserEntity(userInfo) resp.AccessToken = token - resp.IsAdmin = roleID == role.RoleAdminID + resp.RoleID = roleID return resp, nil } @@ -131,14 +131,14 @@ func (us *UserService) EmailLogin(ctx context.Context, req *schema.UserEmailLogi UserID: userInfo.ID, EmailStatus: userInfo.MailStatus, UserStatus: userInfo.Status, - IsAdmin: roleID == role.RoleAdminID, + RoleID: roleID, } resp.AccessToken, err = us.authService.SetUserCacheInfo(ctx, userCacheInfo) if err != nil { return nil, err } - resp.IsAdmin = userCacheInfo.IsAdmin - if resp.IsAdmin { + resp.RoleID = userCacheInfo.RoleID + if resp.RoleID == role.RoleAdminID { err = us.authService.SetAdminUserCacheInfo(ctx, resp.AccessToken, userCacheInfo) if err != nil { return nil, err @@ -365,14 +365,14 @@ func (us *UserService) UserRegisterByEmail(ctx context.Context, registerUserInfo UserID: userInfo.ID, EmailStatus: userInfo.MailStatus, UserStatus: userInfo.Status, - IsAdmin: roleID == role.RoleAdminID, + RoleID: roleID, } resp.AccessToken, err = us.authService.SetUserCacheInfo(ctx, userCacheInfo) if err != nil { return nil, nil, err } - resp.IsAdmin = userCacheInfo.IsAdmin - if resp.IsAdmin { + resp.RoleID = userCacheInfo.RoleID + if resp.RoleID == role.RoleAdminID { err = us.authService.SetAdminUserCacheInfo(ctx, resp.AccessToken, &entity.UserCacheInfo{UserID: userInfo.ID}) if err != nil { return nil, nil, err @@ -457,7 +457,7 @@ func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVeri UserID: userInfo.ID, EmailStatus: userInfo.MailStatus, UserStatus: userInfo.Status, - IsAdmin: roleID == role.RoleAdminID, + RoleID: roleID, } resp.AccessToken, err = us.authService.SetUserCacheInfo(ctx, userCacheInfo) if err != nil { @@ -467,8 +467,8 @@ func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVeri if err = us.authService.SetUserStatus(ctx, userCacheInfo); err != nil { return nil, err } - resp.IsAdmin = userCacheInfo.IsAdmin - if resp.IsAdmin { + resp.RoleID = userCacheInfo.RoleID + if resp.RoleID == role.RoleAdminID { err = us.authService.SetAdminUserCacheInfo(ctx, resp.AccessToken, &entity.UserCacheInfo{UserID: userInfo.ID}) if err != nil { return nil, err