mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-04 00:01:16 -04:00
Compare commits
9 Commits
3e99cadfa8
...
4ee9e17cec
Author | SHA1 | Date | |
---|---|---|---|
|
4ee9e17cec | ||
|
97fc87af89 | ||
|
6fe5c4c4d9 | ||
|
dd1fd89185 | ||
|
a8efed8c62 | ||
|
4211016c85 | ||
|
b711e5fd91 | ||
|
93dd2042ab | ||
|
a1420340dd |
@ -32,6 +32,8 @@ var Service = struct {
|
|||||||
AllowedUserVisibilityModesSlice AllowedVisibility `ini:"-"`
|
AllowedUserVisibilityModesSlice AllowedVisibility `ini:"-"`
|
||||||
DefaultOrgVisibility string
|
DefaultOrgVisibility string
|
||||||
DefaultOrgVisibilityMode structs.VisibleType
|
DefaultOrgVisibilityMode structs.VisibleType
|
||||||
|
AllowedOrgVisibilityModes []string
|
||||||
|
AllowedOrgVisibilityModesSlice AllowedVisibility `ini:"-"`
|
||||||
ActiveCodeLives int
|
ActiveCodeLives int
|
||||||
ResetPwdCodeLives int
|
ResetPwdCodeLives int
|
||||||
RegisterEmailConfirm bool
|
RegisterEmailConfirm bool
|
||||||
@ -108,6 +110,7 @@ var Service = struct {
|
|||||||
}
|
}
|
||||||
}{
|
}{
|
||||||
AllowedUserVisibilityModesSlice: []bool{true, true, true},
|
AllowedUserVisibilityModesSlice: []bool{true, true, true},
|
||||||
|
AllowedOrgVisibilityModesSlice: []bool{true, true, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllowedVisibility store in a 3 item bool array what is allowed
|
// AllowedVisibility store in a 3 item bool array what is allowed
|
||||||
@ -245,7 +248,34 @@ func loadServiceFrom(rootCfg ConfigProvider) {
|
|||||||
Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
|
Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
|
||||||
}
|
}
|
||||||
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
|
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
|
||||||
Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
|
||||||
|
// Process allowed organization visibility modes
|
||||||
|
modes = sec.Key("ALLOWED_ORG_VISIBILITY_MODES").Strings(",")
|
||||||
|
if len(modes) != 0 {
|
||||||
|
Service.AllowedOrgVisibilityModes = []string{}
|
||||||
|
Service.AllowedOrgVisibilityModesSlice = []bool{false, false, false}
|
||||||
|
for _, sMode := range modes {
|
||||||
|
if tp, ok := structs.VisibilityModes[sMode]; ok { // remove unsupported modes
|
||||||
|
Service.AllowedOrgVisibilityModes = append(Service.AllowedOrgVisibilityModes, sMode)
|
||||||
|
Service.AllowedOrgVisibilityModesSlice[tp] = true
|
||||||
|
} else {
|
||||||
|
log.Warn("ALLOWED_ORG_VISIBILITY_MODES %s is unsupported", sMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(Service.AllowedOrgVisibilityModes) == 0 {
|
||||||
|
Service.AllowedOrgVisibilityModes = []string{"public", "limited", "private"}
|
||||||
|
Service.AllowedOrgVisibilityModesSlice = []bool{true, true, true}
|
||||||
|
}
|
||||||
|
|
||||||
|
Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").String()
|
||||||
|
if Service.DefaultOrgVisibility == "" {
|
||||||
|
Service.DefaultOrgVisibility = Service.AllowedOrgVisibilityModes[0]
|
||||||
|
} else if !Service.AllowedOrgVisibilityModesSlice[structs.VisibilityModes[Service.DefaultOrgVisibility]] {
|
||||||
|
log.Warn("DEFAULT_ORG_VISIBILITY %s is wrong or not in ALLOWED_ORG_VISIBILITY_MODES, using first allowed", Service.DefaultOrgVisibility)
|
||||||
|
Service.DefaultOrgVisibility = Service.AllowedOrgVisibilityModes[0]
|
||||||
|
}
|
||||||
Service.DefaultOrgVisibilityMode = structs.VisibilityModes[Service.DefaultOrgVisibility]
|
Service.DefaultOrgVisibilityMode = structs.VisibilityModes[Service.DefaultOrgVisibility]
|
||||||
Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool()
|
Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool()
|
||||||
Service.UserDeleteWithCommentsMaxTime = sec.Key("USER_DELETE_WITH_COMMENTS_MAX_TIME").MustDuration(0)
|
Service.UserDeleteWithCommentsMaxTime = sec.Key("USER_DELETE_WITH_COMMENTS_MAX_TIME").MustDuration(0)
|
||||||
|
@ -126,6 +126,87 @@ ALLOWED_USER_VISIBILITY_MODES = public, limit, privated
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadServiceOrgVisibilityModes(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&Service)()
|
||||||
|
|
||||||
|
kases := map[string]func(){
|
||||||
|
`
|
||||||
|
[service]
|
||||||
|
DEFAULT_ORG_VISIBILITY = public
|
||||||
|
ALLOWED_ORG_VISIBILITY_MODES = public,limited,private
|
||||||
|
`: func() {
|
||||||
|
assert.Equal(t, "public", Service.DefaultOrgVisibility)
|
||||||
|
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultOrgVisibilityMode)
|
||||||
|
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedOrgVisibilityModes)
|
||||||
|
},
|
||||||
|
`
|
||||||
|
[service]
|
||||||
|
DEFAULT_ORG_VISIBILITY = public
|
||||||
|
`: func() {
|
||||||
|
assert.Equal(t, "public", Service.DefaultOrgVisibility)
|
||||||
|
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultOrgVisibilityMode)
|
||||||
|
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedOrgVisibilityModes)
|
||||||
|
},
|
||||||
|
`
|
||||||
|
[service]
|
||||||
|
DEFAULT_ORG_VISIBILITY = limited
|
||||||
|
`: func() {
|
||||||
|
assert.Equal(t, "limited", Service.DefaultOrgVisibility)
|
||||||
|
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultOrgVisibilityMode)
|
||||||
|
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedOrgVisibilityModes)
|
||||||
|
},
|
||||||
|
`
|
||||||
|
[service]
|
||||||
|
ALLOWED_ORG_VISIBILITY_MODES = public,limited,private
|
||||||
|
`: func() {
|
||||||
|
assert.Equal(t, "public", Service.DefaultOrgVisibility)
|
||||||
|
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultOrgVisibilityMode)
|
||||||
|
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedOrgVisibilityModes)
|
||||||
|
},
|
||||||
|
`
|
||||||
|
[service]
|
||||||
|
DEFAULT_ORG_VISIBILITY = public
|
||||||
|
ALLOWED_ORG_VISIBILITY_MODES = limited,private
|
||||||
|
`: func() {
|
||||||
|
assert.Equal(t, "limited", Service.DefaultOrgVisibility)
|
||||||
|
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultOrgVisibilityMode)
|
||||||
|
assert.Equal(t, []string{"limited", "private"}, Service.AllowedOrgVisibilityModes)
|
||||||
|
},
|
||||||
|
`
|
||||||
|
[service]
|
||||||
|
DEFAULT_ORG_VISIBILITY = my_type
|
||||||
|
ALLOWED_ORG_VISIBILITY_MODES = limited,private
|
||||||
|
`: func() {
|
||||||
|
assert.Equal(t, "limited", Service.DefaultOrgVisibility)
|
||||||
|
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultOrgVisibilityMode)
|
||||||
|
assert.Equal(t, []string{"limited", "private"}, Service.AllowedOrgVisibilityModes)
|
||||||
|
},
|
||||||
|
`
|
||||||
|
[service]
|
||||||
|
DEFAULT_ORG_VISIBILITY = public
|
||||||
|
ALLOWED_ORG_VISIBILITY_MODES = public, limit, privated
|
||||||
|
`: func() {
|
||||||
|
assert.Equal(t, "public", Service.DefaultOrgVisibility)
|
||||||
|
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultOrgVisibilityMode)
|
||||||
|
assert.Equal(t, []string{"public"}, Service.AllowedOrgVisibilityModes)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for kase, fun := range kases {
|
||||||
|
t.Run(kase, func(t *testing.T) {
|
||||||
|
cfg, err := NewConfigProviderFromData(kase)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
loadServiceFrom(cfg)
|
||||||
|
fun()
|
||||||
|
// reset
|
||||||
|
Service.AllowedOrgVisibilityModesSlice = []bool{true, true, true}
|
||||||
|
Service.AllowedOrgVisibilityModes = []string{}
|
||||||
|
Service.DefaultOrgVisibility = ""
|
||||||
|
Service.DefaultOrgVisibilityMode = structs.VisibleTypePublic
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadServiceRequireSignInView(t *testing.T) {
|
func TestLoadServiceRequireSignInView(t *testing.T) {
|
||||||
defer test.MockVariableValue(&Service)()
|
defer test.MockVariableValue(&Service)()
|
||||||
|
|
||||||
|
@ -2829,6 +2829,7 @@ form.name_been_taken = The organisation name "%s" has already been taken.
|
|||||||
form.name_reserved = The organization name "%s" is reserved.
|
form.name_reserved = The organization name "%s" is reserved.
|
||||||
form.name_pattern_not_allowed = The pattern "%s" is not allowed in an organization name.
|
form.name_pattern_not_allowed = The pattern "%s" is not allowed in an organization name.
|
||||||
form.create_org_not_allowed = You are not allowed to create an organization.
|
form.create_org_not_allowed = You are not allowed to create an organization.
|
||||||
|
form.visibility_not_allowed = The selected visibility mode is not allowed.
|
||||||
|
|
||||||
settings = Settings
|
settings = Settings
|
||||||
settings.options = Organization
|
settings.options = Organization
|
||||||
|
@ -1969,6 +1969,7 @@ pulls.cmd_instruction_checkout_title=Basculer
|
|||||||
pulls.cmd_instruction_checkout_desc=Depuis votre dépôt, basculer sur une nouvelle branche et tester des modifications.
|
pulls.cmd_instruction_checkout_desc=Depuis votre dépôt, basculer sur une nouvelle branche et tester des modifications.
|
||||||
pulls.cmd_instruction_merge_title=Fusionner
|
pulls.cmd_instruction_merge_title=Fusionner
|
||||||
pulls.cmd_instruction_merge_desc=Fusionner les modifications et mettre à jour sur Gitea.
|
pulls.cmd_instruction_merge_desc=Fusionner les modifications et mettre à jour sur Gitea.
|
||||||
|
pulls.cmd_instruction_merge_warning=Attention : cette opération ne peut pas fusionner la demande d’ajout car la « détection automatique de fusion manuelle » n’a pas été activée
|
||||||
pulls.clear_merge_message=Effacer le message de fusion
|
pulls.clear_merge_message=Effacer le message de fusion
|
||||||
pulls.clear_merge_message_hint=Effacer le message de fusion ne supprimera que le message de la révision, mais pas les pieds de révision générés tels que "Co-Authored-By:".
|
pulls.clear_merge_message_hint=Effacer le message de fusion ne supprimera que le message de la révision, mais pas les pieds de révision générés tels que "Co-Authored-By:".
|
||||||
|
|
||||||
@ -2768,6 +2769,8 @@ branch.new_branch_from=`Créer une nouvelle branche à partir de "%s"`
|
|||||||
branch.renamed=La branche %s à été renommée en %s.
|
branch.renamed=La branche %s à été renommée en %s.
|
||||||
branch.rename_default_or_protected_branch_error=Seuls les administrateurs peuvent renommer les branches par défaut ou protégées.
|
branch.rename_default_or_protected_branch_error=Seuls les administrateurs peuvent renommer les branches par défaut ou protégées.
|
||||||
branch.rename_protected_branch_failed=Cette branche est protégée par des règles de protection basées sur des globs.
|
branch.rename_protected_branch_failed=Cette branche est protégée par des règles de protection basées sur des globs.
|
||||||
|
branch.commits_divergence_from=Divergence de révisions : %[1]d en retard et %[2]d en avance sur %[3]s
|
||||||
|
branch.commits_no_divergence=Identique à la branche %[1]s
|
||||||
|
|
||||||
tag.create_tag=Créer l'étiquette %s
|
tag.create_tag=Créer l'étiquette %s
|
||||||
tag.create_tag_operation=Créer une étiquette
|
tag.create_tag_operation=Créer une étiquette
|
||||||
|
@ -2769,6 +2769,8 @@ branch.new_branch_from=`Cruthaigh brainse nua ó "%s"`
|
|||||||
branch.renamed=Ainmníodh brainse %s go %s.
|
branch.renamed=Ainmníodh brainse %s go %s.
|
||||||
branch.rename_default_or_protected_branch_error=Ní féidir ach le riarthóirí brainsí réamhshocraithe nó cosanta a athainmniú.
|
branch.rename_default_or_protected_branch_error=Ní féidir ach le riarthóirí brainsí réamhshocraithe nó cosanta a athainmniú.
|
||||||
branch.rename_protected_branch_failed=Tá an brainse seo faoi chosaint ag rialacha cosanta domhanda.
|
branch.rename_protected_branch_failed=Tá an brainse seo faoi chosaint ag rialacha cosanta domhanda.
|
||||||
|
branch.commits_divergence_from=Déanann sé dialltacht a thiomnú: %[1]d taobh thiar agus %[2]d chun tosaigh ar %[3]s
|
||||||
|
branch.commits_no_divergence=Mar an gcéanna le brainse %[1]s
|
||||||
|
|
||||||
tag.create_tag=Cruthaigh clib %s
|
tag.create_tag=Cruthaigh clib %s
|
||||||
tag.create_tag_operation=Cruthaigh clib
|
tag.create_tag_operation=Cruthaigh clib
|
||||||
@ -2782,6 +2784,7 @@ topic.done=Déanta
|
|||||||
topic.count_prompt=Ní féidir leat níos mó ná 25 topaicí a roghnú
|
topic.count_prompt=Ní féidir leat níos mó ná 25 topaicí a roghnú
|
||||||
topic.format_prompt=Ní mór do thopaicí tosú le litir nó uimhir, is féidir daiseanna ('-') agus poncanna ('.') a áireamh, a bheith suas le 35 carachtar ar fad. Ní mór litreacha a bheith i litreacha beaga.
|
topic.format_prompt=Ní mór do thopaicí tosú le litir nó uimhir, is féidir daiseanna ('-') agus poncanna ('.') a áireamh, a bheith suas le 35 carachtar ar fad. Ní mór litreacha a bheith i litreacha beaga.
|
||||||
|
|
||||||
|
find_file.follow_symlink=Lean an nasc siombalach seo go dtí an áit a bhfuil sé ag pointeáil air
|
||||||
find_file.go_to_file=Téigh go dtí an comhad
|
find_file.go_to_file=Téigh go dtí an comhad
|
||||||
find_file.no_matching=Níl aon chomhad meaitseála le fáil
|
find_file.no_matching=Níl aon chomhad meaitseála le fáil
|
||||||
|
|
||||||
|
@ -1562,8 +1562,8 @@ issues.filter_project=Planeamento
|
|||||||
issues.filter_project_all=Todos os planeamentos
|
issues.filter_project_all=Todos os planeamentos
|
||||||
issues.filter_project_none=Nenhum planeamento
|
issues.filter_project_none=Nenhum planeamento
|
||||||
issues.filter_assignee=Encarregado
|
issues.filter_assignee=Encarregado
|
||||||
issues.filter_assignee_no_assignee=Não atribuído
|
issues.filter_assignee_no_assignee=Não atribuída
|
||||||
issues.filter_assignee_any_assignee=Atribuído a qualquer pessoa
|
issues.filter_assignee_any_assignee=Atribuída a alguém
|
||||||
issues.filter_poster=Autor(a)
|
issues.filter_poster=Autor(a)
|
||||||
issues.filter_user_placeholder=Procurar utilizadores
|
issues.filter_user_placeholder=Procurar utilizadores
|
||||||
issues.filter_user_no_select=Todos os utilizadores
|
issues.filter_user_no_select=Todos os utilizadores
|
||||||
@ -1969,6 +1969,7 @@ pulls.cmd_instruction_checkout_title=Checkout
|
|||||||
pulls.cmd_instruction_checkout_desc=A partir do seu repositório, crie um novo ramo e teste nele as modificações.
|
pulls.cmd_instruction_checkout_desc=A partir do seu repositório, crie um novo ramo e teste nele as modificações.
|
||||||
pulls.cmd_instruction_merge_title=Integrar
|
pulls.cmd_instruction_merge_title=Integrar
|
||||||
pulls.cmd_instruction_merge_desc=Integrar as modificações e enviar para o Gitea.
|
pulls.cmd_instruction_merge_desc=Integrar as modificações e enviar para o Gitea.
|
||||||
|
pulls.cmd_instruction_merge_warning=Aviso: Esta operação não pode executar pedidos de integração porque a opção "auto-identificar integração manual" não está habilitada.
|
||||||
pulls.clear_merge_message=Apagar mensagem de integração
|
pulls.clear_merge_message=Apagar mensagem de integração
|
||||||
pulls.clear_merge_message_hint=Apagar a mensagem de integração apenas remove o conteúdo da mensagem de cometimento e mantém os rodapés do git, tais como "Co-Autorado-Por …".
|
pulls.clear_merge_message_hint=Apagar a mensagem de integração apenas remove o conteúdo da mensagem de cometimento e mantém os rodapés do git, tais como "Co-Autorado-Por …".
|
||||||
|
|
||||||
@ -2768,6 +2769,8 @@ branch.new_branch_from=`Criar um novo ramo a partir do ramo "%s"`
|
|||||||
branch.renamed=O ramo %s foi renomeado para %s.
|
branch.renamed=O ramo %s foi renomeado para %s.
|
||||||
branch.rename_default_or_protected_branch_error=Só os administradores é que podem renomear o ramo principal ou ramos protegidos.
|
branch.rename_default_or_protected_branch_error=Só os administradores é que podem renomear o ramo principal ou ramos protegidos.
|
||||||
branch.rename_protected_branch_failed=Este ramo está protegido por regras de salvaguarda baseadas em padrões glob.
|
branch.rename_protected_branch_failed=Este ramo está protegido por regras de salvaguarda baseadas em padrões glob.
|
||||||
|
branch.commits_divergence_from=Divergência nos cometimentos: %[1]d atrás e %[2]d à frente de %[3]s
|
||||||
|
branch.commits_no_divergence=Idêntico ao ramo %[1]s
|
||||||
|
|
||||||
tag.create_tag=Criar etiqueta %s
|
tag.create_tag=Criar etiqueta %s
|
||||||
tag.create_tag_operation=Criar etiqueta
|
tag.create_tag_operation=Criar etiqueta
|
||||||
@ -2781,6 +2784,7 @@ topic.done=Concluído
|
|||||||
topic.count_prompt=Não pode escolher mais do que 25 tópicos
|
topic.count_prompt=Não pode escolher mais do que 25 tópicos
|
||||||
topic.format_prompt=Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') ou pontos ('.') e podem ter até 35 caracteres. As letras têm que ser minúsculas.
|
topic.format_prompt=Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') ou pontos ('.') e podem ter até 35 caracteres. As letras têm que ser minúsculas.
|
||||||
|
|
||||||
|
find_file.follow_symlink=Seguir esta ligação simbólica para onde ela está apontando
|
||||||
find_file.go_to_file=Ir para o ficheiro
|
find_file.go_to_file=Ir para o ficheiro
|
||||||
find_file.no_matching=Não foi encontrado qualquer ficheiro correspondente
|
find_file.no_matching=Não foi encontrado qualquer ficheiro correspondente
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ func Create(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["visibility"] = setting.Service.DefaultOrgVisibilityMode
|
ctx.Data["visibility"] = setting.Service.DefaultOrgVisibilityMode
|
||||||
|
ctx.Data["AllowedOrgVisibilityModes"] = setting.Service.AllowedOrgVisibilityModesSlice.ToVisibleTypeSlice()
|
||||||
ctx.Data["repo_admin_change_team_access"] = true
|
ctx.Data["repo_admin_change_team_access"] = true
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplCreateOrg)
|
ctx.HTML(http.StatusOK, tplCreateOrg)
|
||||||
@ -48,6 +49,13 @@ func CreatePost(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the visibility is allowed
|
||||||
|
if !setting.Service.AllowedOrgVisibilityModesSlice.IsAllowedVisibility(form.Visibility) {
|
||||||
|
ctx.Data["Err_OrgVisibility"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("org.form.visibility_not_allowed"), tplCreateOrg, &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
ctx.HTML(http.StatusOK, tplCreateOrg)
|
ctx.HTML(http.StatusOK, tplCreateOrg)
|
||||||
return
|
return
|
||||||
|
@ -46,6 +46,7 @@ func Settings(ctx *context.Context) {
|
|||||||
ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
|
ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
|
||||||
ctx.Data["RepoAdminChangeTeamAccess"] = ctx.Org.Organization.RepoAdminChangeTeamAccess
|
ctx.Data["RepoAdminChangeTeamAccess"] = ctx.Org.Organization.RepoAdminChangeTeamAccess
|
||||||
ctx.Data["ContextUser"] = ctx.ContextUser
|
ctx.Data["ContextUser"] = ctx.ContextUser
|
||||||
|
ctx.Data["AllowedOrgVisibilityModes"] = setting.Service.AllowedOrgVisibilityModesSlice.ToVisibleTypeSlice()
|
||||||
|
|
||||||
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
ctx.ServerError("RenderUserOrgHeader", err)
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
@ -62,6 +63,14 @@ func SettingsPost(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsOrgSettings"] = true
|
ctx.Data["PageIsOrgSettings"] = true
|
||||||
ctx.Data["PageIsSettingsOptions"] = true
|
ctx.Data["PageIsSettingsOptions"] = true
|
||||||
ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
|
ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
|
||||||
|
ctx.Data["AllowedOrgVisibilityModes"] = setting.Service.AllowedOrgVisibilityModesSlice.ToVisibleTypeSlice()
|
||||||
|
|
||||||
|
// Check if the visibility is allowed
|
||||||
|
if !setting.Service.AllowedOrgVisibilityModesSlice.IsAllowedVisibility(form.Visibility) {
|
||||||
|
ctx.Data["Err_Visibility"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("org.form.visibility_not_allowed"), tplSettingsOptions, form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
ctx.HTML(http.StatusOK, tplSettingsOptions)
|
ctx.HTML(http.StatusOK, tplSettingsOptions)
|
||||||
|
@ -149,6 +149,9 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er
|
|||||||
if !u.IsOrganization() && !setting.Service.AllowedUserVisibilityModesSlice.IsAllowedVisibility(opts.Visibility.Value()) {
|
if !u.IsOrganization() && !setting.Service.AllowedUserVisibilityModesSlice.IsAllowedVisibility(opts.Visibility.Value()) {
|
||||||
return fmt.Errorf("visibility mode not allowed: %s", opts.Visibility.Value().String())
|
return fmt.Errorf("visibility mode not allowed: %s", opts.Visibility.Value().String())
|
||||||
}
|
}
|
||||||
|
if u.IsOrganization() && !setting.Service.AllowedOrgVisibilityModesSlice.IsAllowedVisibility(opts.Visibility.Value()) {
|
||||||
|
return fmt.Errorf("visibility mode not allowed for organization: %s", opts.Visibility.Value().String())
|
||||||
|
}
|
||||||
u.Visibility = opts.Visibility.Value()
|
u.Visibility = opts.Visibility.Value()
|
||||||
|
|
||||||
cols = append(cols, "visibility")
|
cols = append(cols, "visibility")
|
||||||
|
@ -11,7 +11,9 @@ import (
|
|||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
password_module "code.gitea.io/gitea/modules/auth/password"
|
password_module "code.gitea.io/gitea/modules/auth/password"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -122,3 +124,68 @@ func TestUpdateAuth(t *testing.T) {
|
|||||||
Password: optional.Some("aaaa"),
|
Password: optional.Some("aaaa"),
|
||||||
}), password_module.ErrMinLength)
|
}), password_module.ErrMinLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVisibilityModeValidation(t *testing.T) {
|
||||||
|
// Mock testing setup
|
||||||
|
defer test.MockVariableValue(&setting.Service)()
|
||||||
|
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
// Organization user
|
||||||
|
org := &user_model.User{
|
||||||
|
ID: 500,
|
||||||
|
Type: user_model.UserTypeOrganization,
|
||||||
|
Name: "test-org",
|
||||||
|
LowerName: "test-org",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular user
|
||||||
|
user := &user_model.User{
|
||||||
|
ID: 501,
|
||||||
|
Type: user_model.UserTypeIndividual,
|
||||||
|
Name: "test-user",
|
||||||
|
LowerName: "test-user",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test case 1: Allow only limited and private visibility for organizations
|
||||||
|
setting.Service.AllowedOrgVisibilityModesSlice = []bool{false, true, true}
|
||||||
|
setting.Service.AllowedOrgVisibilityModes = []string{"limited", "private"}
|
||||||
|
|
||||||
|
// Should fail when trying to set public visibility for organization
|
||||||
|
err := UpdateUser(db.DefaultContext, org, &UpdateOptions{
|
||||||
|
Visibility: optional.Some(structs.VisibleTypePublic),
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "visibility mode not allowed for organization")
|
||||||
|
|
||||||
|
// Should succeed when setting limited visibility for organization
|
||||||
|
err = UpdateUser(db.DefaultContext, org, &UpdateOptions{
|
||||||
|
Visibility: optional.Some(structs.VisibleTypeLimited),
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, structs.VisibleTypeLimited, org.Visibility)
|
||||||
|
|
||||||
|
// Test case 2: Allow only public and limited visibility for users
|
||||||
|
setting.Service.AllowedUserVisibilityModesSlice = []bool{true, true, false}
|
||||||
|
setting.Service.AllowedUserVisibilityModes = []string{"public", "limited"}
|
||||||
|
|
||||||
|
// Should fail when trying to set private visibility for user
|
||||||
|
err = UpdateUser(db.DefaultContext, user, &UpdateOptions{
|
||||||
|
Visibility: optional.Some(structs.VisibleTypePrivate),
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "visibility mode not allowed")
|
||||||
|
|
||||||
|
// Should succeed when setting public visibility for user
|
||||||
|
err = UpdateUser(db.DefaultContext, user, &UpdateOptions{
|
||||||
|
Visibility: optional.Some(structs.VisibleTypePublic),
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, structs.VisibleTypePublic, user.Visibility)
|
||||||
|
|
||||||
|
// Reset to default settings
|
||||||
|
setting.Service.AllowedOrgVisibilityModesSlice = []bool{true, true, true}
|
||||||
|
setting.Service.AllowedOrgVisibilityModes = []string{"public", "limited", "private"}
|
||||||
|
setting.Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
|
||||||
|
setting.Service.AllowedUserVisibilityModes = []string{"public", "limited", "private"}
|
||||||
|
}
|
||||||
|
@ -29,7 +29,7 @@ export default {
|
|||||||
important: true, // the frameworks are mixed together, so tailwind needs to override other framework's styles
|
important: true, // the frameworks are mixed together, so tailwind needs to override other framework's styles
|
||||||
content: [
|
content: [
|
||||||
isProduction && '!./templates/devtest/**/*',
|
isProduction && '!./templates/devtest/**/*',
|
||||||
isProduction && '!./web_src/js/standalone/devtest.js',
|
isProduction && '!./web_src/js/standalone/devtest.ts',
|
||||||
'!./templates/swagger/v1_json.tmpl',
|
'!./templates/swagger/v1_json.tmpl',
|
||||||
'!./templates/user/auth/oidc_wellknown.tmpl',
|
'!./templates/user/auth/oidc_wellknown.tmpl',
|
||||||
'!**/*_test.go',
|
'!**/*_test.go',
|
||||||
|
@ -17,18 +17,24 @@
|
|||||||
<div class="inline field required {{if .Err_OrgVisibility}}error{{end}}">
|
<div class="inline field required {{if .Err_OrgVisibility}}error{{end}}">
|
||||||
<label for="visibility">{{ctx.Locale.Tr "org.settings.visibility"}}</label>
|
<label for="visibility">{{ctx.Locale.Tr "org.settings.visibility"}}</label>
|
||||||
<div class="inline-right">
|
<div class="inline-right">
|
||||||
|
{{range $mode := .AllowedOrgVisibilityModes}}
|
||||||
|
{{if $mode.IsPublic}}
|
||||||
<div class="ui radio checkbox">
|
<div class="ui radio checkbox">
|
||||||
<input class="enable-system-radio" name="visibility" type="radio" value="0" {{if .visibility.IsPublic}}checked{{end}}>
|
<input class="enable-system-radio" name="visibility" type="radio" value="0" {{if $.visibility.IsPublic}}checked{{end}}>
|
||||||
<label>{{ctx.Locale.Tr "org.settings.visibility.public"}}</label>
|
<label>{{ctx.Locale.Tr "org.settings.visibility.public"}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{{else if $mode.IsLimited}}
|
||||||
<div class="ui radio checkbox">
|
<div class="ui radio checkbox">
|
||||||
<input class="enable-system-radio" name="visibility" type="radio" value="1" {{if .visibility.IsLimited}}checked{{end}}>
|
<input class="enable-system-radio" name="visibility" type="radio" value="1" {{if $.visibility.IsLimited}}checked{{end}}>
|
||||||
<label>{{ctx.Locale.Tr "org.settings.visibility.limited"}}</label>
|
<label>{{ctx.Locale.Tr "org.settings.visibility.limited"}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{{else if $mode.IsPrivate}}
|
||||||
<div class="ui radio checkbox">
|
<div class="ui radio checkbox">
|
||||||
<input class="enable-system-radio" name="visibility" type="radio" value="2" {{if .visibility.IsPrivate}}checked{{end}}>
|
<input class="enable-system-radio" name="visibility" type="radio" value="2" {{if $.visibility.IsPrivate}}checked{{end}}>
|
||||||
<label>{{ctx.Locale.Tr "org.settings.visibility.private"}}</label>
|
<label>{{ctx.Locale.Tr "org.settings.visibility.private"}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -30,27 +30,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="field" id="visibility_box">
|
|
||||||
<label for="visibility">{{ctx.Locale.Tr "org.settings.visibility"}}</label>
|
|
||||||
<div class="field">
|
|
||||||
<div class="ui radio checkbox">
|
|
||||||
<input class="enable-system-radio" name="visibility" type="radio" value="0" {{if eq .CurrentVisibility 0}}checked{{end}}>
|
|
||||||
<label>{{ctx.Locale.Tr "org.settings.visibility.public"}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="ui radio checkbox">
|
|
||||||
<input class="enable-system-radio" name="visibility" type="radio" value="1" {{if eq .CurrentVisibility 1}}checked{{end}}>
|
|
||||||
<label>{{ctx.Locale.Tr "org.settings.visibility.limited"}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="ui radio checkbox">
|
|
||||||
<input class="enable-system-radio" name="visibility" type="radio" value="2" {{if eq .CurrentVisibility 2}}checked{{end}}>
|
|
||||||
<label>{{ctx.Locale.Tr "org.settings.visibility.private"}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field" id="permission_box">
|
<div class="field" id="permission_box">
|
||||||
<label>{{ctx.Locale.Tr "org.settings.permission"}}</label>
|
<label>{{ctx.Locale.Tr "org.settings.permission"}}</label>
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached error danger segment">
|
<div class="ui attached error danger segment">
|
||||||
<div class="flex-list">
|
<div class="flex-list">
|
||||||
|
<div class="flex-item">
|
||||||
|
<div class="flex-item-main">
|
||||||
|
<div class="flex-item-title">{{ctx.Locale.Tr "org.settings.visibility"}}</div>
|
||||||
|
<div class="flex-item-body">{{ctx.Locale.Tr "org.settings.visibility_helper"}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-trailing">
|
||||||
|
<button class="ui basic red show-modal button" data-modal="#change-visibility-modal">{{ctx.Locale.Tr "org.settings.change_visibility"}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex-item tw-items-center">
|
<div class="flex-item tw-items-center">
|
||||||
<div class="flex-item-main">
|
<div class="flex-item-main">
|
||||||
<div class="flex-item-title">{{ctx.Locale.Tr "org.settings.rename"}}</div>
|
<div class="flex-item-title">{{ctx.Locale.Tr "org.settings.rename"}}</div>
|
||||||
@ -25,6 +35,49 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="ui small modal" id="change-visibility-modal">
|
||||||
|
<div class="header">
|
||||||
|
{{ctx.Locale.Tr "org.settings.change_visibility"}}
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>{{ctx.Locale.Tr "org.settings.visibility_change_warning"}}</p>
|
||||||
|
<form class="ui form form-fetch-action" action="{{.Link}}" method="post">
|
||||||
|
{{.CsrfTokenHtml}}
|
||||||
|
<div class="field" id="visibility_box">
|
||||||
|
<label for="visibility">{{ctx.Locale.Tr "org.settings.visibility"}}</label>
|
||||||
|
{{range $mode := .AllowedOrgVisibilityModes}}
|
||||||
|
{{if $mode.IsPublic}}
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
<input class="enable-system-radio" name="visibility" type="radio" value="0" {{if eq $.CurrentVisibility 0}}checked{{end}}>
|
||||||
|
<label>{{ctx.Locale.Tr "org.settings.visibility.public"}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else if $mode.IsLimited}}
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
<input class="enable-system-radio" name="visibility" type="radio" value="1" {{if eq $.CurrentVisibility 1}}checked{{end}}>
|
||||||
|
<label>{{ctx.Locale.Tr "org.settings.visibility.limited"}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else if $mode.IsPrivate}}
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
<input class="enable-system-radio" name="visibility" type="radio" value="2" {{if eq $.CurrentVisibility 2}}checked{{end}}>
|
||||||
|
<label>{{ctx.Locale.Tr "org.settings.visibility.private"}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="ui cancel button">{{ctx.Locale.Tr "settings.cancel"}}</button>
|
||||||
|
<button class="ui red button">{{ctx.Locale.Tr "org.settings.update_settings"}}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="ui small modal" id="rename-org-modal">
|
<div class="ui small modal" id="rename-org-modal">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
{{ctx.Locale.Tr "org.settings.rename"}}
|
{{ctx.Locale.Tr "org.settings.rename"}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user