Make allowed Visiblity modes configurable for Users (#16271)
Now that #16069 is merged, some sites may wish to enforce that users are all public, limited or private, and/or disallow users from becoming private. This PR adds functionality and settings to constrain a user's ability to change their visibility. Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
parent
2a98ec1c3c
commit
0b27b93728
11 changed files with 146 additions and 63 deletions
|
@ -656,6 +656,9 @@ PATH =
|
||||||
;; Public is for users visible for everyone
|
;; Public is for users visible for everyone
|
||||||
;DEFAULT_USER_VISIBILITY = public
|
;DEFAULT_USER_VISIBILITY = public
|
||||||
;;
|
;;
|
||||||
|
;; Set whitch visibibilty modes a user can have
|
||||||
|
;ALLOWED_USER_VISIBILITY_MODES = public,limited,private
|
||||||
|
;;
|
||||||
;; Either "public", "limited" or "private", default is "public"
|
;; Either "public", "limited" or "private", default is "public"
|
||||||
;; Limited is for organizations visible only to signed users
|
;; Limited is for organizations visible only to signed users
|
||||||
;; Private is for organizations visible only to members of the organization
|
;; Private is for organizations visible only to members of the organization
|
||||||
|
|
|
@ -513,6 +513,7 @@ relation to port exhaustion.
|
||||||
- `AUTO_WATCH_NEW_REPOS`: **true**: Enable this to let all organisation users watch new repos when they are created
|
- `AUTO_WATCH_NEW_REPOS`: **true**: Enable this to let all organisation users watch new repos when they are created
|
||||||
- `AUTO_WATCH_ON_CHANGES`: **false**: Enable this to make users watch a repository after their first commit to it
|
- `AUTO_WATCH_ON_CHANGES`: **false**: Enable this to make users watch a repository after their first commit to it
|
||||||
- `DEFAULT_USER_VISIBILITY`: **public**: Set default visibility mode for users, either "public", "limited" or "private".
|
- `DEFAULT_USER_VISIBILITY`: **public**: Set default visibility mode for users, either "public", "limited" or "private".
|
||||||
|
- `ALLOWED_USER_VISIBILITY_MODES`: **public,limited,private**: Set whitch visibibilty modes a user can have
|
||||||
- `DEFAULT_ORG_VISIBILITY`: **public**: Set default visibility mode for organisations, either "public", "limited" or "private".
|
- `DEFAULT_ORG_VISIBILITY`: **public**: Set default visibility mode for organisations, either "public", "limited" or "private".
|
||||||
- `DEFAULT_ORG_MEMBER_VISIBLE`: **false** True will make the membership of the users visible when added to the organisation.
|
- `DEFAULT_ORG_MEMBER_VISIBLE`: **false** True will make the membership of the users visible when added to the organisation.
|
||||||
- `ALLOW_ONLY_INTERNAL_REGISTRATION`: **false** Set to true to force registration only via gitea.
|
- `ALLOW_ONLY_INTERNAL_REGISTRATION`: **false** Set to true to force registration only via gitea.
|
||||||
|
|
|
@ -863,12 +863,31 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set system defaults
|
||||||
|
u.KeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate
|
||||||
|
u.Visibility = setting.Service.DefaultUserVisibilityMode
|
||||||
|
u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation
|
||||||
|
u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification
|
||||||
|
u.MaxRepoCreation = -1
|
||||||
|
u.Theme = setting.UI.DefaultTheme
|
||||||
|
|
||||||
|
// overwrite defaults if set
|
||||||
|
if len(overwriteDefault) != 0 && overwriteDefault[0] != nil {
|
||||||
|
u.Visibility = overwriteDefault[0].Visibility
|
||||||
|
}
|
||||||
|
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
if err = sess.Begin(); err != nil {
|
if err = sess.Begin(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate data
|
||||||
|
|
||||||
|
if err := validateUser(u); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
isExist, err := isUserExist(sess, 0, u.Name)
|
isExist, err := isUserExist(sess, 0, u.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -876,15 +895,6 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
return ErrUserAlreadyExist{u.Name}
|
return ErrUserAlreadyExist{u.Name}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = deleteUserRedirect(sess, u.Name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Email = strings.ToLower(u.Email)
|
|
||||||
if err = ValidateEmail(u.Email); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
isExist, err = isEmailUsed(sess, u.Email)
|
isExist, err = isEmailUsed(sess, u.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -892,6 +902,8 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
return ErrEmailAlreadyUsed{u.Email}
|
return ErrEmailAlreadyUsed{u.Email}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepare for database
|
||||||
|
|
||||||
u.LowerName = strings.ToLower(u.Name)
|
u.LowerName = strings.ToLower(u.Name)
|
||||||
u.AvatarEmail = u.Email
|
u.AvatarEmail = u.Email
|
||||||
if u.Rands, err = GetUserSalt(); err != nil {
|
if u.Rands, err = GetUserSalt(); err != nil {
|
||||||
|
@ -901,16 +913,10 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// set system defaults
|
// save changes to database
|
||||||
u.KeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate
|
|
||||||
u.Visibility = setting.Service.DefaultUserVisibilityMode
|
if err = deleteUserRedirect(sess, u.Name); err != nil {
|
||||||
u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation
|
return err
|
||||||
u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification
|
|
||||||
u.MaxRepoCreation = -1
|
|
||||||
u.Theme = setting.UI.DefaultTheme
|
|
||||||
// overwrite defaults if set
|
|
||||||
if len(overwriteDefault) != 0 && overwriteDefault[0] != nil {
|
|
||||||
u.Visibility = overwriteDefault[0].Visibility
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = sess.Insert(u); err != nil {
|
if _, err = sess.Insert(u); err != nil {
|
||||||
|
@ -1056,12 +1062,22 @@ func checkDupEmail(e Engine, u *User) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUser(e Engine, u *User) (err error) {
|
// validateUser check if user is valide to insert / update into database
|
||||||
|
func validateUser(u *User) error {
|
||||||
|
if !setting.Service.AllowedUserVisibilityModesSlice.IsAllowedVisibility(u.Visibility) {
|
||||||
|
return fmt.Errorf("visibility Mode not allowed: %s", u.Visibility.String())
|
||||||
|
}
|
||||||
|
|
||||||
u.Email = strings.ToLower(u.Email)
|
u.Email = strings.ToLower(u.Email)
|
||||||
if err = ValidateEmail(u.Email); err != nil {
|
return ValidateEmail(u.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUser(e Engine, u *User) error {
|
||||||
|
if err := validateUser(u); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = e.ID(u.ID).AllCols().Update(u)
|
|
||||||
|
_, err := e.ID(u.ID).AllCols().Update(u)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,6 +1092,10 @@ func UpdateUserCols(u *User, cols ...string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUserCols(e Engine, u *User, cols ...string) error {
|
func updateUserCols(e Engine, u *User, cols ...string) error {
|
||||||
|
if err := validateUser(u); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_, err := e.ID(u.ID).Cols(cols...).Update(u)
|
_, err := e.ID(u.ID).Cols(cols...).Update(u)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -189,6 +190,7 @@ func TestDeleteUser(t *testing.T) {
|
||||||
|
|
||||||
func TestEmailNotificationPreferences(t *testing.T) {
|
func TestEmailNotificationPreferences(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
expected string
|
expected string
|
||||||
userID int64
|
userID int64
|
||||||
|
@ -467,3 +469,23 @@ ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ib
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdateUser(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||||
|
|
||||||
|
user.KeepActivityPrivate = true
|
||||||
|
assert.NoError(t, UpdateUser(user))
|
||||||
|
user = AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||||
|
assert.True(t, user.KeepActivityPrivate)
|
||||||
|
|
||||||
|
setting.Service.AllowedUserVisibilityModesSlice = []bool{true, false, false}
|
||||||
|
user.KeepActivityPrivate = false
|
||||||
|
user.Visibility = structs.VisibleTypePrivate
|
||||||
|
assert.Error(t, UpdateUser(user))
|
||||||
|
user = AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||||
|
assert.True(t, user.KeepActivityPrivate)
|
||||||
|
|
||||||
|
user.Email = "no mail@mail.org"
|
||||||
|
assert.Error(t, UpdateUser(user))
|
||||||
|
}
|
||||||
|
|
|
@ -14,9 +14,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Service settings
|
// Service settings
|
||||||
var Service struct {
|
var Service = struct {
|
||||||
DefaultUserVisibility string
|
DefaultUserVisibility string
|
||||||
DefaultUserVisibilityMode structs.VisibleType
|
DefaultUserVisibilityMode structs.VisibleType
|
||||||
|
AllowedUserVisibilityModes []string
|
||||||
|
AllowedUserVisibilityModesSlice AllowedVisibility `ini:"-"`
|
||||||
DefaultOrgVisibility string
|
DefaultOrgVisibility string
|
||||||
DefaultOrgVisibilityMode structs.VisibleType
|
DefaultOrgVisibilityMode structs.VisibleType
|
||||||
ActiveCodeLives int
|
ActiveCodeLives int
|
||||||
|
@ -71,6 +73,29 @@ var Service struct {
|
||||||
RequireSigninView bool `ini:"REQUIRE_SIGNIN_VIEW"`
|
RequireSigninView bool `ini:"REQUIRE_SIGNIN_VIEW"`
|
||||||
DisableUsersPage bool `ini:"DISABLE_USERS_PAGE"`
|
DisableUsersPage bool `ini:"DISABLE_USERS_PAGE"`
|
||||||
} `ini:"service.explore"`
|
} `ini:"service.explore"`
|
||||||
|
}{
|
||||||
|
AllowedUserVisibilityModesSlice: []bool{true, true, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowedVisibility store in a 3 item bool array what is allowed
|
||||||
|
type AllowedVisibility []bool
|
||||||
|
|
||||||
|
// IsAllowedVisibility check if a AllowedVisibility allow a specific VisibleType
|
||||||
|
func (a AllowedVisibility) IsAllowedVisibility(t structs.VisibleType) bool {
|
||||||
|
if int(t) >= len(a) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return a[t]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToVisibleTypeSlice convert a AllowedVisibility into a VisibleType slice
|
||||||
|
func (a AllowedVisibility) ToVisibleTypeSlice() (result []structs.VisibleType) {
|
||||||
|
for i, v := range a {
|
||||||
|
if v {
|
||||||
|
result = append(result, structs.VisibleType(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func newService() {
|
func newService() {
|
||||||
|
@ -122,6 +147,13 @@ func newService() {
|
||||||
Service.AutoWatchOnChanges = sec.Key("AUTO_WATCH_ON_CHANGES").MustBool(false)
|
Service.AutoWatchOnChanges = sec.Key("AUTO_WATCH_ON_CHANGES").MustBool(false)
|
||||||
Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
||||||
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
|
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
|
||||||
|
Service.AllowedUserVisibilityModes = sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",")
|
||||||
|
if len(Service.AllowedUserVisibilityModes) != 0 {
|
||||||
|
Service.AllowedUserVisibilityModesSlice = []bool{false, false, false}
|
||||||
|
for _, sMode := range Service.AllowedUserVisibilityModes {
|
||||||
|
Service.AllowedUserVisibilityModesSlice[structs.VisibilityModes[sMode]] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
||||||
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()
|
||||||
|
|
|
@ -52,6 +52,7 @@ func NewUser(ctx *context.Context) {
|
||||||
ctx.Data["PageIsAdmin"] = true
|
ctx.Data["PageIsAdmin"] = true
|
||||||
ctx.Data["PageIsAdminUsers"] = true
|
ctx.Data["PageIsAdminUsers"] = true
|
||||||
ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode
|
ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode
|
||||||
|
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||||
|
|
||||||
ctx.Data["login_type"] = "0-0"
|
ctx.Data["login_type"] = "0-0"
|
||||||
|
|
||||||
|
@ -211,6 +212,7 @@ func EditUser(ctx *context.Context) {
|
||||||
ctx.Data["PageIsAdminUsers"] = true
|
ctx.Data["PageIsAdminUsers"] = true
|
||||||
ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation
|
ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation
|
||||||
ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
|
ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
|
||||||
|
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||||
|
|
||||||
prepareUserInfo(ctx)
|
prepareUserInfo(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
|
|
|
@ -56,7 +56,6 @@ func TestNewUserPost_MustChangePassword(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewUserPost_MustChangePasswordFalse(t *testing.T) {
|
func TestNewUserPost_MustChangePasswordFalse(t *testing.T) {
|
||||||
|
|
||||||
models.PrepareTestEnv(t)
|
models.PrepareTestEnv(t)
|
||||||
ctx := test.MockContext(t, "admin/users/new")
|
ctx := test.MockContext(t, "admin/users/new")
|
||||||
|
|
||||||
|
@ -94,7 +93,6 @@ func TestNewUserPost_MustChangePasswordFalse(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewUserPost_InvalidEmail(t *testing.T) {
|
func TestNewUserPost_InvalidEmail(t *testing.T) {
|
||||||
|
|
||||||
models.PrepareTestEnv(t)
|
models.PrepareTestEnv(t)
|
||||||
ctx := test.MockContext(t, "admin/users/new")
|
ctx := test.MockContext(t, "admin/users/new")
|
||||||
|
|
||||||
|
@ -125,7 +123,6 @@ func TestNewUserPost_InvalidEmail(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewUserPost_VisiblityDefaultPublic(t *testing.T) {
|
func TestNewUserPost_VisiblityDefaultPublic(t *testing.T) {
|
||||||
|
|
||||||
models.PrepareTestEnv(t)
|
models.PrepareTestEnv(t)
|
||||||
ctx := test.MockContext(t, "admin/users/new")
|
ctx := test.MockContext(t, "admin/users/new")
|
||||||
|
|
||||||
|
@ -164,7 +161,6 @@ func TestNewUserPost_VisiblityDefaultPublic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewUserPost_VisibilityPrivate(t *testing.T) {
|
func TestNewUserPost_VisibilityPrivate(t *testing.T) {
|
||||||
|
|
||||||
models.PrepareTestEnv(t)
|
models.PrepareTestEnv(t)
|
||||||
ctx := test.MockContext(t, "admin/users/new")
|
ctx := test.MockContext(t, "admin/users/new")
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ const (
|
||||||
func Profile(ctx *context.Context) {
|
func Profile(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("settings")
|
ctx.Data["Title"] = ctx.Tr("settings")
|
||||||
ctx.Data["PageIsSettingsProfile"] = true
|
ctx.Data["PageIsSettingsProfile"] = true
|
||||||
|
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplSettingsProfile)
|
ctx.HTML(http.StatusOK, tplSettingsProfile)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,25 +32,25 @@
|
||||||
<div class="inline field {{if .Err_Visibility}}error{{end}}">
|
<div class="inline field {{if .Err_Visibility}}error{{end}}">
|
||||||
<span class="inline required field"><label for="visibility">{{.i18n.Tr "settings.visibility"}}</label></span>
|
<span class="inline required field"><label for="visibility">{{.i18n.Tr "settings.visibility"}}</label></span>
|
||||||
<div class="ui selection type dropdown">
|
<div class="ui selection type dropdown">
|
||||||
{{if .User.Visibility.IsPublic}}
|
{{if .User.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}}
|
||||||
<input type="hidden" id="visibility" name="visibility" value="0">
|
{{if .User.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}}
|
||||||
{{end}}
|
{{if .User.Visibility.IsPrivate}}<input type="hidden" id="visibility" name="visibility" value="2">{{end}}
|
||||||
{{if .User.Visibility.IsLimited}}
|
|
||||||
<input type="hidden" id="visibility" name="visibility" value="1">
|
|
||||||
{{end}}
|
|
||||||
{{if .User.Visibility.IsPrivate}}
|
|
||||||
<input type="hidden" id="visibility" name="visibility" value="2">
|
|
||||||
{{end}}
|
|
||||||
<div class="text">
|
<div class="text">
|
||||||
{{if .User.Visibility.IsPublic}}{{.i18n.Tr "settings.visibility.public"}}{{end}}
|
{{if .User.Visibility.IsPublic}}{{.i18n.Tr "settings.visibility.public"}}{{end}}
|
||||||
{{if .User.Visibility.IsLimited}}{{.i18n.Tr "settings.visibility.limited"}}{{end}}
|
{{if .User.Visibility.IsLimited}}{{.i18n.Tr "settings.visibility.limited"}}{{end}}
|
||||||
{{if .User.Visibility.IsPrivate}}{{.i18n.Tr "settings.visibility.private"}}{{end}}
|
{{if .User.Visibility.IsPrivate}}{{.i18n.Tr "settings.visibility.private"}}{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{.i18n.Tr "settings.visibility.public"}}</div>
|
{{range $mode := .AllowedUserVisibilityModes}}
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{.i18n.Tr "settings.visibility.limited"}}</div>
|
{{if $mode.IsPublic}}
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{.i18n.Tr "settings.visibility.private"}}</div>
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{$.i18n.Tr "settings.visibility.public"}}</div>
|
||||||
|
{{else if $mode.IsLimited}}
|
||||||
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{$.i18n.Tr "settings.visibility.limited"}}</div>
|
||||||
|
{{else if $mode.IsPrivate}}
|
||||||
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{$.i18n.Tr "settings.visibility.private"}}</div>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,15 +30,21 @@
|
||||||
<div class="ui selection type dropdown">
|
<div class="ui selection type dropdown">
|
||||||
<input type="hidden" id="visibility" name="visibility" value="{{.visibility}}">
|
<input type="hidden" id="visibility" name="visibility" value="{{.visibility}}">
|
||||||
<div class="text">
|
<div class="text">
|
||||||
{{if .DefaultUserVisibilityMode.IsPublic}}{{.i18n.Tr "settings.visibility.public"}}{{end}}
|
{{if .DefaultUserVisibilityMode.IsPublic}}{{.i18n.Tr "settings.visibility.public"}}{{end}}
|
||||||
{{if .DefaultUserVisibilityMode.IsLimited}}{{.i18n.Tr "settings.visibility.limited"}}{{end}}
|
{{if .DefaultUserVisibilityMode.IsLimited}}{{.i18n.Tr "settings.visibility.limited"}}{{end}}
|
||||||
{{if .DefaultUserVisibilityMode.IsPrivate}}{{.i18n.Tr "settings.visibility.private"}}{{end}}
|
{{if .DefaultUserVisibilityMode.IsPrivate}}{{.i18n.Tr "settings.visibility.private"}}{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{.i18n.Tr "settings.visibility.public"}}</div>
|
{{range $mode := .AllowedUserVisibilityModes}}
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{.i18n.Tr "settings.visibility.limited"}}</div>
|
{{if $mode.IsPublic}}
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{.i18n.Tr "settings.visibility.private"}}</div>
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{$.i18n.Tr "settings.visibility.public"}}</div>
|
||||||
|
{{else if $mode.IsLimited}}
|
||||||
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{$.i18n.Tr "settings.visibility.limited"}}</div>
|
||||||
|
{{else if $mode.IsPrivate}}
|
||||||
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{$.i18n.Tr "settings.visibility.private"}}</div>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -71,25 +71,25 @@
|
||||||
<div class="inline field {{if .Err_Visibility}}error{{end}}">
|
<div class="inline field {{if .Err_Visibility}}error{{end}}">
|
||||||
<span class="inline required field"><label for="visibility">{{.i18n.Tr "settings.visibility"}}</label></span>
|
<span class="inline required field"><label for="visibility">{{.i18n.Tr "settings.visibility"}}</label></span>
|
||||||
<div class="ui selection type dropdown">
|
<div class="ui selection type dropdown">
|
||||||
{{if .SignedUser.Visibility.IsPublic}}
|
{{if .SignedUser.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}}
|
||||||
<input type="hidden" id="visibility" name="visibility" value="0">
|
{{if .SignedUser.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}}
|
||||||
{{end}}
|
{{if .SignedUser.Visibility.IsPrivate}}<input type="hidden" id="visibility" name="visibility" value="2">{{end}}
|
||||||
{{if .SignedUser.Visibility.IsLimited}}
|
|
||||||
<input type="hidden" id="visibility" name="visibility" value="1">
|
|
||||||
{{end}}
|
|
||||||
{{if .SignedUser.Visibility.IsPrivate}}
|
|
||||||
<input type="hidden" id="visibility" name="visibility" value="2">
|
|
||||||
{{end}}
|
|
||||||
<div class="text">
|
<div class="text">
|
||||||
{{if .SignedUser.Visibility.IsPublic}}{{.i18n.Tr "settings.visibility.public"}}{{end}}
|
{{if .SignedUser.Visibility.IsPublic}}{{.i18n.Tr "settings.visibility.public"}}{{end}}
|
||||||
{{if .SignedUser.Visibility.IsLimited}}{{.i18n.Tr "settings.visibility.limited"}}{{end}}
|
{{if .SignedUser.Visibility.IsLimited}}{{.i18n.Tr "settings.visibility.limited"}}{{end}}
|
||||||
{{if .SignedUser.Visibility.IsPrivate}}{{.i18n.Tr "settings.visibility.private"}}{{end}}
|
{{if .SignedUser.Visibility.IsPrivate}}{{.i18n.Tr "settings.visibility.private"}}{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{.i18n.Tr "settings.visibility.public"}}</div>
|
{{range $mode := .AllowedUserVisibilityModes}}
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{.i18n.Tr "settings.visibility.limited"}}</div>
|
{{if $mode.IsPublic}}
|
||||||
<div class="item poping up" data-content="{{.i18n.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{.i18n.Tr "settings.visibility.private"}}</div>
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{$.i18n.Tr "settings.visibility.public"}}</div>
|
||||||
|
{{else if $mode.IsLimited}}
|
||||||
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{$.i18n.Tr "settings.visibility.limited"}}</div>
|
||||||
|
{{else if $mode.IsPrivate}}
|
||||||
|
<div class="item poping up" data-content="{{$.i18n.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{$.i18n.Tr "settings.visibility.private"}}</div>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Reference in a new issue