mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-22 09:01:25 +00:00
enhance(ui): use OpenAPI 3.0 spec in API viewer, add spec buttons (#38478)
Follow-ups from https://github.com/go-gitea/gitea/pull/37038: - Render the OpenAPI 3.0 spec in the API viewer, it is richer than the Swagger 2.0 rendering - Replace the back link with gitea-styled buttons to view both specs and return to Gitea, flowing above swagger-ui on viewports where they would overlap the title - Key `VisibilityModes` by the string enum type, now named `VisibilityString`, removing the `string()` casts at API call sites - Drop the raw visibility strings from the `Service` settings struct in favor of the typed mode fields, which also removes the org default visibility row from the admin config page - Fix two pre-existing issues surfaced in review: an invalid `DEFAULT_USER_VISIBILITY` was silently accepted as public, and the org visibility error message showed the enum zero value instead of the submitted input Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -117,8 +117,8 @@ func (t *Team) CanNonMemberReadMeta(ctx context.Context, org, doer *user_model.U
|
||||
}
|
||||
}
|
||||
|
||||
func NormalizeTeamVisibility(s string) structs.VisibleType {
|
||||
if vt, ok := structs.VisibilityModes[s]; ok {
|
||||
func NormalizeTeamVisibility[T ~string](v T) structs.VisibleType {
|
||||
if vt, ok := structs.VisibilityModes[structs.VisibilityString(v)]; ok {
|
||||
return vt
|
||||
}
|
||||
return structs.VisibleTypePrivate
|
||||
|
||||
@@ -25,12 +25,9 @@ const (
|
||||
|
||||
// Service settings
|
||||
var Service = struct {
|
||||
DefaultUserVisibility string
|
||||
DefaultUserVisibilityMode structs.VisibleType
|
||||
AllowedUserVisibilityModes []string
|
||||
AllowedUserVisibilityModesSlice AllowedVisibility `ini:"-"`
|
||||
DefaultOrgVisibility string
|
||||
DefaultOrgVisibilityMode structs.VisibleType
|
||||
DefaultUserVisibilityMode structs.VisibleType `ini:"-"`
|
||||
AllowedUserVisibilityModesSlice AllowedVisibility `ini:"-"`
|
||||
DefaultOrgVisibilityMode structs.VisibleType `ini:"-"`
|
||||
ActiveCodeLives int
|
||||
ResetPwdCodeLives int
|
||||
RegisterEmailConfirm bool
|
||||
@@ -217,36 +214,35 @@ func loadServiceFrom(rootCfg ConfigProvider) {
|
||||
Service.EnableUserHeatmap = sec.Key("ENABLE_USER_HEATMAP").MustBool(true)
|
||||
Service.AutoWatchNewRepos = sec.Key("AUTO_WATCH_NEW_REPOS").MustBool(true)
|
||||
Service.AutoWatchOnChanges = sec.Key("AUTO_WATCH_ON_CHANGES").MustBool(false)
|
||||
modes := sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",")
|
||||
if len(modes) != 0 {
|
||||
Service.AllowedUserVisibilityModes = []string{}
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{false, false, false}
|
||||
for _, sMode := range modes {
|
||||
if tp, ok := structs.VisibilityModes[sMode]; ok { // remove unsupported modes
|
||||
Service.AllowedUserVisibilityModes = append(Service.AllowedUserVisibilityModes, sMode)
|
||||
Service.AllowedUserVisibilityModesSlice[tp] = true
|
||||
} else {
|
||||
log.Warn("ALLOWED_USER_VISIBILITY_MODES %s is unsupported", sMode)
|
||||
}
|
||||
|
||||
Service.AllowedUserVisibilityModesSlice = AllowedVisibility{false, false, false}
|
||||
var allowedUserVisibilityModes []structs.VisibilityString
|
||||
for _, allowedMode := range sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",") {
|
||||
if tp, ok := structs.VisibilityModes[structs.VisibilityString(allowedMode)]; ok { // remove unsupported modes
|
||||
allowedUserVisibilityModes = append(allowedUserVisibilityModes, structs.VisibilityString(allowedMode))
|
||||
Service.AllowedUserVisibilityModesSlice[tp] = true
|
||||
} else {
|
||||
log.Warn("ALLOWED_USER_VISIBILITY_MODES %s is unsupported", allowedMode)
|
||||
}
|
||||
}
|
||||
|
||||
if len(Service.AllowedUserVisibilityModes) == 0 {
|
||||
Service.AllowedUserVisibilityModes = []string{"public", "limited", "private"}
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
|
||||
if len(allowedUserVisibilityModes) == 0 {
|
||||
allowedUserVisibilityModes = []structs.VisibilityString{structs.VisibilityStringPublic, structs.VisibilityStringLimited, structs.VisibilityStringPrivate}
|
||||
Service.AllowedUserVisibilityModesSlice = AllowedVisibility{true, true, true}
|
||||
}
|
||||
|
||||
Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").String()
|
||||
if Service.DefaultUserVisibility == "" {
|
||||
Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
|
||||
} else if !Service.AllowedUserVisibilityModesSlice[structs.VisibilityModes[Service.DefaultUserVisibility]] {
|
||||
log.Warn("DEFAULT_USER_VISIBILITY %s is wrong or not in ALLOWED_USER_VISIBILITY_MODES, using first allowed", Service.DefaultUserVisibility)
|
||||
Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
|
||||
defaultUserVisibility := structs.VisibilityString(sec.Key("DEFAULT_USER_VISIBILITY").String())
|
||||
if defaultUserVisibility == "" {
|
||||
defaultUserVisibility = allowedUserVisibilityModes[0]
|
||||
} else if vt, ok := structs.VisibilityModes[defaultUserVisibility]; !ok || !Service.AllowedUserVisibilityModesSlice[vt] {
|
||||
log.Warn("DEFAULT_USER_VISIBILITY %s is wrong or not in ALLOWED_USER_VISIBILITY_MODES, using first allowed", defaultUserVisibility)
|
||||
defaultUserVisibility = allowedUserVisibilityModes[0]
|
||||
}
|
||||
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
|
||||
Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
||||
Service.DefaultOrgVisibilityMode = structs.VisibilityModes[Service.DefaultOrgVisibility]
|
||||
Service.DefaultUserVisibilityMode = structs.VisibilityModes[defaultUserVisibility]
|
||||
|
||||
defaultOrgVisibility := structs.VisibilityString(sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.VisibilityModeKeys()))
|
||||
Service.DefaultOrgVisibilityMode = structs.VisibilityModes[defaultOrgVisibility]
|
||||
Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool()
|
||||
|
||||
Service.UserDeleteWithCommentsMaxTime = sec.Key("USER_DELETE_WITH_COMMENTS_MAX_TIME").MustDuration(0)
|
||||
sec.Key("VALID_SITE_URL_SCHEMES").MustString("http,https")
|
||||
Service.ValidSiteURLSchemes = sec.Key("VALID_SITE_URL_SCHEMES").Strings(",")
|
||||
|
||||
@@ -48,80 +48,83 @@ EMAIL_DOMAIN_BLOCKLIST = d3, *.b
|
||||
func TestLoadServiceVisibilityModes(t *testing.T) {
|
||||
defer test.MockVariableValue(&Service)()
|
||||
|
||||
kases := map[string]func(){
|
||||
visibleTypeSlice := func(s ...structs.VisibilityString) (ret []structs.VisibleType) {
|
||||
for _, v := range s {
|
||||
ret = append(ret, structs.VisibilityModes[v])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
testCases := map[string]func(){
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = limited
|
||||
`: func() {
|
||||
assert.Equal(t, "limited", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`
|
||||
[service]
|
||||
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "limited", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
assert.Equal(t, visibleTypeSlice("limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = my_type
|
||||
ALLOWED_USER_VISIBILITY_MODES = limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "limited", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
assert.Equal(t, visibleTypeSlice("limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = my_type
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = public, limit, privated
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public"}, Service.AllowedUserVisibilityModes)
|
||||
assert.Equal(t, visibleTypeSlice("public"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
}
|
||||
|
||||
for kase, fun := range kases {
|
||||
t.Run(kase, func(t *testing.T) {
|
||||
cfg, err := NewConfigProviderFromData(kase)
|
||||
for tc, fn := range testCases {
|
||||
t.Run(tc, func(t *testing.T) {
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
|
||||
Service.DefaultUserVisibilityMode = structs.VisibleTypePublic
|
||||
cfg, err := NewConfigProviderFromData(tc)
|
||||
assert.NoError(t, err)
|
||||
loadServiceFrom(cfg)
|
||||
fun()
|
||||
// reset
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
|
||||
Service.AllowedUserVisibilityModes = []string{}
|
||||
Service.DefaultUserVisibility = ""
|
||||
Service.DefaultUserVisibilityMode = structs.VisibleTypePublic
|
||||
fn()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ type CreateUserOption struct {
|
||||
// Whether the user has restricted access privileges
|
||||
Restricted *bool `json:"restricted"`
|
||||
// User visibility level: public, limited, or private
|
||||
Visibility UserVisibility `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
Visibility VisibilityString `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
|
||||
// For explicitly setting the user creation timestamp. Useful when users are
|
||||
// migrated from other systems. When omitted, the user's creation timestamp
|
||||
@@ -78,5 +78,5 @@ type EditUserOption struct {
|
||||
// Whether the user has restricted access privileges
|
||||
Restricted *bool `json:"restricted"`
|
||||
// User visibility level: public, limited, or private
|
||||
Visibility UserVisibility `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
Visibility VisibilityString `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type Organization struct {
|
||||
// The location of the organization
|
||||
Location string `json:"location"`
|
||||
// The visibility level of the organization (public, limited, private)
|
||||
Visibility UserVisibility `json:"visibility"`
|
||||
Visibility VisibilityString `json:"visibility"`
|
||||
// Whether repository administrators can change team access
|
||||
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
|
||||
// username of the organization
|
||||
@@ -60,7 +60,7 @@ type CreateOrgOption struct {
|
||||
// The location of the organization
|
||||
Location string `json:"location" binding:"MaxSize(50)"`
|
||||
// possible values are `public` (default), `limited` or `private`
|
||||
Visibility UserVisibility `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
Visibility VisibilityString `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
// Whether repository administrators can change team access
|
||||
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
|
||||
}
|
||||
@@ -78,7 +78,7 @@ type EditOrgOption struct {
|
||||
// The location of the organization
|
||||
Location *string `json:"location" binding:"MaxSize(50)"`
|
||||
// possible values are `public`, `limited` or `private`
|
||||
Visibility *UserVisibility `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
Visibility *VisibilityString `json:"visibility" binding:"In(,public,limited,private)"`
|
||||
// Whether repository administrators can change team access
|
||||
RepoAdminChangeTeamAccess *bool `json:"repo_admin_change_team_access"`
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ type User struct {
|
||||
// the user's description
|
||||
Description string `json:"description"`
|
||||
// User visibility level option: public, limited, private
|
||||
Visibility UserVisibility `json:"visibility"`
|
||||
Visibility VisibilityString `json:"visibility"`
|
||||
|
||||
// user counts
|
||||
Followers int `json:"followers_count"`
|
||||
|
||||
@@ -18,10 +18,10 @@ const (
|
||||
)
|
||||
|
||||
// VisibilityModes is a map of Visibility types
|
||||
var VisibilityModes = map[string]VisibleType{
|
||||
"public": VisibleTypePublic,
|
||||
"limited": VisibleTypeLimited,
|
||||
"private": VisibleTypePrivate,
|
||||
var VisibilityModes = map[VisibilityString]VisibleType{
|
||||
VisibilityStringPublic: VisibleTypePublic,
|
||||
VisibilityStringLimited: VisibleTypeLimited,
|
||||
VisibilityStringPrivate: VisibleTypePrivate,
|
||||
}
|
||||
|
||||
// IsPublic returns true if VisibleType is public
|
||||
@@ -43,27 +43,27 @@ func (vt VisibleType) IsPrivate() bool {
|
||||
func (vt VisibleType) String() string {
|
||||
for k, v := range VisibilityModes {
|
||||
if vt == v {
|
||||
return k
|
||||
return string(k)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ExtractKeysFromMapString provides a slice of keys from map
|
||||
func ExtractKeysFromMapString(in map[string]VisibleType) (keys []string) {
|
||||
for k := range in {
|
||||
keys = append(keys, k)
|
||||
// VisibilityModeKeys returns the visibility mode names (public, limited, private)
|
||||
func VisibilityModeKeys() (keys []string) {
|
||||
for k := range VisibilityModes {
|
||||
keys = append(keys, string(k))
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// UserVisibility defines the visibility level of a user or organization as
|
||||
// rendered in API payloads. The DB representation is VisibleType (int).
|
||||
// swagger:enum UserVisibility
|
||||
type UserVisibility string
|
||||
// VisibilityString defines the visibility level of a user/organization/team as
|
||||
// rendered in API and config payloads. The DB representation is VisibleType (int).
|
||||
// swagger:enum VisibilityString
|
||||
type VisibilityString string
|
||||
|
||||
const (
|
||||
UserVisibilityPublic UserVisibility = "public"
|
||||
UserVisibilityLimited UserVisibility = "limited"
|
||||
UserVisibilityPrivate UserVisibility = "private"
|
||||
VisibilityStringPublic VisibilityString = "public"
|
||||
VisibilityStringLimited VisibilityString = "limited"
|
||||
VisibilityStringPrivate VisibilityString = "private"
|
||||
)
|
||||
|
||||
@@ -3306,7 +3306,6 @@
|
||||
"admin.config.default_enable_timetracking": "Enable Time Tracking by Default",
|
||||
"admin.config.default_allow_only_contributors_to_track_time": "Let Only Contributors Track Time",
|
||||
"admin.config.no_reply_address": "Hidden Email Domain",
|
||||
"admin.config.default_visibility_organization": "Default visibility for new Organizations",
|
||||
"admin.config.default_enable_dependencies": "Enable Issue Dependencies by Default",
|
||||
"admin.config.webhook_config": "Webhook Configuration",
|
||||
"admin.config.queue_length": "Queue Length",
|
||||
|
||||
@@ -48,7 +48,7 @@ func CreateOrg(ctx *context.APIContext) {
|
||||
|
||||
visibility := api.VisibleTypePublic
|
||||
if form.Visibility != "" {
|
||||
visibility = api.VisibilityModes[string(form.Visibility)]
|
||||
visibility = api.VisibilityModes[form.Visibility]
|
||||
}
|
||||
|
||||
org := &organization.Organization{
|
||||
|
||||
@@ -121,7 +121,7 @@ func CreateUser(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
if form.Visibility != "" {
|
||||
visibility := api.VisibilityModes[string(form.Visibility)]
|
||||
visibility := api.VisibilityModes[form.Visibility]
|
||||
overwriteDefault.Visibility = &visibility
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ func EditUser(ctx *context.APIContext) {
|
||||
Description: optional.FromPtr(form.Description),
|
||||
IsActive: optional.FromPtr(form.Active),
|
||||
IsAdmin: user_service.UpdateOptionFieldFromPtr(form.Admin),
|
||||
Visibility: optional.FromMapLookup(api.VisibilityModes, string(form.Visibility)),
|
||||
Visibility: optional.FromMapLookup(api.VisibilityModes, form.Visibility),
|
||||
AllowGitHook: optional.FromPtr(form.AllowGitHook),
|
||||
AllowImportLocal: optional.FromPtr(form.AllowImportLocal),
|
||||
MaxRepoCreation: optional.FromPtr(form.MaxRepoCreation),
|
||||
@@ -469,7 +469,7 @@ func SearchUsers(ctx *context.APIContext) {
|
||||
|
||||
var visible []api.VisibleType
|
||||
visibilityParam := ctx.FormString("visibility")
|
||||
if visibility, ok := api.VisibilityModes[visibilityParam]; ok {
|
||||
if visibility, ok := api.VisibilityModes[api.VisibilityString(visibilityParam)]; ok {
|
||||
visible = []api.VisibleType{visibility}
|
||||
} else if visibilityParam != "" {
|
||||
ctx.APIError(http.StatusUnprocessableEntity, "invalid visibility")
|
||||
|
||||
@@ -269,7 +269,7 @@ func Create(ctx *context.APIContext) {
|
||||
|
||||
visibility := api.VisibleTypePublic
|
||||
if form.Visibility != "" {
|
||||
visibility = api.VisibilityModes[string(form.Visibility)]
|
||||
visibility = api.VisibilityModes[form.Visibility]
|
||||
}
|
||||
|
||||
org := &organization.Organization{
|
||||
@@ -413,7 +413,7 @@ func Edit(ctx *context.APIContext) {
|
||||
Description: optional.FromPtr(form.Description),
|
||||
Website: optional.FromPtr(form.Website),
|
||||
Location: optional.FromPtr(form.Location),
|
||||
Visibility: optional.FromMapLookup(api.VisibilityModes, string(optional.FromPtr(form.Visibility).Value())),
|
||||
Visibility: optional.FromMapLookup(api.VisibilityModes, optional.FromPtr(form.Visibility).Value()),
|
||||
RepoAdminChangeTeamAccess: optional.FromPtr(form.RepoAdminChangeTeamAccess),
|
||||
}
|
||||
if err := user_service.UpdateUser(ctx, ctx.Org.Organization.AsUser(), opts); err != nil {
|
||||
|
||||
@@ -223,7 +223,7 @@ func CreateTeam(ctx *context.APIContext) {
|
||||
IncludesAllRepositories: form.IncludesAllRepositories,
|
||||
CanCreateOrgRepo: form.CanCreateOrgRepo,
|
||||
AccessMode: teamPermission,
|
||||
Visibility: organization.NormalizeTeamVisibility(string(form.Visibility)),
|
||||
Visibility: organization.NormalizeTeamVisibility(form.Visibility),
|
||||
}
|
||||
|
||||
if team.AccessMode < perm.AccessModeAdmin {
|
||||
@@ -302,7 +302,7 @@ func EditTeam(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
if form.Visibility != nil && !team.IsOwnerTeam() {
|
||||
team.Visibility = organization.NormalizeTeamVisibility(string(*form.Visibility))
|
||||
team.Visibility = organization.NormalizeTeamVisibility(*form.Visibility)
|
||||
}
|
||||
|
||||
isAuthChanged := false
|
||||
|
||||
@@ -235,9 +235,10 @@ func SettingsRenamePost(ctx *context.Context) {
|
||||
|
||||
// SettingsChangeVisibilityPost response for change organization visibility
|
||||
func SettingsChangeVisibilityPost(ctx *context.Context) {
|
||||
visibility, ok := structs.VisibilityModes[ctx.FormString("visibility")]
|
||||
visibilityStr := ctx.FormString("visibility")
|
||||
visibility, ok := structs.VisibilityModes[structs.VisibilityString(visibilityStr)]
|
||||
if !ok {
|
||||
ctx.Flash.Error(ctx.Tr("invalid_data", visibility))
|
||||
ctx.Flash.Error(ctx.Tr("invalid_data", visibilityStr))
|
||||
ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(ctx.Org.Organization.Name) + "/settings")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -864,7 +864,7 @@ func ToOrganization(ctx context.Context, org *organization.Organization) *api.Or
|
||||
Description: org.Description,
|
||||
Website: org.Website,
|
||||
Location: org.Location,
|
||||
Visibility: api.UserVisibility(org.Visibility.String()),
|
||||
Visibility: api.VisibilityString(org.Visibility.String()),
|
||||
RepoAdminChangeTeamAccess: org.RepoAdminChangeTeamAccess,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap
|
||||
StarredRepos: user.NumStars,
|
||||
}
|
||||
|
||||
result.Visibility = api.UserVisibility(user.Visibility.String())
|
||||
result.Visibility = api.VisibilityString(user.Visibility.String())
|
||||
|
||||
// hide primary email if API caller is anonymous or user keep email private
|
||||
if signed && (!user.KeepEmailPrivate || authed) {
|
||||
|
||||
@@ -29,11 +29,11 @@ func TestUser_ToUser(t *testing.T) {
|
||||
|
||||
apiUser = toUser(t.Context(), user1, false, false)
|
||||
assert.False(t, apiUser.IsAdmin)
|
||||
assert.Equal(t, api.UserVisibilityPublic, apiUser.Visibility)
|
||||
assert.Equal(t, api.VisibilityStringPublic, apiUser.Visibility)
|
||||
|
||||
user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31, IsAdmin: false, Visibility: api.VisibleTypePrivate})
|
||||
|
||||
apiUser = toUser(t.Context(), user31, true, true)
|
||||
assert.False(t, apiUser.IsAdmin)
|
||||
assert.Equal(t, api.UserVisibilityPrivate, apiUser.Visibility)
|
||||
assert.Equal(t, api.VisibilityStringPrivate, apiUser.Visibility)
|
||||
}
|
||||
|
||||
@@ -155,8 +155,6 @@
|
||||
<dt>{{ctx.Locale.Tr "admin.config.default_allow_only_contributors_to_track_time"}}</dt>
|
||||
<dd>{{svg (Iif .Service.DefaultAllowOnlyContributorsToTrackTime "octicon-check" "octicon-x")}}</dd>
|
||||
{{end}}
|
||||
<dt>{{ctx.Locale.Tr "admin.config.default_visibility_organization"}}</dt>
|
||||
<dd>{{.Service.DefaultOrgVisibility}}</dd>
|
||||
|
||||
<dt>{{ctx.Locale.Tr "admin.config.no_reply_address"}}</dt>
|
||||
<dd>{{if .Service.NoReplyAddress}}{{.Service.NoReplyAddress}}{{else}}-{{end}}</dd>
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
{{ctx.HeadMetaContentSecurityPolicy}}
|
||||
<title>Gitea API</title>
|
||||
<link rel="stylesheet" href="{{ctx.CurrentWebTheme.PublicAssetURI}}">
|
||||
{{/* HINT: SWAGGER-CSS-IMPORT: load swagger styles ahead to avoid flicker (e.g. the swagger-back-link) */}}
|
||||
{{/* HINT: SWAGGER-CSS-IMPORT: load swagger styles ahead to avoid flicker (e.g. the swagger-page-links) */}}
|
||||
{{AssetCSSLinks "web_src/js/swagger.ts" "web_src/css/swagger-standalone.css"}}
|
||||
</head>
|
||||
<body>
|
||||
{{/* TODO: add Help & Glossary to help users understand the API, and explain some concepts like "Owner" */}}
|
||||
<a class="swagger-back-link" href="{{AppSubUrl}}/">{{svg "octicon-reply"}}{{ctx.Locale.Tr "return_to_gitea"}}</a>
|
||||
<div id="swagger-ui" data-source="{{AppSubUrl}}/swagger.v1.json"></div>
|
||||
<div class="swagger-page-links">
|
||||
<a href="{{AppSubUrl}}/openapi3.v1.json" target="_blank">{{svg "octicon-file-code"}}OpenAPI JSON</a>
|
||||
<a href="{{AppSubUrl}}/swagger.v1.json" target="_blank">{{svg "octicon-file-code"}}Swagger JSON</a>
|
||||
<a href="{{AppSubUrl}}/">{{svg "octicon-reply"}}{{ctx.Locale.Tr "return_to_gitea"}}</a>
|
||||
</div>
|
||||
<div id="swagger-ui" data-source="{{AppSubUrl}}/openapi3.v1.json"></div>
|
||||
<footer class="page-footer"></footer>
|
||||
{{ctx.ScriptImport "web_src/js/swagger.ts" "module"}}
|
||||
</body>
|
||||
|
||||
12
templates/swagger/v1_json.tmpl
generated
12
templates/swagger/v1_json.tmpl
generated
@@ -24561,7 +24561,7 @@
|
||||
"limited",
|
||||
"private"
|
||||
],
|
||||
"x-go-enum-desc": "public UserVisibilityPublic\nlimited UserVisibilityLimited\nprivate UserVisibilityPrivate",
|
||||
"x-go-enum-desc": "public VisibilityStringPublic\nlimited VisibilityStringLimited\nprivate VisibilityStringPrivate",
|
||||
"x-go-name": "Visibility"
|
||||
},
|
||||
"website": {
|
||||
@@ -25131,7 +25131,7 @@
|
||||
"limited",
|
||||
"private"
|
||||
],
|
||||
"x-go-enum-desc": "public UserVisibilityPublic\nlimited UserVisibilityLimited\nprivate UserVisibilityPrivate",
|
||||
"x-go-enum-desc": "public VisibilityStringPublic\nlimited VisibilityStringLimited\nprivate VisibilityStringPrivate",
|
||||
"x-go-name": "Visibility"
|
||||
}
|
||||
},
|
||||
@@ -25833,7 +25833,7 @@
|
||||
"limited",
|
||||
"private"
|
||||
],
|
||||
"x-go-enum-desc": "public UserVisibilityPublic\nlimited UserVisibilityLimited\nprivate UserVisibilityPrivate",
|
||||
"x-go-enum-desc": "public VisibilityStringPublic\nlimited VisibilityStringLimited\nprivate VisibilityStringPrivate",
|
||||
"x-go-name": "Visibility"
|
||||
},
|
||||
"website": {
|
||||
@@ -26375,7 +26375,7 @@
|
||||
"limited",
|
||||
"private"
|
||||
],
|
||||
"x-go-enum-desc": "public UserVisibilityPublic\nlimited UserVisibilityLimited\nprivate UserVisibilityPrivate",
|
||||
"x-go-enum-desc": "public VisibilityStringPublic\nlimited VisibilityStringLimited\nprivate VisibilityStringPrivate",
|
||||
"x-go-name": "Visibility"
|
||||
},
|
||||
"website": {
|
||||
@@ -28227,7 +28227,7 @@
|
||||
"limited",
|
||||
"private"
|
||||
],
|
||||
"x-go-enum-desc": "public UserVisibilityPublic\nlimited UserVisibilityLimited\nprivate UserVisibilityPrivate",
|
||||
"x-go-enum-desc": "public VisibilityStringPublic\nlimited VisibilityStringLimited\nprivate VisibilityStringPrivate",
|
||||
"x-go-name": "Visibility"
|
||||
},
|
||||
"website": {
|
||||
@@ -30590,7 +30590,7 @@
|
||||
"limited",
|
||||
"private"
|
||||
],
|
||||
"x-go-enum-desc": "public UserVisibilityPublic\nlimited UserVisibilityLimited\nprivate UserVisibilityPrivate",
|
||||
"x-go-enum-desc": "public VisibilityStringPublic\nlimited VisibilityStringLimited\nprivate VisibilityStringPrivate",
|
||||
"x-go-name": "Visibility"
|
||||
},
|
||||
"website": {
|
||||
|
||||
14
templates/swagger/v1_openapi3_json.tmpl
generated
14
templates/swagger/v1_openapi3_json.tmpl
generated
@@ -4304,7 +4304,7 @@
|
||||
"visibility": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/UserVisibility"
|
||||
"$ref": "#/components/schemas/VisibilityString"
|
||||
}
|
||||
],
|
||||
"description": "possible values are `public` (default), `limited` or `private`"
|
||||
@@ -4845,7 +4845,7 @@
|
||||
"visibility": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/UserVisibility"
|
||||
"$ref": "#/components/schemas/VisibilityString"
|
||||
}
|
||||
],
|
||||
"description": "User visibility level: public, limited, or private"
|
||||
@@ -5549,7 +5549,7 @@
|
||||
"visibility": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/UserVisibility"
|
||||
"$ref": "#/components/schemas/VisibilityString"
|
||||
}
|
||||
],
|
||||
"description": "possible values are `public`, `limited` or `private`"
|
||||
@@ -6075,7 +6075,7 @@
|
||||
"visibility": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/UserVisibility"
|
||||
"$ref": "#/components/schemas/VisibilityString"
|
||||
}
|
||||
],
|
||||
"description": "User visibility level: public, limited, or private"
|
||||
@@ -7949,7 +7949,7 @@
|
||||
"visibility": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/UserVisibility"
|
||||
"$ref": "#/components/schemas/VisibilityString"
|
||||
}
|
||||
],
|
||||
"description": "The visibility level of the organization (public, limited, private)"
|
||||
@@ -10343,7 +10343,7 @@
|
||||
"visibility": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/UserVisibility"
|
||||
"$ref": "#/components/schemas/VisibilityString"
|
||||
}
|
||||
],
|
||||
"description": "User visibility level option: public, limited, private"
|
||||
@@ -10496,7 +10496,7 @@
|
||||
"type": "object",
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"UserVisibility": {
|
||||
"VisibilityString": {
|
||||
"enum": [
|
||||
"public",
|
||||
"limited",
|
||||
|
||||
@@ -128,7 +128,7 @@ func testAPIOrgGeneral(t *testing.T) {
|
||||
apiOrgList := DecodeJSON(t, resp, []*api.Organization{})
|
||||
assert.Len(t, apiOrgList, 13)
|
||||
assert.Equal(t, "Limited Org 36", apiOrgList[1].FullName)
|
||||
assert.Equal(t, api.UserVisibilityLimited, apiOrgList[1].Visibility)
|
||||
assert.Equal(t, api.VisibilityStringLimited, apiOrgList[1].Visibility)
|
||||
|
||||
// accessing without a token will return only public orgs
|
||||
req = NewRequest(t, "GET", "/api/v1/orgs")
|
||||
@@ -137,7 +137,7 @@ func testAPIOrgGeneral(t *testing.T) {
|
||||
apiOrgList = DecodeJSON(t, resp, []*api.Organization{})
|
||||
assert.Len(t, apiOrgList, 9)
|
||||
assert.Equal(t, "org 17", apiOrgList[0].FullName)
|
||||
assert.Equal(t, api.UserVisibilityPublic, apiOrgList[0].Visibility)
|
||||
assert.Equal(t, api.VisibilityStringPublic, apiOrgList[0].Visibility)
|
||||
})
|
||||
|
||||
t.Run("OrgEdit", func(t *testing.T) {
|
||||
@@ -149,7 +149,7 @@ func testAPIOrgGeneral(t *testing.T) {
|
||||
Description: new("new description"),
|
||||
Website: new("https://org3-new-website.example.com"),
|
||||
Location: new("new location"),
|
||||
Visibility: new(api.UserVisibilityLimited),
|
||||
Visibility: new(api.VisibilityStringLimited),
|
||||
Email: new("org3-new-email@example.com"),
|
||||
}
|
||||
req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org3Edit).AddTokenAuth(user1Token)
|
||||
@@ -179,7 +179,7 @@ func testAPIOrgGeneral(t *testing.T) {
|
||||
|
||||
t.Run("OrgEditInvalidVisibility", func(t *testing.T) {
|
||||
org := api.EditOrgOption{
|
||||
Visibility: new(api.UserVisibility("invalid-visibility")),
|
||||
Visibility: new(api.VisibilityString("invalid-visibility")),
|
||||
}
|
||||
req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).AddTokenAuth(user1Token)
|
||||
MakeRequest(t, req, http.StatusUnprocessableEntity)
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestAPIUserSearchLoggedIn(t *testing.T) {
|
||||
for _, user := range results.Data {
|
||||
assert.Contains(t, user.UserName, query)
|
||||
assert.NotEmpty(t, user.Email)
|
||||
assert.Equal(t, api.UserVisibilityPublic, user.Visibility)
|
||||
assert.Equal(t, api.VisibilityStringPublic, user.Visibility)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func TestAPIUserSearchAdminLoggedInUserHidden(t *testing.T) {
|
||||
for _, user := range results.Data {
|
||||
assert.Contains(t, user.UserName, query)
|
||||
assert.NotEmpty(t, user.Email)
|
||||
assert.Equal(t, api.UserVisibilityPrivate, user.Visibility)
|
||||
assert.Equal(t, api.VisibilityStringPrivate, user.Visibility)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,26 +4,57 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.swagger-back-link {
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
.swagger-page-links {
|
||||
/* overlay the top-right of the info block by replicating swagger-ui's ".wrapper" and ".info" metrics */
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1.5rem;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: 1460px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
pointer-events: none; /* only the links themselves are clickable */
|
||||
}
|
||||
|
||||
/* below this width the links would overlap the title, flow above swagger-ui instead */
|
||||
@media (max-width: 991.98px) {
|
||||
.swagger-page-links {
|
||||
position: static;
|
||||
padding: 10px 20px 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* mimic the regular gitea button, the main site CSS is not loaded on this page */
|
||||
.swagger-page-links a {
|
||||
pointer-events: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
border-radius: 4px;
|
||||
background: var(--color-button);
|
||||
border: 1px solid var(--color-light-border);
|
||||
color: var(--color-text);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.swagger-back-link:hover {
|
||||
text-decoration: underline;
|
||||
.swagger-page-links a:hover {
|
||||
background: var(--color-hover);
|
||||
}
|
||||
|
||||
.swagger-back-link svg {
|
||||
color: inherit;
|
||||
.swagger-page-links a:active {
|
||||
background: var(--color-active);
|
||||
}
|
||||
|
||||
.swagger-page-links svg {
|
||||
fill: currentcolor;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.swagger-spec-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user