| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package schema |
| |
| import ( |
| "context" |
| "fmt" |
| "net/mail" |
| "net/url" |
| "path/filepath" |
| "strings" |
| |
| "github.com/apache/answer/internal/base/constant" |
| "github.com/apache/answer/internal/base/handler" |
| "github.com/apache/answer/internal/base/reason" |
| "github.com/apache/answer/internal/base/translator" |
| "github.com/apache/answer/internal/base/validator" |
| "github.com/segmentfault/pacman/errors" |
| ) |
| |
| // SiteGeneralReq site general request |
| type SiteGeneralReq struct { |
| Name string `validate:"required,sanitizer,gt=1,lte=128" form:"name" json:"name"` |
| ShortDescription string `validate:"omitempty,sanitizer,gt=3,lte=255" form:"short_description" json:"short_description"` |
| Description string `validate:"omitempty,sanitizer,gt=3,lte=2000" form:"description" json:"description"` |
| SiteUrl string `validate:"required,sanitizer,gt=1,lte=512,url" form:"site_url" json:"site_url"` |
| ContactEmail string `validate:"required,sanitizer,gt=1,lte=512,email" form:"contact_email" json:"contact_email"` |
| } |
| |
| func (r *SiteGeneralReq) FormatSiteUrl() { |
| parsedUrl, err := url.Parse(r.SiteUrl) |
| if err != nil { |
| return |
| } |
| r.SiteUrl = fmt.Sprintf("%s://%s", parsedUrl.Scheme, parsedUrl.Host) |
| if len(parsedUrl.Path) > 0 { |
| r.SiteUrl += parsedUrl.Path |
| r.SiteUrl = strings.TrimSuffix(r.SiteUrl, "/") |
| } |
| } |
| |
| // 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"` |
| // Deperecated: use SiteUsersSettingsReq instead |
| DefaultAvatar string `validate:"omitempty" json:"-"` |
| // Deperecated: use SiteUsersSettingsReq instead |
| GravatarBaseURL string `validate:"omitempty" json:"-"` |
| } |
| |
| // SiteInterfaceSettingsReq site interface settings request |
| type SiteInterfaceSettingsReq struct { |
| Language string `validate:"required,gt=1,lte=128" json:"language"` |
| TimeZone string `validate:"required,gt=1,lte=128" json:"time_zone"` |
| } |
| |
| type SiteInterfaceSettingsResp SiteInterfaceSettingsReq |
| |
| type SiteUsersSettingsReq struct { |
| DefaultAvatar string `validate:"required,oneof=system gravatar" json:"default_avatar"` |
| GravatarBaseURL string `validate:"omitempty" json:"gravatar_base_url"` |
| } |
| |
| type SiteUsersSettingsResp SiteUsersSettingsReq |
| |
| // SiteBrandingReq site branding request |
| type SiteBrandingReq struct { |
| Logo string `validate:"omitempty,gt=0,lte=512" form:"logo" json:"logo"` |
| MobileLogo string `validate:"omitempty,gt=0,lte=512" form:"mobile_logo" json:"mobile_logo"` |
| SquareIcon string `validate:"omitempty,gt=0,lte=512" form:"square_icon" json:"square_icon"` |
| Favicon string `validate:"omitempty,gt=0,lte=512" form:"favicon" json:"favicon"` |
| } |
| |
| // SiteWriteReq site write request use SiteQuestionsReq, SiteAdvancedReq and SiteTagsReq instead |
| type SiteWriteReq struct { |
| MinimumContent int `validate:"omitempty,gte=0,lte=65535" json:"min_content"` |
| RestrictAnswer bool `validate:"omitempty" json:"restrict_answer"` |
| MinimumTags int `validate:"omitempty,gte=0,lte=5" json:"min_tags"` |
| RequiredTag bool `validate:"omitempty" json:"required_tag"` |
| RecommendTags []*SiteWriteTag `validate:"omitempty,dive" json:"recommend_tags"` |
| ReservedTags []*SiteWriteTag `validate:"omitempty,dive" json:"reserved_tags"` |
| MaxImageSize int `validate:"omitempty,gt=0" json:"max_image_size"` |
| MaxAttachmentSize int `validate:"omitempty,gt=0" json:"max_attachment_size"` |
| MaxImageMegapixel int `validate:"omitempty,gt=0" json:"max_image_megapixel"` |
| AuthorizedImageExtensions []string `validate:"omitempty" json:"authorized_image_extensions"` |
| AuthorizedAttachmentExtensions []string `validate:"omitempty" json:"authorized_attachment_extensions"` |
| UserID string `json:"-"` |
| } |
| |
| type SiteWriteResp SiteWriteReq |
| |
| // SiteQuestionsReq site questions settings request |
| type SiteQuestionsReq struct { |
| MinimumTags int `validate:"omitempty,gte=0,lte=5" json:"min_tags"` |
| MinimumContent int `validate:"omitempty,gte=0,lte=65535" json:"min_content"` |
| RestrictAnswer bool `validate:"omitempty" json:"restrict_answer"` |
| } |
| |
| // SiteAdvancedReq site advanced settings request |
| type SiteAdvancedReq struct { |
| MaxImageSize int `validate:"omitempty,gt=0" json:"max_image_size"` |
| MaxAttachmentSize int `validate:"omitempty,gt=0" json:"max_attachment_size"` |
| MaxImageMegapixel int `validate:"omitempty,gt=0" json:"max_image_megapixel"` |
| AuthorizedImageExtensions []string `validate:"omitempty" json:"authorized_image_extensions"` |
| AuthorizedAttachmentExtensions []string `validate:"omitempty" json:"authorized_attachment_extensions"` |
| } |
| |
| // SiteTagsReq site tags settings request |
| type SiteTagsReq struct { |
| ReservedTags []*SiteWriteTag `validate:"omitempty,dive" json:"reserved_tags"` |
| RecommendTags []*SiteWriteTag `validate:"omitempty,dive" json:"recommend_tags"` |
| RequiredTag bool `validate:"omitempty" json:"required_tag"` |
| UserID string `json:"-"` |
| } |
| |
| func (s *SiteAdvancedResp) GetMaxImageSize() int64 { |
| if s.MaxImageSize <= 0 { |
| return constant.DefaultMaxImageSize |
| } |
| return int64(s.MaxImageSize) * 1024 * 1024 |
| } |
| |
| func (s *SiteAdvancedResp) GetMaxAttachmentSize() int64 { |
| if s.MaxAttachmentSize <= 0 { |
| return constant.DefaultMaxAttachmentSize |
| } |
| return int64(s.MaxAttachmentSize) * 1024 * 1024 |
| } |
| |
| func (s *SiteAdvancedResp) GetMaxImageMegapixel() int { |
| if s.MaxImageMegapixel <= 0 { |
| return constant.DefaultMaxImageMegapixel |
| } |
| return s.MaxImageMegapixel * 1000 * 1000 |
| } |
| |
| // SiteWriteTag site write response tag |
| type SiteWriteTag struct { |
| SlugName string `validate:"required" json:"slug_name"` |
| DisplayName string `json:"display_name"` |
| } |
| |
| // SiteLegalReq site branding request use SitePoliciesReq and SiteSecurityReq instead |
| type SiteLegalReq struct { |
| TermsOfServiceOriginalText string `json:"terms_of_service_original_text"` |
| TermsOfServiceParsedText string `json:"terms_of_service_parsed_text"` |
| PrivacyPolicyOriginalText string `json:"privacy_policy_original_text"` |
| PrivacyPolicyParsedText string `json:"privacy_policy_parsed_text"` |
| ExternalContentDisplay string `validate:"required,oneof=always_display ask_before_display" json:"external_content_display"` |
| } |
| |
| type SitePoliciesReq struct { |
| TermsOfServiceOriginalText string `json:"terms_of_service_original_text"` |
| TermsOfServiceParsedText string `json:"terms_of_service_parsed_text"` |
| PrivacyPolicyOriginalText string `json:"privacy_policy_original_text"` |
| PrivacyPolicyParsedText string `json:"privacy_policy_parsed_text"` |
| } |
| |
| type SiteSecurityReq struct { |
| LoginRequired bool `json:"login_required"` |
| ExternalContentDisplay string `validate:"required,oneof=always_display ask_before_display" json:"external_content_display"` |
| CheckUpdate bool `validate:"omitempty,sanitizer" form:"check_update" json:"check_update"` |
| } |
| |
| type SitePoliciesResp SitePoliciesReq |
| type SiteSecurityResp SiteSecurityReq |
| |
| // GetSiteLegalInfoReq site site legal request |
| type GetSiteLegalInfoReq struct { |
| InfoType string `validate:"required,oneof=tos privacy" form:"info_type"` |
| } |
| |
| func (r *GetSiteLegalInfoReq) IsTOS() bool { |
| return r.InfoType == "tos" |
| } |
| |
| func (r *GetSiteLegalInfoReq) IsPrivacy() bool { |
| return r.InfoType == "privacy" |
| } |
| |
| // GetSiteLegalInfoResp get site legal info response |
| type GetSiteLegalInfoResp struct { |
| TermsOfServiceOriginalText string `json:"terms_of_service_original_text,omitempty"` |
| TermsOfServiceParsedText string `json:"terms_of_service_parsed_text,omitempty"` |
| PrivacyPolicyOriginalText string `json:"privacy_policy_original_text,omitempty"` |
| PrivacyPolicyParsedText string `json:"privacy_policy_parsed_text,omitempty"` |
| } |
| |
| // SiteUsersReq site users config request |
| type SiteUsersReq struct { |
| DefaultAvatar string `validate:"required,oneof=system gravatar" json:"default_avatar"` |
| GravatarBaseURL string `json:"gravatar_base_url"` |
| AllowUpdateDisplayName bool `json:"allow_update_display_name"` |
| AllowUpdateUsername bool `json:"allow_update_username"` |
| AllowUpdateAvatar bool `json:"allow_update_avatar"` |
| AllowUpdateBio bool `json:"allow_update_bio"` |
| AllowUpdateWebsite bool `json:"allow_update_website"` |
| AllowUpdateLocation bool `json:"allow_update_location"` |
| } |
| |
| // SiteLoginReq site login request |
| type SiteLoginReq struct { |
| AllowNewRegistrations bool `json:"allow_new_registrations"` |
| AllowEmailRegistrations bool `json:"allow_email_registrations"` |
| AllowPasswordLogin bool `json:"allow_password_login"` |
| AllowEmailDomains []string `json:"allow_email_domains"` |
| } |
| |
| // SiteCustomCssHTMLReq site custom css html |
| type SiteCustomCssHTMLReq struct { |
| CustomHead string `validate:"omitempty,gt=0,lte=65536" json:"custom_head"` |
| CustomCss string `validate:"omitempty,gt=0,lte=65536" json:"custom_css"` |
| CustomHeader string `validate:"omitempty,gt=0,lte=65536" json:"custom_header"` |
| CustomFooter string `validate:"omitempty,gt=0,lte=65536" json:"custom_footer"` |
| CustomSideBar string `validate:"omitempty,gt=0,lte=65536" json:"custom_sidebar"` |
| } |
| |
| // SiteThemeReq site theme config |
| type SiteThemeReq struct { |
| Theme string `validate:"required,gt=0,lte=255" json:"theme"` |
| ThemeConfig map[string]any `validate:"omitempty" json:"theme_config"` |
| ColorScheme string `validate:"omitempty,gt=0,lte=100" json:"color_scheme"` |
| Layout string `validate:"omitempty,oneof=Full-width Fixed-width" json:"layout"` |
| } |
| |
| type SiteSeoReq struct { |
| Permalink int `validate:"required,lte=4,gte=0" form:"permalink" json:"permalink"` |
| Robots string `validate:"required" form:"robots" json:"robots"` |
| } |
| |
| func (s *SiteSeoResp) IsShortLink() bool { |
| return s.Permalink == constant.PermalinkQuestionIDAndTitleByShortID || |
| s.Permalink == constant.PermalinkQuestionIDByShortID |
| } |
| |
| // AIPromptConfig AI prompt configuration for different languages |
| type AIPromptConfig struct { |
| ZhCN string `json:"zh_cn"` |
| EnUS string `json:"en_us"` |
| } |
| |
| // SiteAIReq AI configuration request |
| type SiteAIReq struct { |
| Enabled bool `validate:"omitempty" form:"enabled" json:"enabled"` |
| ChosenProvider string `validate:"omitempty,lte=50" form:"chosen_provider" json:"chosen_provider"` |
| SiteAIProviders []*SiteAIProvider `validate:"omitempty,dive" form:"ai_providers" json:"ai_providers"` |
| PromptConfig *AIPromptConfig `validate:"omitempty" form:"prompt_config" json:"prompt_config,omitempty"` |
| } |
| |
| func (s *SiteAIResp) GetProvider() *SiteAIProvider { |
| if !s.Enabled || s.ChosenProvider == "" { |
| return &SiteAIProvider{} |
| } |
| if len(s.SiteAIProviders) == 0 { |
| return &SiteAIProvider{} |
| } |
| for _, provider := range s.SiteAIProviders { |
| if provider.Provider == s.ChosenProvider { |
| return provider |
| } |
| } |
| return &SiteAIProvider{} |
| } |
| |
| type SiteAIProvider struct { |
| Provider string `validate:"omitempty,lte=50" form:"provider" json:"provider"` |
| APIHost string `validate:"omitempty,lte=512" form:"api_host" json:"api_host"` |
| APIKey string `validate:"omitempty,lte=256" form:"api_key" json:"api_key"` |
| Model string `validate:"omitempty,lte=100" form:"model" json:"model"` |
| } |
| |
| // SiteAIResp AI configuration response |
| type SiteAIResp SiteAIReq |
| |
| type SiteMCPReq struct { |
| Enabled bool `validate:"omitempty" form:"enabled" json:"enabled"` |
| } |
| |
| type SiteMCPResp struct { |
| Enabled bool `json:"enabled"` |
| Type string `json:"type"` |
| URL string `json:"url"` |
| HTTPHeader string `json:"http_header"` |
| } |
| |
| // SiteGeneralResp site general response |
| type SiteGeneralResp SiteGeneralReq |
| |
| // SiteInterfaceResp site interface response |
| type SiteInterfaceResp SiteInterfaceReq |
| |
| // SiteBrandingResp site branding response |
| type SiteBrandingResp SiteBrandingReq |
| |
| // SiteLoginResp site login response |
| type SiteLoginResp SiteLoginReq |
| |
| // SiteCustomCssHTMLResp site custom css html response |
| type SiteCustomCssHTMLResp SiteCustomCssHTMLReq |
| |
| // SiteUsersResp site users response |
| type SiteUsersResp SiteUsersReq |
| |
| // SiteThemeResp site theme response |
| type SiteThemeResp struct { |
| ThemeOptions []*ThemeOption `json:"theme_options"` |
| Theme string `json:"theme"` |
| ThemeConfig map[string]any `json:"theme_config"` |
| ColorScheme string `json:"color_scheme"` |
| Layout string `json:"layout"` |
| } |
| |
| func (s *SiteThemeResp) TrTheme(ctx context.Context) { |
| la := handler.GetLangByCtx(ctx) |
| for _, option := range s.ThemeOptions { |
| tr := translator.Tr(la, option.Value) |
| // if tr is equal the option value means not found translation, so use the original label |
| if tr != option.Value { |
| option.Label = tr |
| } |
| } |
| } |
| |
| // ThemeOption get label option |
| type ThemeOption struct { |
| Label string `json:"label"` |
| Value string `json:"value"` |
| } |
| |
| type SiteQuestionsResp SiteQuestionsReq |
| type SiteAdvancedResp SiteAdvancedReq |
| type SiteTagsResp SiteTagsReq |
| |
| // SiteLegalResp site write response use SitePoliciesResp and SiteSecurityResp instead |
| type SiteLegalResp SiteLegalReq |
| |
| // SiteLegalSimpleResp site write response |
| type SiteLegalSimpleResp struct { |
| ExternalContentDisplay string `validate:"required,oneof=always_display ask_before_display" json:"external_content_display"` |
| } |
| |
| // SiteSeoResp site write response |
| type SiteSeoResp SiteSeoReq |
| |
| // SiteInfoResp get site info response |
| type SiteInfoResp struct { |
| General *SiteGeneralResp `json:"general"` |
| Interface *SiteInterfaceSettingsResp `json:"interface"` |
| UsersSettings *SiteUsersSettingsResp `json:"users_settings"` |
| Branding *SiteBrandingResp `json:"branding"` |
| Login *SiteLoginResp `json:"login"` |
| Theme *SiteThemeResp `json:"theme"` |
| CustomCssHtml *SiteCustomCssHTMLResp `json:"custom_css_html"` |
| SiteSeo *SiteSeoResp `json:"site_seo"` |
| SiteUsers *SiteUsersResp `json:"site_users"` |
| Advanced *SiteAdvancedResp `json:"site_advanced"` |
| Questions *SiteQuestionsResp `json:"site_questions"` |
| Tags *SiteTagsResp `json:"site_tags"` |
| Legal *SiteLegalSimpleResp `json:"site_legal"` |
| Security *SiteSecurityResp `json:"site_security"` |
| Version string `json:"version"` |
| Revision string `json:"revision"` |
| AIEnabled bool `json:"ai_enabled"` |
| MCPEnabled bool `json:"mcp_enabled"` |
| } |
| |
| type TemplateSiteInfoResp struct { |
| General *SiteGeneralResp `json:"general"` |
| Interface *SiteInterfaceSettingsResp `json:"interface"` |
| Branding *SiteBrandingResp `json:"branding"` |
| SiteSeo *SiteSeoResp `json:"site_seo"` |
| CustomCssHtml *SiteCustomCssHTMLResp `json:"custom_css_html"` |
| Title string |
| Year string |
| Canonical string |
| JsonLD string |
| Keywords string |
| Description string |
| } |
| |
| // UpdateSMTPConfigReq get smtp config request |
| type UpdateSMTPConfigReq struct { |
| FromEmail string `validate:"omitempty,gt=0,lte=256" json:"from_email"` |
| FromName string `validate:"omitempty,gt=0,lte=256" json:"from_name"` |
| SMTPHost string `validate:"omitempty,gt=0,lte=256" json:"smtp_host"` |
| SMTPPort int `validate:"omitempty,min=1,max=65535" json:"smtp_port"` |
| Encryption string `validate:"omitempty,oneof=SSL TLS" json:"encryption"` // "" SSL TLS |
| SMTPUsername string `validate:"omitempty,gt=0,lte=256" json:"smtp_username"` |
| SMTPPassword string `validate:"omitempty,gt=0,lte=256" json:"smtp_password"` |
| SMTPAuthentication bool `validate:"omitempty" json:"smtp_authentication"` |
| TestEmailRecipient string `validate:"omitempty,email" json:"test_email_recipient"` |
| } |
| |
| func (r *UpdateSMTPConfigReq) Check() (errField []*validator.FormErrorField, err error) { |
| _, err = mail.ParseAddress(r.FromName) |
| if err == nil { |
| return append(errField, &validator.FormErrorField{ |
| ErrorField: "from_name", |
| ErrorMsg: reason.SMTPConfigFromNameCannotBeEmail, |
| }), errors.BadRequest(reason.SMTPConfigFromNameCannotBeEmail) |
| } |
| return nil, nil |
| } |
| |
| // GetSMTPConfigResp get smtp config response |
| type GetSMTPConfigResp struct { |
| FromEmail string `json:"from_email"` |
| FromName string `json:"from_name"` |
| SMTPHost string `json:"smtp_host"` |
| SMTPPort int `json:"smtp_port"` |
| Encryption string `json:"encryption"` // "" SSL TLS |
| SMTPUsername string `json:"smtp_username"` |
| SMTPPassword string `json:"smtp_password"` |
| SMTPAuthentication bool `json:"smtp_authentication"` |
| } |
| |
| // GetManifestJsonResp get manifest json response |
| type GetManifestJsonResp struct { |
| ManifestVersion int `json:"manifest_version"` |
| Version string `json:"version"` |
| Revision string `json:"revision"` |
| ShortName string `json:"short_name"` |
| Name string `json:"name"` |
| Icons []ManifestJsonIcon `json:"icons"` |
| StartUrl string `json:"start_url"` |
| Display string `json:"display"` |
| ThemeColor string `json:"theme_color"` |
| BackgroundColor string `json:"background_color"` |
| } |
| |
| type ManifestJsonIcon struct { |
| Src string `json:"src"` |
| Sizes string `json:"sizes"` |
| Type string `json:"type"` |
| } |
| |
| func CreateManifestJsonIcons(icon string) []ManifestJsonIcon { |
| ext := filepath.Ext(icon) |
| if ext == "" { |
| ext = "png" |
| } else { |
| ext = strings.ToLower(ext[1:]) |
| } |
| iconType := fmt.Sprintf("image/%s", ext) |
| return []ManifestJsonIcon{ |
| { |
| Src: icon, |
| Sizes: "16x16", |
| Type: iconType, |
| }, |
| { |
| Src: icon, |
| Sizes: "32x32", |
| Type: iconType, |
| }, |
| { |
| Src: icon, |
| Sizes: "48x48", |
| Type: iconType, |
| }, |
| { |
| Src: icon, |
| Sizes: "128x128", |
| Type: iconType, |
| }, |
| } |
| } |
| |
| const ( |
| // PrivilegeLevel1 low |
| PrivilegeLevel1 PrivilegeLevel = 1 |
| // PrivilegeLevel2 medium |
| PrivilegeLevel2 PrivilegeLevel = 2 |
| // PrivilegeLevel3 high |
| PrivilegeLevel3 PrivilegeLevel = 3 |
| // PrivilegeLevelCustom custom |
| PrivilegeLevelCustom PrivilegeLevel = 99 |
| ) |
| |
| type PrivilegeLevel int |
| type PrivilegeOptions []*PrivilegeOption |
| |
| func (p PrivilegeOptions) Choose(level PrivilegeLevel) (option *PrivilegeOption) { |
| for _, op := range p { |
| if op.Level == level { |
| return op |
| } |
| } |
| return nil |
| } |
| |
| // GetPrivilegesConfigResp get privileges config response |
| type GetPrivilegesConfigResp struct { |
| Options []*PrivilegeOption `json:"options"` |
| SelectedLevel PrivilegeLevel `json:"selected_level"` |
| } |
| |
| // PrivilegeOption privilege option |
| type PrivilegeOption struct { |
| Level PrivilegeLevel `json:"level"` |
| LevelDesc string `json:"level_desc"` |
| Privileges []*constant.Privilege `validate:"dive" json:"privileges"` |
| } |
| |
| // UpdatePrivilegesConfigReq update privileges config request |
| type UpdatePrivilegesConfigReq struct { |
| Level PrivilegeLevel `validate:"required,min=1,max=3|eq=99" json:"level"` |
| CustomPrivileges []*constant.Privilege `validate:"dive" json:"custom_privileges"` |
| } |
| |
| var ( |
| DefaultPrivilegeOptions PrivilegeOptions |
| DefaultCustomPrivilegeOption *PrivilegeOption |
| privilegeOptionsLevelMapping = map[string][]int{ |
| constant.RankQuestionAddKey: {1, 1, 1}, |
| constant.RankAnswerAddKey: {1, 1, 1}, |
| constant.RankCommentAddKey: {1, 1, 1}, |
| constant.RankReportAddKey: {1, 1, 1}, |
| constant.RankCommentVoteUpKey: {1, 1, 1}, |
| constant.RankLinkUrlLimitKey: {1, 10, 10}, |
| constant.RankQuestionVoteUpKey: {1, 8, 15}, |
| constant.RankAnswerVoteUpKey: {1, 8, 15}, |
| constant.RankQuestionVoteDownKey: {125, 125, 125}, |
| constant.RankAnswerVoteDownKey: {125, 125, 125}, |
| constant.RankInviteSomeoneToAnswerKey: {1, 500, 1000}, |
| constant.RankTagAddKey: {1, 750, 1500}, |
| constant.RankTagEditKey: {1, 50, 100}, |
| constant.RankQuestionEditKey: {1, 100, 200}, |
| constant.RankAnswerEditKey: {1, 100, 200}, |
| constant.RankQuestionEditWithoutReviewKey: {1, 1000, 2000}, |
| constant.RankAnswerEditWithoutReviewKey: {1, 1000, 2000}, |
| constant.RankQuestionAuditKey: {1, 1000, 2000}, |
| constant.RankAnswerAuditKey: {1, 1000, 2000}, |
| constant.RankTagAuditKey: {1, 2500, 5000}, |
| constant.RankTagEditWithoutReviewKey: {1, 10000, 20000}, |
| constant.RankTagSynonymKey: {1, 10000, 20000}, |
| } |
| ) |
| |
| func init() { |
| 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 { |
| continue |
| } |
| option.Privileges = append(option.Privileges, &constant.Privilege{ |
| Label: privilege.Label, |
| Value: privilegeOptionsLevelMapping[privilege.Key][option.Level-1], |
| Key: privilege.Key, |
| }) |
| } |
| } |
| |
| // set up default custom privilege option |
| DefaultCustomPrivilegeOption = &PrivilegeOption{ |
| Level: PrivilegeLevelCustom, |
| LevelDesc: reason.PrivilegeLevelCustomDesc, |
| Privileges: DefaultPrivilegeOptions[0].Privileges, |
| } |
| } |