diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml index c619234d..663554d7 100644 --- a/i18n/en_US.yaml +++ b/i18n/en_US.yaml @@ -184,7 +184,9 @@ backend: fail_to_meet_the_condition: other: Rank fail to meet the condition. vote_fail_to_meet_the_condition: - other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote. + other: Thanks for the feedback. You need at least {{.Rank}} reputation to cast a vote. + no_enough_rank_to_operate: + other: You need at least {{.Rank}} reputation to do this. report: handle_failed: other: Report handle failed. diff --git a/i18n/zh_CN.yaml b/i18n/zh_CN.yaml index 6329718e..1987e6e0 100644 --- a/i18n/zh_CN.yaml +++ b/i18n/zh_CN.yaml @@ -178,7 +178,9 @@ backend: fail_to_meet_the_condition: other: 级别不符合条件 vote_fail_to_meet_the_condition: - other: 感谢您的投票。您至少需要{{ rank }}声望才能投票。 + other: 感谢您的投票。您至少需要{{.Rank}}声望才能投票。 + no_enough_rank_to_operate: + other: 您至少需要{{.Rank}}声望才能执行此操作。 report: handle_failed: other: 报告处理失败 diff --git a/internal/base/reason/reason.go b/internal/base/reason/reason.go index 3c257944..b4cdbcb9 100644 --- a/internal/base/reason/reason.go +++ b/internal/base/reason/reason.go @@ -52,6 +52,7 @@ const ( TagAlreadyExist = "error.tag.already_exist" RankFailToMeetTheCondition = "error.rank.fail_to_meet_the_condition" VoteRankFailToMeetTheCondition = "error.rank.vote_fail_to_meet_the_condition" + NoEnoughRankToOperate = "error.rank.no_enough_rank_to_operate" ThemeNotFound = "error.theme.not_found" LangNotFound = "error.lang.not_found" ReportHandleFailed = "error.report.handle_failed" diff --git a/internal/controller/permission_controller.go b/internal/controller/permission_controller.go index 5dc6a46b..351c90c0 100644 --- a/internal/controller/permission_controller.go +++ b/internal/controller/permission_controller.go @@ -34,14 +34,18 @@ func (u *PermissionController) GetPermission(ctx *gin.Context) { } userID := middleware.GetLoginUserIDFromContext(ctx) - resp, err := u.rankService.CheckOperationPermissions(ctx, userID, req.Actions) + ops, requireRanks, err := u.rankService.CheckOperationPermissionsForRanks(ctx, userID, req.Actions) if err != nil { handler.HandleResponse(ctx, err, nil) return } - mapping := make(map[string]bool, len(resp)) + + lang := handler.GetLangByCtx(ctx) + mapping := make(map[string]*schema.GetPermissionResp, len(ops)) for i, action := range req.Actions { - mapping[action] = resp[i] + t := &schema.GetPermissionResp{HasPermission: ops[i]} + t.TrTip(lang, requireRanks[i]) + mapping[action] = t } handler.HandleResponse(ctx, err, mapping) } diff --git a/internal/controller/vote_controller.go b/internal/controller/vote_controller.go index 46fe8e32..6af80e35 100644 --- a/internal/controller/vote_controller.go +++ b/internal/controller/vote_controller.go @@ -1,8 +1,6 @@ package controller import ( - "fmt" - "github.com/answerdev/answer/internal/base/handler" "github.com/answerdev/answer/internal/base/middleware" "github.com/answerdev/answer/internal/base/reason" @@ -44,16 +42,15 @@ func (vc *VoteController) VoteUp(ctx *gin.Context) { } req.ObjectID = uid.DeShortID(req.ObjectID) req.UserID = middleware.GetLoginUserIDFromContext(ctx) - can, rank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, true) + can, needRank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, true) if err != nil { handler.HandleResponse(ctx, err, nil) return } if !can { lang := handler.GetLang(ctx) - msg := translator.Tr(lang, reason.VoteRankFailToMeetTheCondition) - msg = handler.MsgWithParameter(msg, map[string]string{"rank": fmt.Sprintf("%d", rank)}) - handler.HandleResponse(ctx, errors.Forbidden(reason.VoteRankFailToMeetTheCondition).WithMsg(msg), nil) + msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: needRank}) + handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) return } @@ -84,16 +81,15 @@ func (vc *VoteController) VoteDown(ctx *gin.Context) { } req.ObjectID = uid.DeShortID(req.ObjectID) req.UserID = middleware.GetLoginUserIDFromContext(ctx) - can, rank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, false) + can, needRank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, false) if err != nil { handler.HandleResponse(ctx, err, nil) return } if !can { lang := handler.GetLang(ctx) - msg := translator.Tr(lang, reason.VoteRankFailToMeetTheCondition) - msg = handler.MsgWithParameter(msg, map[string]string{"rank": fmt.Sprintf("%d", rank)}) - handler.HandleResponse(ctx, errors.Forbidden(reason.VoteRankFailToMeetTheCondition).WithMsg(msg), nil) + msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: needRank}) + handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) return } diff --git a/internal/schema/permission.go b/internal/schema/permission.go index 91f4a0f9..d6fa98f7 100644 --- a/internal/schema/permission.go +++ b/internal/schema/permission.go @@ -3,9 +3,17 @@ package schema import ( "strings" + "github.com/answerdev/answer/internal/base/reason" + "github.com/answerdev/answer/internal/base/translator" "github.com/answerdev/answer/internal/base/validator" + "github.com/segmentfault/pacman/i18n" ) +// PermissionTrTplData template data as for translate permission message +type PermissionTrTplData struct { + Rank int +} + // PermissionMemberAction permission member action type PermissionMemberAction struct { Action string `json:"action"` @@ -25,3 +33,22 @@ func (r *GetPermissionReq) Check() (errField []*validator.FormErrorField, err er } return nil, nil } + +// GetPermissionResp get permission response +type GetPermissionResp struct { + HasPermission bool `json:"has_permission"` + // only not allow, will return this tip + NoPermissionTip string `json:"no_permission_tip"` +} + +func (r *GetPermissionResp) TrTip(lang i18n.Language, requireRank int) { + if r.HasPermission { + return + } + if requireRank <= 0 { + r.NoPermissionTip = translator.Tr(lang, reason.RankFailToMeetTheCondition) + } else { + r.NoPermissionTip = translator.TrWithData( + lang, reason.NoEnoughRankToOperate, &PermissionTrTplData{Rank: requireRank}) + } +} diff --git a/internal/service/rank/rank_service.go b/internal/service/rank/rank_service.go index 4ef63d00..af60152b 100644 --- a/internal/service/rank/rank_service.go +++ b/internal/service/rank/rank_service.go @@ -95,21 +95,22 @@ func (rs *RankService) CheckOperationPermission(ctx context.Context, userID stri return can, nil } -// CheckOperationPermissions verify that the user has permission -func (rs *RankService) CheckOperationPermissions(ctx context.Context, userID string, actions []string) ( - can []bool, err error) { +// CheckOperationPermissionsForRanks verify that the user has permission +func (rs *RankService) CheckOperationPermissionsForRanks(ctx context.Context, userID string, actions []string) ( + can []bool, requireRanks []int, err error) { can = make([]bool, len(actions)) + requireRanks = make([]int, len(actions)) if len(userID) == 0 { - return can, nil + return can, requireRanks, nil } // get the rank of the current user userInfo, exist, err := rs.userCommon.GetUserBasicInfoByID(ctx, userID) if err != nil { - return can, err + return can, requireRanks, err } if !exist { - return can, nil + return can, requireRanks, nil } powerMapping := rs.getUserPowerMapping(ctx, userID) @@ -118,10 +119,18 @@ func (rs *RankService) CheckOperationPermissions(ctx context.Context, userID str can[idx] = true continue } - meetRank, _ := rs.checkUserRank(ctx, userInfo.ID, userInfo.Rank, PermissionPrefix+action) + meetRank, requireRank := rs.checkUserRank(ctx, userInfo.ID, userInfo.Rank, PermissionPrefix+action) can[idx] = meetRank + requireRanks[idx] = requireRank } - return can, nil + return can, requireRanks, nil +} + +// CheckOperationPermissions verify that the user has permission +func (rs *RankService) CheckOperationPermissions(ctx context.Context, userID string, actions []string) ( + can []bool, err error) { + can, _, err = rs.CheckOperationPermissionsForRanks(ctx, userID, actions) + return can, err } // CheckOperationObjectOwner check operation object owner @@ -142,7 +151,7 @@ func (rs *RankService) CheckOperationObjectOwner(ctx context.Context, userID, ob // CheckVotePermission verify that the user has vote permission func (rs *RankService) CheckVotePermission(ctx context.Context, userID, objectID string, voteUp bool) ( - can bool, rank int, err error) { + can bool, needRank int, err error) { if len(userID) == 0 || len(objectID) == 0 { return false, 0, nil } @@ -180,13 +189,12 @@ func (rs *RankService) CheckVotePermission(ctx context.Context, userID, objectID action = permission.CommentVoteDown } } - meetRank, rank := rs.checkUserRank(ctx, userInfo.ID, userInfo.Rank, PermissionPrefix+action) powerMapping := rs.getUserPowerMapping(ctx, userID) if powerMapping[action] { - return true, rank, nil + return true, 0, nil } - - return meetRank, rank, nil + can, needRank = rs.checkUserRank(ctx, userInfo.ID, userInfo.Rank, PermissionPrefix+action) + return can, needRank, nil } // getUserPowerMapping get user power mapping