mirror of https://gitee.com/answerdev/answer.git
feat(privilege): add privileges API
This commit is contained in:
parent
910484013c
commit
8800b376d5
24
docs/docs.go
24
docs/docs.go
|
@ -7919,10 +7919,6 @@ const docTemplate = `{
|
|||
"custom_header": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
},
|
||||
"custom_sidebar": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -7944,10 +7940,6 @@ const docTemplate = `{
|
|||
"custom_header": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
},
|
||||
"custom_sidebar": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -8049,18 +8041,10 @@ const docTemplate = `{
|
|||
"schema.SiteInterfaceReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"default_avatar",
|
||||
"language",
|
||||
"time_zone"
|
||||
],
|
||||
"properties": {
|
||||
"default_avatar": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"system",
|
||||
"gravatar"
|
||||
]
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"maxLength": 128
|
||||
|
@ -8074,18 +8058,10 @@ const docTemplate = `{
|
|||
"schema.SiteInterfaceResp": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"default_avatar",
|
||||
"language",
|
||||
"time_zone"
|
||||
],
|
||||
"properties": {
|
||||
"default_avatar": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"system",
|
||||
"gravatar"
|
||||
]
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"maxLength": 128
|
||||
|
|
|
@ -7907,10 +7907,6 @@
|
|||
"custom_header": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
},
|
||||
"custom_sidebar": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -7932,10 +7928,6 @@
|
|||
"custom_header": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
},
|
||||
"custom_sidebar": {
|
||||
"type": "string",
|
||||
"maxLength": 65536
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -8037,18 +8029,10 @@
|
|||
"schema.SiteInterfaceReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"default_avatar",
|
||||
"language",
|
||||
"time_zone"
|
||||
],
|
||||
"properties": {
|
||||
"default_avatar": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"system",
|
||||
"gravatar"
|
||||
]
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"maxLength": 128
|
||||
|
@ -8062,18 +8046,10 @@
|
|||
"schema.SiteInterfaceResp": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"default_avatar",
|
||||
"language",
|
||||
"time_zone"
|
||||
],
|
||||
"properties": {
|
||||
"default_avatar": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"system",
|
||||
"gravatar"
|
||||
]
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"maxLength": 128
|
||||
|
|
|
@ -1463,9 +1463,6 @@ definitions:
|
|||
custom_header:
|
||||
maxLength: 65536
|
||||
type: string
|
||||
custom_sidebar:
|
||||
maxLength: 65536
|
||||
type: string
|
||||
type: object
|
||||
schema.SiteCustomCssHTMLResp:
|
||||
properties:
|
||||
|
@ -1481,9 +1478,6 @@ definitions:
|
|||
custom_header:
|
||||
maxLength: 65536
|
||||
type: string
|
||||
custom_sidebar:
|
||||
maxLength: 65536
|
||||
type: string
|
||||
type: object
|
||||
schema.SiteGeneralReq:
|
||||
properties:
|
||||
|
@ -1554,11 +1548,6 @@ definitions:
|
|||
type: object
|
||||
schema.SiteInterfaceReq:
|
||||
properties:
|
||||
default_avatar:
|
||||
enum:
|
||||
- system
|
||||
- gravatar
|
||||
type: string
|
||||
language:
|
||||
maxLength: 128
|
||||
type: string
|
||||
|
@ -1566,17 +1555,11 @@ definitions:
|
|||
maxLength: 128
|
||||
type: string
|
||||
required:
|
||||
- default_avatar
|
||||
- language
|
||||
- time_zone
|
||||
type: object
|
||||
schema.SiteInterfaceResp:
|
||||
properties:
|
||||
default_avatar:
|
||||
enum:
|
||||
- system
|
||||
- gravatar
|
||||
type: string
|
||||
language:
|
||||
maxLength: 128
|
||||
type: string
|
||||
|
@ -1584,7 +1567,6 @@ definitions:
|
|||
maxLength: 128
|
||||
type: string
|
||||
required:
|
||||
- default_avatar
|
||||
- language
|
||||
- time_zone
|
||||
type: object
|
||||
|
|
|
@ -40,6 +40,60 @@ backend:
|
|||
other: Have the full power to access the site.
|
||||
moderator:
|
||||
other: Has access to all posts except admin settings.
|
||||
privilege:
|
||||
level_1:
|
||||
description:
|
||||
other: Level 1 (less reputation required for startup community)
|
||||
level_2:
|
||||
description:
|
||||
other: Level 2 (low reputation required for startup community)
|
||||
level_3:
|
||||
description:
|
||||
other: Level 3 (high reputation required for mature community)
|
||||
rank_question_add_label:
|
||||
other: Ask question
|
||||
rank_answer_add_label:
|
||||
other: Write answer
|
||||
rank_comment_add_label:
|
||||
other: Write comment
|
||||
rank_answer_accept_label:
|
||||
other: Accept answer
|
||||
rank_report_add_label:
|
||||
other: Flag
|
||||
rank_comment_vote_up_label:
|
||||
other: Upvote comment
|
||||
rank_link_url_limit_label:
|
||||
other: Post more than 2 links at a time
|
||||
rank_question_vote_up_label:
|
||||
other: Upvote question
|
||||
rank_answer_vote_up_label:
|
||||
other: Upvote answer
|
||||
rank_question_vote_down_label:
|
||||
other: Downvote question
|
||||
rank_answer_vote_down_label:
|
||||
other: Downvote answer
|
||||
rank_tag_add_label:
|
||||
other: Create new tag
|
||||
rank_tag_edit_label:
|
||||
other: Edit tag description (need to review)
|
||||
rank_question_edit_label:
|
||||
other: Edit other's question (need to review)
|
||||
rank_answer_edit_label:
|
||||
other: Edit other's answer (need to review)
|
||||
rank_question_edit_without_review_label:
|
||||
other: Edit other's question without review
|
||||
rank_answer_edit_without_review_label:
|
||||
other: Edit other's answer without review
|
||||
rank_question_audit_label:
|
||||
other: Review question edits
|
||||
rank_answer_audit_label:
|
||||
other: Review answer edits
|
||||
rank_tag_audit_label:
|
||||
other: Review tag edits
|
||||
rank_tag_edit_without_review_label:
|
||||
other: Edit tag description without review
|
||||
rank_tag_synonym_label:
|
||||
other: Manage tag synonyms
|
||||
email:
|
||||
other: Email
|
||||
password:
|
||||
|
|
|
@ -37,6 +37,60 @@ backend:
|
|||
other: 拥有管理网站的全部权限。
|
||||
moderator:
|
||||
other: 拥有访问除管理员设置以外的所有权限。
|
||||
privilege:
|
||||
level_1:
|
||||
description:
|
||||
other: 等级1(创业社区所需的声望最低)
|
||||
level_2:
|
||||
description:
|
||||
other: 等级2(创业社区所需的声望较低)
|
||||
level_3:
|
||||
description:
|
||||
other: 等级3(成熟社区所需的声望较高)
|
||||
rank_question_add_label:
|
||||
other: 提问
|
||||
rank_answer_add_label:
|
||||
other: 回答问题
|
||||
rank_comment_add_label:
|
||||
other: 发表评论
|
||||
rank_answer_accept_label:
|
||||
other: 接受答案
|
||||
rank_report_add_label:
|
||||
other: 举报
|
||||
rank_comment_vote_up_label:
|
||||
other: 评论点赞
|
||||
rank_link_url_limit_label:
|
||||
other: 一次发布超过两个链接
|
||||
rank_question_vote_up_label:
|
||||
other: 问题点赞
|
||||
rank_answer_vote_up_label:
|
||||
other: 答案点赞
|
||||
rank_question_vote_down_label:
|
||||
other: 问题点踩
|
||||
rank_answer_vote_down_label:
|
||||
other: 答案点踩
|
||||
rank_tag_add_label:
|
||||
other: 创建新标签
|
||||
rank_tag_edit_label:
|
||||
other: 编辑标签描述(需要审核)
|
||||
rank_question_edit_label:
|
||||
other: 编辑他人提问(需要审核)
|
||||
rank_answer_edit_label:
|
||||
other: 编辑他人回答(需要审核)
|
||||
rank_question_edit_without_review_label:
|
||||
other: 编辑他人提问(无需审核)
|
||||
rank_answer_edit_without_review_label:
|
||||
other: 编辑他人回答(无需审核)
|
||||
rank_question_audit_label:
|
||||
other: 审核问题编辑
|
||||
rank_answer_audit_label:
|
||||
other: 审核答案编辑
|
||||
rank_tag_audit_label:
|
||||
other: 审核标签编辑
|
||||
rank_tag_edit_without_review_label:
|
||||
other: 编辑标签描述(无需审核)
|
||||
rank_tag_synonym_label:
|
||||
other: 管理标签同义词
|
||||
email:
|
||||
other: 邮箱
|
||||
password:
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package constant
|
||||
|
||||
import "github.com/answerdev/answer/internal/base/reason"
|
||||
|
||||
type Privilege struct {
|
||||
Key string `json:"key"`
|
||||
Label string `json:"label"`
|
||||
Value int `json:"value"`
|
||||
Key string `json:"-"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -41,80 +43,29 @@ const (
|
|||
RankTagUseReservedTagKey = "rank.tag.use_reserved_tag"
|
||||
)
|
||||
|
||||
//| Permission | Level 1 | Level 2 | Level 3 | Custom Level |
|
||||
//| -------------------------------------- | ------------------------------------------------ | --------------------------------------------- | --------------------------------------------- | ------------ |
|
||||
//| Description | less reputation required for private team, group | low reputation required for startup community | high reputation required for mature community | |
|
||||
//| Ask question | 1 | 1 | 1 | |
|
||||
//| Write answer | 1 | 1 | 1 | |
|
||||
//| Write comment | 1 | 1 | 1 | |
|
||||
//| Accept answer | 1 | 1 | 1 | |
|
||||
//| Flag | 1 | 1 | 1 | |
|
||||
//| Upvote comment | 1 | 1 | 1 | |
|
||||
//| Post more than 2 links at a time | 1 | 10 | 10 | |
|
||||
//| Upvote question | 1 | 1 | 15 | |
|
||||
//| Upvote answer | 1 | 1 | 15 | |
|
||||
//| Downvote question | 125 | 125 | 125 | |
|
||||
//| Downvote answer | 125 | 125 | 125 | |
|
||||
//| Create new tag | 1 | 750 | 1500 | |
|
||||
//| Edit tag description (need to review) | 1 | 50 | 100 | |
|
||||
//| Edit other's question (need to review) | 1 | 100 | 200 | |
|
||||
//| Edit other's answer (need to review) | 1 | 100 | 200 | |
|
||||
//| Edit other's question without review | 1 | 1000 | 2000 | |
|
||||
//| Edit other's answer without review | 1 | 1000 | 2000 | |
|
||||
//| Revew question edits | 1 | 1000 | 2000 | |
|
||||
//| Review answer edits | 1 | 1000 | 2000 | |
|
||||
//| Review tag edits | 1 | 2500 | 5000 | |
|
||||
//| Edit tag description without review | 1 | 10000 | 20000 | |
|
||||
//| Manage tag synonyms | 1 | 10000 | 20000 | |
|
||||
|
||||
const (
|
||||
RankQuestionAddLabel = "Ask question"
|
||||
RankAnswerAddLabel = "Write answer"
|
||||
RankCommentAddLabel = "Write comment"
|
||||
RankAnswerAcceptLabel = "Accept answer"
|
||||
RankReportAddLabel = "Flag"
|
||||
RankCommentVoteUpLabel = "Upvote comment"
|
||||
RankLinkUrlLimitLabel = "Post more than 2 links at a time"
|
||||
RankQuestionVoteUpLabel = "Upvote question"
|
||||
RankAnswerVoteUpLabel = "Upvote answer"
|
||||
RankQuestionVoteDownLabel = "Downvote question"
|
||||
RankAnswerVoteDownLabel = "Downvote answer"
|
||||
RankTagAddLabel = "Create new tag"
|
||||
RankTagEditLabel = "Edit tag description (need to review)"
|
||||
RankQuestionEditLabel = "Edit other's question (need to review)"
|
||||
RankAnswerEditLabel = "Edit other's answer (need to review)"
|
||||
RankQuestionEditWithoutReviewLabel = "Edit other's question without review"
|
||||
RankAnswerEditWithoutReviewLabel = "Edit other's answer without review"
|
||||
RankQuestionAuditLabel = "Review question edits"
|
||||
RankAnswerAuditLabel = "Review answer edits"
|
||||
RankTagAuditLabel = "Review tag edits"
|
||||
RankTagEditWithoutReviewLabel = "Edit tag description without review"
|
||||
RankTagSynonymLabel = "Manage tag synonyms"
|
||||
)
|
||||
|
||||
var (
|
||||
RankAllPrivileges = []*Privilege{
|
||||
{Label: RankQuestionAddLabel, Key: RankQuestionAddKey},
|
||||
{Label: RankAnswerAddLabel, Key: RankAnswerAddKey},
|
||||
{Label: RankCommentAddLabel, Key: RankCommentAddKey},
|
||||
{Label: RankAnswerAcceptLabel, Key: RankAnswerAcceptKey},
|
||||
{Label: RankReportAddLabel, Key: RankReportAddKey},
|
||||
{Label: RankCommentVoteUpLabel, Key: RankCommentVoteUpKey},
|
||||
{Label: RankLinkUrlLimitLabel, Key: RankLinkUrlLimitKey},
|
||||
{Label: RankQuestionVoteUpLabel, Key: RankQuestionVoteUpKey},
|
||||
{Label: RankAnswerVoteUpLabel, Key: RankAnswerVoteUpKey},
|
||||
{Label: RankQuestionVoteDownLabel, Key: RankQuestionVoteDownKey},
|
||||
{Label: RankAnswerVoteDownLabel, Key: RankAnswerVoteDownKey},
|
||||
{Label: RankTagAddLabel, Key: RankTagAddKey},
|
||||
{Label: RankTagEditLabel, Key: RankTagEditKey},
|
||||
{Label: RankQuestionEditLabel, Key: RankQuestionEditKey},
|
||||
{Label: RankAnswerEditLabel, Key: RankAnswerEditKey},
|
||||
{Label: RankQuestionEditWithoutReviewLabel, Key: RankQuestionEditWithoutReviewKey},
|
||||
{Label: RankAnswerEditWithoutReviewLabel, Key: RankAnswerEditWithoutReviewKey},
|
||||
{Label: RankQuestionAuditLabel, Key: RankQuestionAuditKey},
|
||||
{Label: RankAnswerAuditLabel, Key: RankAnswerAuditKey},
|
||||
{Label: RankTagAuditLabel, Key: RankTagAuditKey},
|
||||
{Label: RankTagEditWithoutReviewLabel, Key: RankTagEditWithoutReviewKey},
|
||||
{Label: RankTagSynonymLabel, Key: RankTagSynonymKey},
|
||||
{Label: reason.RankQuestionAddLabel, Key: RankQuestionAddKey},
|
||||
{Label: reason.RankAnswerAddLabel, Key: RankAnswerAddKey},
|
||||
{Label: reason.RankCommentAddLabel, Key: RankCommentAddKey},
|
||||
{Label: reason.RankAnswerAcceptLabel, Key: RankAnswerAcceptKey},
|
||||
{Label: reason.RankReportAddLabel, Key: RankReportAddKey},
|
||||
{Label: reason.RankCommentVoteUpLabel, Key: RankCommentVoteUpKey},
|
||||
{Label: reason.RankLinkUrlLimitLabel, Key: RankLinkUrlLimitKey},
|
||||
{Label: reason.RankQuestionVoteUpLabel, Key: RankQuestionVoteUpKey},
|
||||
{Label: reason.RankAnswerVoteUpLabel, Key: RankAnswerVoteUpKey},
|
||||
{Label: reason.RankQuestionVoteDownLabel, Key: RankQuestionVoteDownKey},
|
||||
{Label: reason.RankAnswerVoteDownLabel, Key: RankAnswerVoteDownKey},
|
||||
{Label: reason.RankTagAddLabel, Key: RankTagAddKey},
|
||||
{Label: reason.RankTagEditLabel, Key: RankTagEditKey},
|
||||
{Label: reason.RankQuestionEditLabel, Key: RankQuestionEditKey},
|
||||
{Label: reason.RankAnswerEditLabel, Key: RankAnswerEditKey},
|
||||
{Label: reason.RankQuestionEditWithoutReviewLabel, Key: RankQuestionEditWithoutReviewKey},
|
||||
{Label: reason.RankAnswerEditWithoutReviewLabel, Key: RankAnswerEditWithoutReviewKey},
|
||||
{Label: reason.RankQuestionAuditLabel, Key: RankQuestionAuditKey},
|
||||
{Label: reason.RankAnswerAuditLabel, Key: RankAnswerAuditKey},
|
||||
{Label: reason.RankTagAuditLabel, Key: RankTagAuditKey},
|
||||
{Label: reason.RankTagEditWithoutReviewLabel, Key: RankTagEditWithoutReviewKey},
|
||||
{Label: reason.RankTagSynonymLabel, Key: RankTagSynonymKey},
|
||||
}
|
||||
)
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package reason
|
||||
|
||||
const (
|
||||
PrivilegeLevel1Desc = "privilege.level_1.description"
|
||||
PrivilegeLevel2Desc = "privilege.level_2.description"
|
||||
PrivilegeLevel3Desc = "privilege.level_3.description"
|
||||
|
||||
RankQuestionAddLabel = "privilege.rank_question_add_label"
|
||||
RankAnswerAddLabel = "privilege.rank_answer_add_label"
|
||||
RankCommentAddLabel = "privilege.rank_comment_add_label"
|
||||
RankAnswerAcceptLabel = "privilege.rank_answer_accept_label"
|
||||
RankReportAddLabel = "privilege.rank_report_add_label"
|
||||
RankCommentVoteUpLabel = "privilege.rank_comment_vote_up_label"
|
||||
RankLinkUrlLimitLabel = "privilege.rank_link_url_limit_label"
|
||||
RankQuestionVoteUpLabel = "privilege.rank_question_vote_up_label"
|
||||
RankAnswerVoteUpLabel = "privilege.rank_answer_vote_up_label"
|
||||
RankQuestionVoteDownLabel = "privilege.rank_question_vote_down_label"
|
||||
RankAnswerVoteDownLabel = "privilege.rank_answer_vote_down_label"
|
||||
RankTagAddLabel = "privilege.rank_tag_add_label"
|
||||
RankTagEditLabel = "privilege.rank_tag_edit_label"
|
||||
RankQuestionEditLabel = "privilege.rank_question_edit_label"
|
||||
RankAnswerEditLabel = "privilege.rank_answer_edit_label"
|
||||
RankQuestionEditWithoutReviewLabel = "privilege.rank_question_edit_without_review_label"
|
||||
RankAnswerEditWithoutReviewLabel = "privilege.rank_answer_edit_without_review_label"
|
||||
RankQuestionAuditLabel = "privilege.rank_question_audit_label"
|
||||
RankAnswerAuditLabel = "privilege.rank_answer_audit_label"
|
||||
RankTagAuditLabel = "privilege.rank_tag_audit_label"
|
||||
RankTagEditWithoutReviewLabel = "privilege.rank_tag_edit_without_review_label"
|
||||
RankTagSynonymLabel = "privilege.rank_tag_synonym_label"
|
||||
)
|
|
@ -68,6 +68,7 @@ func NewHTTPServer(debug bool,
|
|||
// plugin routes
|
||||
pluginAPIRouter.RegisterUnAuthConnectorRouter(mustUnAuthV1)
|
||||
pluginAPIRouter.RegisterAuthUserConnectorRouter(authV1)
|
||||
pluginAPIRouter.RegisterAuthAdminConnectorRouter(adminauthV1)
|
||||
|
||||
_ = plugin.CallAgent(func(agent plugin.Agent) error {
|
||||
agent.RegisterUnAuthRouter(unAuthV1)
|
||||
|
|
|
@ -137,7 +137,7 @@ func (uc *UserCenterController) UserCenterLoginCallback(ctx *gin.Context) {
|
|||
return
|
||||
}
|
||||
if len(resp.ErrMsg) > 0 {
|
||||
ctx.String(http.StatusOK, resp.ErrMsg)
|
||||
ctx.Redirect(http.StatusFound, "/50x?msg="+resp.ErrMsg)
|
||||
return
|
||||
}
|
||||
userCenter.AfterLogin(userInfo.ExternalID, resp.AccessToken)
|
||||
|
@ -172,7 +172,7 @@ func (uc *UserCenterController) UserCenterSignUpCallback(ctx *gin.Context) {
|
|||
return
|
||||
}
|
||||
if len(resp.ErrMsg) > 0 {
|
||||
ctx.String(http.StatusOK, resp.ErrMsg)
|
||||
ctx.Redirect(http.StatusFound, "/50x?msg="+resp.ErrMsg)
|
||||
return
|
||||
}
|
||||
userCenter.AfterLogin(userInfo.ExternalID, resp.AccessToken)
|
||||
|
|
|
@ -32,7 +32,7 @@ func NewUserAdminController(userService *user_admin.UserAdminService) *UserAdmin
|
|||
// @Success 200 {object} handler.RespBody
|
||||
// @Router /answer/admin/api/user/status [put]
|
||||
func (uc *UserAdminController) UpdateUserStatus(ctx *gin.Context) {
|
||||
if plugin.UserCenterEnabled() {
|
||||
if u, ok := plugin.GetUserCenter(); ok && u.Description().UserStatusAgentEnabled {
|
||||
handler.HandleResponse(ctx, errors.Forbidden(reason.ForbiddenError), nil)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -6,4 +6,5 @@ type UserCacheInfo struct {
|
|||
UserStatus int `json:"user_status"`
|
||||
EmailStatus int `json:"email_status"`
|
||||
RoleID int `json:"role_id"`
|
||||
ExternalID string `json:"external_id"`
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/answerdev/answer/internal/base/constant"
|
||||
"github.com/answerdev/answer/internal/entity"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/tidwall/gjson"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
|
@ -22,10 +23,47 @@ func addLoginLimitations(x *xorm.Engine) error {
|
|||
content := &schema.SiteLoginReq{}
|
||||
_ = json.Unmarshal([]byte(loginSiteInfo.Content), content)
|
||||
content.AllowEmailRegistrations = true
|
||||
content.AllowEmailDomains = make([]string, 0)
|
||||
_, err = x.ID(loginSiteInfo.ID).Cols("content").Update(loginSiteInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update site info failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
interfaceSiteInfo := &entity.SiteInfo{
|
||||
Type: constant.SiteTypeInterface,
|
||||
}
|
||||
exist, err = x.Get(interfaceSiteInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get config failed: %w", err)
|
||||
}
|
||||
siteUsers := &schema.SiteUsersReq{
|
||||
AllowUpdateDisplayName: true,
|
||||
AllowUpdateUsername: true,
|
||||
AllowUpdateAvatar: true,
|
||||
AllowUpdateBio: true,
|
||||
AllowUpdateWebsite: true,
|
||||
AllowUpdateLocation: true,
|
||||
}
|
||||
if exist {
|
||||
siteUsers.DefaultAvatar = gjson.Get(interfaceSiteInfo.Content, "default_avatar").String()
|
||||
}
|
||||
data, _ := json.Marshal(siteUsers)
|
||||
|
||||
exist, err = x.Get(&entity.SiteInfo{Type: constant.SiteTypeUsers})
|
||||
if err != nil {
|
||||
return fmt.Errorf("get config failed: %w", err)
|
||||
}
|
||||
if !exist {
|
||||
usersSiteInfo := &entity.SiteInfo{
|
||||
Type: constant.SiteTypeUsers,
|
||||
Content: string(data),
|
||||
Status: 1,
|
||||
}
|
||||
_, err = x.InsertOne(usersSiteInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("insert site info failed: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -206,7 +206,7 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
|
|||
|
||||
// user
|
||||
r.PUT("/user/password", middleware.BanAPIWhenUserCenterEnabled, a.userController.UserModifyPassWord)
|
||||
r.PUT("/user/info", middleware.BanAPIWhenUserCenterEnabled, a.userController.UserUpdateInfo)
|
||||
r.PUT("/user/info", a.userController.UserUpdateInfo)
|
||||
r.PUT("/user/interface", a.userController.UserUpdateInterface)
|
||||
r.POST("/user/notice/set", a.userController.UserNoticeSet)
|
||||
|
||||
|
|
|
@ -43,9 +43,8 @@ func (r *SiteGeneralReq) FormatSiteUrl() {
|
|||
|
||||
// SiteInterfaceReq site interface request
|
||||
type SiteInterfaceReq struct {
|
||||
Language string `validate:"required,gt=1,lte=128" form:"language" json:"language"`
|
||||
TimeZone string `validate:"required,gt=1,lte=128" form:"time_zone" json:"time_zone"`
|
||||
DefaultAvatar string `validate:"required,oneof=system gravatar" form:"default_avatar" json:"default_avatar"`
|
||||
Language string `validate:"required,gt=1,lte=128" form:"language" json:"language"`
|
||||
TimeZone string `validate:"required,gt=1,lte=128" form:"time_zone" json:"time_zone"`
|
||||
}
|
||||
|
||||
// SiteBrandingReq site branding request
|
||||
|
@ -275,6 +274,7 @@ type GetPrivilegesConfigResp struct {
|
|||
// PrivilegeOption privilege option
|
||||
type PrivilegeOption struct {
|
||||
Level PrivilegeLevel `json:"level"`
|
||||
LevelDesc string `json:"level_desc"`
|
||||
Privileges []*constant.Privilege `json:"privileges"`
|
||||
}
|
||||
|
||||
|
@ -312,21 +312,27 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
for _, option := range []PrivilegeLevel{PrivilegeLevel1, PrivilegeLevel2, PrivilegeLevel3} {
|
||||
op := &PrivilegeOption{
|
||||
Level: option,
|
||||
}
|
||||
DefaultPrivilegeOptions = append(DefaultPrivilegeOptions, &PrivilegeOption{
|
||||
Level: PrivilegeLevel1,
|
||||
LevelDesc: reason.PrivilegeLevel1Desc,
|
||||
}, &PrivilegeOption{
|
||||
Level: PrivilegeLevel2,
|
||||
LevelDesc: reason.PrivilegeLevel2Desc,
|
||||
}, &PrivilegeOption{
|
||||
Level: PrivilegeLevel3,
|
||||
LevelDesc: reason.PrivilegeLevel3Desc,
|
||||
})
|
||||
|
||||
for _, option := range DefaultPrivilegeOptions {
|
||||
for _, privilege := range constant.RankAllPrivileges {
|
||||
if len(privilegeOptionsLevelMapping[privilege.Key]) == 0 {
|
||||
fmt.Println("privilege key not found: ", privilege.Key)
|
||||
continue
|
||||
}
|
||||
op.Privileges = append(op.Privileges, &constant.Privilege{
|
||||
option.Privileges = append(option.Privileges, &constant.Privilege{
|
||||
Label: privilege.Label,
|
||||
Value: privilegeOptionsLevelMapping[privilege.Key][option-1],
|
||||
Value: privilegeOptionsLevelMapping[privilege.Key][option.Level-1],
|
||||
Key: privilege.Key,
|
||||
})
|
||||
}
|
||||
DefaultPrivilegeOptions = append(DefaultPrivilegeOptions, op)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ type UserCenterUserSettingsResp struct {
|
|||
}
|
||||
|
||||
type UserCenterAdminFunctionAgentResp struct {
|
||||
RoleAgentEnabled bool `json:"role_agent_enabled"`
|
||||
UserStatusAgentEnabled bool `json:"user_status_agent_enabled"`
|
||||
}
|
||||
|
||||
type UserSettingAgent struct {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/answerdev/answer/internal/entity"
|
||||
"github.com/answerdev/answer/pkg/token"
|
||||
"github.com/answerdev/answer/plugin"
|
||||
"github.com/segmentfault/pacman/log"
|
||||
)
|
||||
|
||||
|
@ -52,6 +53,14 @@ func (as *AuthService) GetUserCacheInfo(ctx context.Context, accessToken string)
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// try to get user status from user center
|
||||
uc, ok := plugin.GetUserCenter()
|
||||
if ok && len(userCacheInfo.ExternalID) > 0 {
|
||||
if userStatus := uc.UserStatus(userCacheInfo.ExternalID); userStatus != plugin.UserStatusAvailable {
|
||||
userCacheInfo.UserStatus = int(userStatus)
|
||||
}
|
||||
}
|
||||
return userCacheInfo, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/answerdev/answer/internal/base/constant"
|
||||
"github.com/answerdev/answer/internal/base/handler"
|
||||
"github.com/answerdev/answer/internal/base/reason"
|
||||
"github.com/answerdev/answer/internal/base/translator"
|
||||
"github.com/answerdev/answer/internal/entity"
|
||||
|
@ -35,7 +36,7 @@ func NewSiteInfoService(
|
|||
tagCommonService *tagcommon.TagCommonService,
|
||||
configRepo config.ConfigRepo,
|
||||
) *SiteInfoService {
|
||||
resp, err := siteInfoCommonService.GetSiteInterface(context.Background())
|
||||
resp, err := siteInfoCommonService.GetSiteUsers(context.Background())
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
|
@ -131,29 +132,18 @@ func (s *SiteInfoService) SaveSiteGeneral(ctx context.Context, req schema.SiteGe
|
|||
}
|
||||
|
||||
func (s *SiteInfoService) SaveSiteInterface(ctx context.Context, req schema.SiteInterfaceReq) (err error) {
|
||||
var (
|
||||
siteType = "interface"
|
||||
content []byte
|
||||
)
|
||||
|
||||
// check language
|
||||
if !translator.CheckLanguageIsValid(req.Language) {
|
||||
err = errors.BadRequest(reason.LangNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
content, _ = json.Marshal(req)
|
||||
|
||||
content, _ := json.Marshal(req)
|
||||
data := entity.SiteInfo{
|
||||
Type: siteType,
|
||||
Type: constant.SiteTypeInterface,
|
||||
Content: string(content),
|
||||
}
|
||||
|
||||
err = s.siteInfoRepo.SaveByType(ctx, siteType, &data)
|
||||
if err == nil {
|
||||
constant.DefaultAvatar = req.DefaultAvatar
|
||||
}
|
||||
return
|
||||
return s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeInterface, &data)
|
||||
}
|
||||
|
||||
// SaveSiteBranding save site branding information
|
||||
|
@ -235,7 +225,11 @@ func (s *SiteInfoService) SaveSiteUsers(ctx context.Context, req *schema.SiteUse
|
|||
Content: string(content),
|
||||
Status: 1,
|
||||
}
|
||||
return s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeUsers, data)
|
||||
err = s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeUsers, data)
|
||||
if err == nil {
|
||||
constant.DefaultAvatar = req.DefaultAvatar
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSMTPConfig get smtp config
|
||||
|
@ -329,8 +323,8 @@ func (s *SiteInfoService) GetPrivilegesConfig(ctx context.Context) (resp *schema
|
|||
return nil, err
|
||||
}
|
||||
resp = &schema.GetPrivilegesConfigResp{
|
||||
Options: schema.DefaultPrivilegeOptions,
|
||||
SelectedLevel: schema.PrivilegeLevel2,
|
||||
Options: s.translatePrivilegeOptions(ctx),
|
||||
SelectedLevel: schema.PrivilegeLevel3,
|
||||
}
|
||||
if privilege != nil && privilege.Level > 0 {
|
||||
resp.SelectedLevel = privilege.Level
|
||||
|
@ -338,6 +332,25 @@ func (s *SiteInfoService) GetPrivilegesConfig(ctx context.Context) (resp *schema
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *SiteInfoService) translatePrivilegeOptions(ctx context.Context) (options []*schema.PrivilegeOption) {
|
||||
la := handler.GetLangByCtx(ctx)
|
||||
for _, option := range schema.DefaultPrivilegeOptions {
|
||||
op := &schema.PrivilegeOption{
|
||||
Level: option.Level,
|
||||
LevelDesc: translator.Tr(la, option.LevelDesc),
|
||||
}
|
||||
for _, privilege := range option.Privileges {
|
||||
op.Privileges = append(op.Privileges, &constant.Privilege{
|
||||
Key: privilege.Key,
|
||||
Label: translator.Tr(la, privilege.Label),
|
||||
Value: privilege.Value,
|
||||
})
|
||||
}
|
||||
options = append(options, op)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SiteInfoService) UpdatePrivilegesConfig(ctx context.Context, req *schema.UpdatePrivilegesConfigReq) (err error) {
|
||||
var chooseOption *schema.PrivilegeOption
|
||||
for _, option := range schema.DefaultPrivilegeOptions {
|
||||
|
|
|
@ -150,7 +150,7 @@ func (us *UserCommon) MakeUsername(ctx context.Context, displayName string) (use
|
|||
return username + suffix, nil
|
||||
}
|
||||
|
||||
func (us *UserCommon) CacheLoginUserInfo(ctx context.Context, userID string, userStatus, emailStatus int) (
|
||||
func (us *UserCommon) CacheLoginUserInfo(ctx context.Context, userID string, userStatus, emailStatus int, externalID string) (
|
||||
accessToken string, userCacheInfo *entity.UserCacheInfo, err error) {
|
||||
roleID, err := us.userRoleService.GetUserRole(ctx, userID)
|
||||
if err != nil {
|
||||
|
@ -162,6 +162,7 @@ func (us *UserCommon) CacheLoginUserInfo(ctx context.Context, userID string, use
|
|||
EmailStatus: emailStatus,
|
||||
UserStatus: userStatus,
|
||||
RoleID: roleID,
|
||||
ExternalID: externalID,
|
||||
}
|
||||
|
||||
accessToken, err = us.authService.SetUserCacheInfo(ctx, userCacheInfo)
|
||||
|
|
|
@ -78,7 +78,7 @@ func (us *UserCenterLoginService) ExternalLogin(
|
|||
log.Errorf("update user last login date failed: %v", err)
|
||||
}
|
||||
accessToken, _, err := us.userCommonService.CacheLoginUserInfo(
|
||||
ctx, oldUserInfo.ID, oldUserInfo.MailStatus, oldUserInfo.Status)
|
||||
ctx, oldUserInfo.ID, oldUserInfo.MailStatus, oldUserInfo.Status, oldExternalLoginUserInfo.ExternalID)
|
||||
return &schema.UserExternalLoginResp{AccessToken: accessToken}, err
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ func (us *UserCenterLoginService) ExternalLogin(
|
|||
us.activeUser(ctx, oldUserInfo)
|
||||
|
||||
accessToken, _, err := us.userCommonService.CacheLoginUserInfo(
|
||||
ctx, oldUserInfo.ID, oldUserInfo.MailStatus, oldUserInfo.Status)
|
||||
ctx, oldUserInfo.ID, oldUserInfo.MailStatus, oldUserInfo.Status, oldExternalLoginUserInfo.ExternalID)
|
||||
return &schema.UserExternalLoginResp{AccessToken: accessToken}, err
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ func (us *UserCenterLoginService) UserCenterAdminFunctionAgent(ctx context.Conte
|
|||
return
|
||||
}
|
||||
desc := userCenter.Description()
|
||||
resp.RoleAgentEnabled = desc.RoleAgentEnabled
|
||||
resp.UserStatusAgentEnabled = desc.UserStatusAgentEnabled
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ func (us *UserExternalLoginService) ExternalLogin(
|
|||
log.Error(err)
|
||||
}
|
||||
accessToken, _, err := us.userCommonService.CacheLoginUserInfo(
|
||||
ctx, oldUserInfo.ID, newMailStatus, oldUserInfo.Status)
|
||||
ctx, oldUserInfo.ID, newMailStatus, oldUserInfo.Status, oldExternalLoginUserInfo.ExternalID)
|
||||
return &schema.UserExternalLoginResp{AccessToken: accessToken}, err
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ func (us *UserExternalLoginService) ExternalLogin(
|
|||
}
|
||||
|
||||
accessToken, _, err := us.userCommonService.CacheLoginUserInfo(
|
||||
ctx, oldUserInfo.ID, newMailStatus, oldUserInfo.Status)
|
||||
ctx, oldUserInfo.ID, newMailStatus, oldUserInfo.Status, oldExternalLoginUserInfo.ExternalID)
|
||||
return &schema.UserExternalLoginResp{AccessToken: accessToken}, err
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ func (us *UserExternalLoginService) ExternalLoginBindingUserSendEmail(
|
|||
return nil, err
|
||||
}
|
||||
resp.AccessToken, _, err = us.userCommonService.CacheLoginUserInfo(
|
||||
ctx, userInfo.ID, userInfo.MailStatus, userInfo.Status)
|
||||
ctx, userInfo.ID, userInfo.MailStatus, userInfo.Status, externalLoginInfo.ExternalID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
|
|
@ -499,7 +499,7 @@ func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVeri
|
|||
}
|
||||
|
||||
accessToken, userCacheInfo, err := us.userCommonService.CacheLoginUserInfo(
|
||||
ctx, userInfo.ID, userInfo.MailStatus, userInfo.Status)
|
||||
ctx, userInfo.ID, userInfo.MailStatus, userInfo.Status, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ type UserCenter interface {
|
|||
SignUpCallback(ctx *GinContext) (userInfo *UserCenterBasicUserInfo, err error)
|
||||
// UserInfo returns the user information
|
||||
UserInfo(externalID string) (userInfo *UserCenterBasicUserInfo, err error)
|
||||
// UserStatus returns the latest user status
|
||||
UserStatus(externalID string) (userStatus UserStatus)
|
||||
// UserList returns the user list information
|
||||
UserList(externalIDs []string) (userInfo []*UserCenterBasicUserInfo, err error)
|
||||
// UserSettings returns the user settings
|
||||
|
@ -23,14 +25,14 @@ type UserCenter interface {
|
|||
}
|
||||
|
||||
type UserCenterDesc struct {
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon"`
|
||||
Url string `json:"url"`
|
||||
LoginRedirectURL string `json:"login_redirect_url"`
|
||||
SignUpRedirectURL string `json:"sign_up_redirect_url"`
|
||||
RankAgentEnabled bool `json:"rank_agent_enabled"`
|
||||
RoleAgentEnabled bool `json:"role_agent_enabled"`
|
||||
MustAuthEmailEnabled bool `json:"must_auth_email_enabled"`
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon"`
|
||||
Url string `json:"url"`
|
||||
LoginRedirectURL string `json:"login_redirect_url"`
|
||||
SignUpRedirectURL string `json:"sign_up_redirect_url"`
|
||||
RankAgentEnabled bool `json:"rank_agent_enabled"`
|
||||
UserStatusAgentEnabled bool `json:"user_status_agent_enabled"`
|
||||
MustAuthEmailEnabled bool `json:"must_auth_email_enabled"`
|
||||
}
|
||||
|
||||
type UserStatus int
|
||||
|
|
Loading…
Reference in New Issue