Merge pull request 'Improve Swagger documentation for user endpoints' (#6050) from JakobDev/forgejo:userswagger into forgejo
Some checks are pending
/ release (push) Waiting to run
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6050
Reviewed-by: Otto <otto@codeberg.org>
This commit is contained in:
Otto 2024-11-28 20:42:19 +00:00
commit 48b91fa31a
24 changed files with 704 additions and 3 deletions

2
go.mod
View file

@ -45,6 +45,7 @@ require (
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e
github.com/go-git/go-git/v5 v5.11.0
github.com/go-ldap/ldap/v3 v3.4.6
github.com/go-openapi/spec v0.20.14
github.com/go-sql-driver/mysql v1.8.1
github.com/go-swagger/go-swagger v0.30.5
github.com/go-testfixtures/testfixtures/v3 v3.12.0
@ -186,7 +187,6 @@ require (
github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/loads v0.21.5 // indirect
github.com/go-openapi/runtime v0.26.2 // indirect
github.com/go-openapi/spec v0.20.14 // indirect
github.com/go-openapi/strfmt v0.22.0 // indirect
github.com/go-openapi/swag v0.22.7 // indirect
github.com/go-openapi/validate v0.22.6 // indirect

View file

@ -69,6 +69,10 @@ func ListMyOrgs(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/OrganizationList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"

View file

@ -91,6 +91,10 @@ func ListUserTeams(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/TeamList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
teams, count, err := organization.SearchTeam(ctx, &organization.SearchTeamOptions{
ListOptions: utils.GetListOptions(ctx),

View file

@ -217,6 +217,10 @@ func GetStopwatches(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/StopWatchList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
sws, err := issues_model.GetUserStopwatches(ctx, ctx.Doer.ID, utils.GetListOptions(ctx))
if err != nil {

View file

@ -599,6 +599,10 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/TrackedTimeList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
opts := &issues_model.FindTrackedTimesOptions{
ListOptions: utils.GetListOptions(ctx),

View file

@ -304,6 +304,10 @@ func Create(ctx *context.APIContext) {
// "$ref": "#/responses/Repository"
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "409":
// description: The repository with the same name already exists.
// "413":

View file

@ -44,6 +44,10 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
// description: response when updating a secret
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -88,6 +92,10 @@ func DeleteSecret(ctx *context.APIContext) {
// description: delete one secret of the user
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -132,6 +140,10 @@ func CreateVariable(ctx *context.APIContext) {
// description: response when creating a variable
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -191,6 +203,10 @@ func UpdateVariable(ctx *context.APIContext) {
// description: response when updating a variable
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -244,6 +260,10 @@ func DeleteVariable(ctx *context.APIContext) {
// description: response when deleting a variable
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -279,6 +299,10 @@ func GetVariable(ctx *context.APIContext) {
// "$ref": "#/responses/ActionVariable"
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -326,6 +350,10 @@ func ListVariables(ctx *context.APIContext) {
// "$ref": "#/responses/VariableList"
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"

View file

@ -46,6 +46,8 @@ func ListAccessTokens(ctx *context.APIContext) {
// "$ref": "#/responses/AccessTokenList"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
opts := auth_model.ListAccessTokensOptions{UserID: ctx.ContextUser.ID, ListOptions: utils.GetListOptions(ctx)}
@ -95,6 +97,8 @@ func CreateAccessToken(ctx *context.APIContext) {
// "$ref": "#/responses/error"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
form := web.GetForm(ctx).(*api.CreateAccessTokenOption)
@ -224,6 +228,10 @@ func CreateOauth2Application(ctx *context.APIContext) {
// "$ref": "#/responses/OAuth2Application"
// "400":
// "$ref": "#/responses/error"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions)
@ -266,6 +274,10 @@ func ListOauth2Applications(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/OAuth2ApplicationList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
apps, total, err := db.FindAndCount[auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{
ListOptions: utils.GetListOptions(ctx),
@ -303,6 +315,10 @@ func DeleteOauth2Application(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
appID := ctx.ParamsInt64(":id")
@ -335,6 +351,10 @@ func GetOauth2Application(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/OAuth2Application"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
appID := ctx.ParamsInt64(":id")
@ -379,6 +399,10 @@ func UpdateOauth2Application(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/OAuth2Application"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
appID := ctx.ParamsInt64(":id")

View file

@ -28,6 +28,10 @@ func UpdateAvatar(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
form := web.GetForm(ctx).(*api.UpdateUserAvatarOption)
content, err := base64.StdEncoding.DecodeString(form.Image)
@ -55,6 +59,10 @@ func DeleteAvatar(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
err := user_service.DeleteAvatar(ctx, ctx.Doer)
if err != nil {
ctx.Error(http.StatusInternalServerError, "DeleteAvatar", err)

View file

@ -27,6 +27,10 @@ func ListEmails(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/EmailList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
emails, err := user_model.GetEmailAddresses(ctx, ctx.Doer.ID)
if err != nil {
@ -55,6 +59,10 @@ func AddEmail(ctx *context.APIContext) {
// responses:
// '201':
// "$ref": "#/responses/EmailList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "422":
// "$ref": "#/responses/validationError"
@ -112,6 +120,10 @@ func DeleteEmail(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"

View file

@ -53,6 +53,10 @@ func ListMyFollowers(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/UserList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
listUserFollowers(ctx, ctx.Doer)
}
@ -117,6 +121,10 @@ func ListMyFollowing(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/UserList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
listUserFollowing(ctx, ctx.Doer)
}
@ -173,6 +181,10 @@ func CheckMyFollowing(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -222,10 +234,12 @@ func Follow(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "404":
// "$ref": "#/responses/notFound"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
if err := user_model.FollowUser(ctx, ctx.Doer.ID, ctx.ContextUser.ID); err != nil {
if errors.Is(err, user_model.ErrBlockedByUser) {
@ -252,6 +266,10 @@ func Unfollow(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"

View file

@ -92,6 +92,10 @@ func ListMyGPGKeys(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/GPGKeyList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
listGPGKeys(ctx, ctx.Doer.ID, utils.GetListOptions(ctx))
}
@ -113,6 +117,10 @@ func GetGPGKey(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/GPGKey"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -164,6 +172,10 @@ func GetVerificationToken(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/string"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -183,6 +195,10 @@ func VerifyUserGPGKey(ctx *context.APIContext) {
// responses:
// "201":
// "$ref": "#/responses/GPGKey"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
// "422":
@ -244,6 +260,10 @@ func CreateGPGKey(ctx *context.APIContext) {
// responses:
// "201":
// "$ref": "#/responses/GPGKey"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
// "422":
@ -270,6 +290,8 @@ func DeleteGPGKey(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":

View file

@ -32,6 +32,10 @@ func ListHooks(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/HookList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
utils.ListOwnerHooks(
ctx,
@ -56,6 +60,10 @@ func GetHook(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/Hook"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
hook, err := utils.GetOwnerHook(ctx, ctx.Doer.ID, ctx.ParamsInt64("id"))
if err != nil {
@ -93,6 +101,10 @@ func CreateHook(ctx *context.APIContext) {
// responses:
// "201":
// "$ref": "#/responses/Hook"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
utils.AddOwnerHook(
ctx,
@ -124,6 +136,10 @@ func EditHook(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/Hook"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
utils.EditOwnerHook(
ctx,
@ -150,6 +166,10 @@ func DeleteHook(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
utils.DeleteOwnerHook(
ctx,

View file

@ -121,6 +121,10 @@ func ListMyPublicKeys(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/PublicKeyList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
listPublicKeys(ctx, ctx.Doer)
}
@ -176,6 +180,10 @@ func GetPublicKey(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/PublicKey"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -240,6 +248,10 @@ func CreatePublicKey(ctx *context.APIContext) {
// responses:
// "201":
// "$ref": "#/responses/PublicKey"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "422":
// "$ref": "#/responses/validationError"
@ -264,6 +276,8 @@ func DeletePublicKey(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":

View file

@ -18,6 +18,8 @@ func GetQuota(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/QuotaInfo"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
@ -34,6 +36,8 @@ func CheckQuota(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/boolean"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "422":
@ -61,6 +65,8 @@ func ListQuotaAttachments(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/QuotaUsedAttachmentList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
@ -86,6 +92,8 @@ func ListQuotaPackages(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/QuotaUsedPackageList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
@ -111,6 +119,8 @@ func ListQuotaArtifacts(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/QuotaUsedArtifactList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"

View file

@ -106,6 +106,10 @@ func ListMyRepos(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/RepositoryList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "422":
// "$ref": "#/responses/validationError"

View file

@ -21,6 +21,10 @@ func GetRegistrationToken(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/RegistrationToken"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
shared.GetRegistrationToken(ctx, ctx.Doer.ID, 0)
}

View file

@ -24,6 +24,10 @@ func GetUserSettings(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/UserSettings"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
ctx.JSON(http.StatusOK, convert.User2UserSettings(ctx.Doer))
}
@ -42,6 +46,10 @@ func UpdateUserSettings(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/UserSettings"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
form := web.GetForm(ctx).(*api.UserSettingsOptions)

View file

@ -96,6 +96,10 @@ func GetMyStarredRepos(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/RepositoryList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
repos, err := getStarredRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx))
if err != nil {
@ -125,6 +129,10 @@ func IsStarring(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -154,6 +162,10 @@ func Star(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
@ -185,6 +197,10 @@ func Unstar(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"

View file

@ -137,6 +137,10 @@ func GetAuthenticatedUser(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/User"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
ctx.JSON(http.StatusOK, convert.ToUser(ctx, ctx.Doer, ctx.Doer))
}
@ -244,6 +248,10 @@ func ListBlockedUsers(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/BlockedUserList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
utils.ListUserBlockedUsers(ctx, ctx.Doer)
}
@ -264,6 +272,10 @@ func BlockUser(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
// "422":
@ -293,6 +305,10 @@ func UnblockUser(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
// "422":

View file

@ -91,6 +91,10 @@ func GetMyWatchedRepos(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/RepositoryList"
// "401":
// "$ref": "#/responses/unauthorized"
// "403":
// "$ref": "#/responses/forbidden"
repos, total, err := getWatchedRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx))
if err != nil {

View file

@ -99,6 +99,17 @@ type swaggerAPIInvalidTopicsError struct {
// swagger:response empty
type APIEmpty struct{}
type APIUnauthorizedError struct {
APIError
}
// APIUnauthorizedError is a unauthorized error response
// swagger:response unauthorized
type swaggerAPUnauthorizedError struct {
// in:body
Body APIUnauthorizedError `json:"body"`
}
type APIForbiddenError struct {
APIError
}

View file

@ -17318,6 +17318,12 @@
"responses": {
"200": {
"$ref": "#/responses/User"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -17335,6 +17341,12 @@
"responses": {
"200": {
"$ref": "#/responses/RegistrationToken"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -17378,6 +17390,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17411,6 +17429,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17448,6 +17472,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17480,6 +17510,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17523,6 +17559,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17566,6 +17608,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17599,6 +17647,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17632,6 +17686,12 @@
"responses": {
"200": {
"$ref": "#/responses/OAuth2ApplicationList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -17660,6 +17720,12 @@
},
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -17688,6 +17754,12 @@
"200": {
"$ref": "#/responses/OAuth2Application"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17716,6 +17788,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17752,6 +17830,12 @@
"200": {
"$ref": "#/responses/OAuth2Application"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17780,6 +17864,12 @@
"responses": {
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -17795,6 +17885,12 @@
"responses": {
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -17822,6 +17918,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
},
@ -17844,6 +17946,12 @@
"responses": {
"200": {
"$ref": "#/responses/EmailList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -17869,6 +17977,12 @@
"201": {
"$ref": "#/responses/EmailList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"422": {
"$ref": "#/responses/validationError"
}
@ -17896,6 +18010,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -17929,6 +18049,12 @@
"responses": {
"200": {
"$ref": "#/responses/UserList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -17960,6 +18086,12 @@
"responses": {
"200": {
"$ref": "#/responses/UserList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -17984,6 +18116,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18008,6 +18146,9 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
@ -18035,6 +18176,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18055,6 +18202,12 @@
"200": {
"$ref": "#/responses/string"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18078,6 +18231,12 @@
"201": {
"$ref": "#/responses/GPGKey"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
},
@ -18114,6 +18273,12 @@
"responses": {
"200": {
"$ref": "#/responses/GPGKeyList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -18142,6 +18307,12 @@
"201": {
"$ref": "#/responses/GPGKey"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
},
@ -18175,6 +18346,12 @@
"200": {
"$ref": "#/responses/GPGKey"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18203,6 +18380,9 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
@ -18239,6 +18419,12 @@
"responses": {
"200": {
"$ref": "#/responses/HookList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -18267,6 +18453,12 @@
"responses": {
"201": {
"$ref": "#/responses/Hook"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -18294,6 +18486,12 @@
"responses": {
"200": {
"$ref": "#/responses/Hook"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -18319,6 +18517,12 @@
"responses": {
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -18354,6 +18558,12 @@
"responses": {
"200": {
"$ref": "#/responses/Hook"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -18391,6 +18601,12 @@
"responses": {
"200": {
"$ref": "#/responses/PublicKeyList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -18419,6 +18635,12 @@
"201": {
"$ref": "#/responses/PublicKey"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"422": {
"$ref": "#/responses/validationError"
}
@ -18449,6 +18671,12 @@
"200": {
"$ref": "#/responses/PublicKey"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18477,6 +18705,9 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
@ -18513,6 +18744,12 @@
"responses": {
"200": {
"$ref": "#/responses/BlockedUserList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -18545,6 +18782,12 @@
"200": {
"$ref": "#/responses/OrganizationList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18565,6 +18808,9 @@
"200": {
"$ref": "#/responses/QuotaInfo"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
@ -18599,6 +18845,9 @@
"200": {
"$ref": "#/responses/QuotaUsedArtifactList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
@ -18633,6 +18882,9 @@
"200": {
"$ref": "#/responses/QuotaUsedAttachmentList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
@ -18653,6 +18905,9 @@
"200": {
"$ref": "#/responses/boolean"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
@ -18690,6 +18945,9 @@
"200": {
"$ref": "#/responses/QuotaUsedPackageList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
@ -18730,6 +18988,12 @@
"200": {
"$ref": "#/responses/RepositoryList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"422": {
"$ref": "#/responses/validationError"
}
@ -18764,6 +19028,12 @@
"400": {
"$ref": "#/responses/error"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"409": {
"description": "The repository with the same name already exists."
},
@ -18789,6 +19059,12 @@
"responses": {
"200": {
"$ref": "#/responses/UserSettings"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
},
@ -18813,6 +19089,12 @@
"responses": {
"200": {
"$ref": "#/responses/UserSettings"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -18844,6 +19126,12 @@
"responses": {
"200": {
"$ref": "#/responses/RepositoryList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -18875,6 +19163,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18906,6 +19200,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18937,6 +19237,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
@ -18973,6 +19279,12 @@
"responses": {
"200": {
"$ref": "#/responses/StopWatchList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -19004,6 +19316,12 @@
"responses": {
"200": {
"$ref": "#/responses/RepositoryList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -19035,6 +19353,12 @@
"responses": {
"200": {
"$ref": "#/responses/TeamList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -19080,6 +19404,12 @@
"responses": {
"200": {
"$ref": "#/responses/TrackedTimeList"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
}
}
}
@ -19107,6 +19437,12 @@
"204": {
"$ref": "#/responses/empty"
},
"401": {
"$ref": "#/responses/unauthorized"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
},
@ -19729,6 +20065,9 @@
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
}
},
@ -19769,6 +20108,9 @@
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
}
}
@ -19915,6 +20257,20 @@
},
"x-go-package": "code.gitea.io/gitea/services/context"
},
"APIUnauthorizedError": {
"type": "object",
"properties": {
"message": {
"type": "string",
"x-go-name": "Message"
},
"url": {
"type": "string",
"x-go-name": "URL"
}
},
"x-go-package": "code.gitea.io/gitea/services/context"
},
"APIValidationError": {
"type": "object",
"properties": {
@ -28495,6 +28851,12 @@
"type": "string"
}
},
"unauthorized": {
"description": "APIUnauthorizedError is a unauthorized error response",
"schema": {
"$ref": "#/definitions/APIUnauthorizedError"
}
},
"validationError": {
"description": "APIValidationError is error format response related to input validation",
"schema": {

View file

@ -0,0 +1,100 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"net/http"
"strings"
"testing"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/tests"
swagger_spec "github.com/go-openapi/spec"
"github.com/stretchr/testify/require"
)
func getSwagger(t *testing.T) *swagger_spec.Swagger {
t.Helper()
resp := MakeRequest(t, NewRequest(t, "GET", "/swagger.v1.json"), http.StatusOK)
swagger := new(swagger_spec.Swagger)
decoder := json.NewDecoder(resp.Body)
require.NoError(t, decoder.Decode(swagger))
return swagger
}
func checkSwaggerMethodResponse(t *testing.T, path string, method *swagger_spec.Operation, name string, statusCode int, responseType string) {
t.Helper()
if method == nil {
return
}
val, ok := method.Responses.StatusCodeResponses[statusCode]
if !ok {
t.Errorf("%s %s is missing response status code %d in swagger", name, path, statusCode)
return
}
if responseType != val.Ref.String() {
t.Errorf("%s %s has %s response type for %d in swagger (expected %s)", name, path, val.Ref.String(), statusCode, responseType)
}
}
func checkSwaggerPathResponse(t *testing.T, paths map[string]swagger_spec.PathItem, pathMatch string, statusCode int, responseType string) {
t.Helper()
for pathName, pathData := range paths {
if pathName != pathMatch {
continue
}
checkSwaggerMethodResponse(t, pathName, pathData.Get, "GET", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Put, "PUT", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Post, "POST", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Patch, "PATCH", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Delete, "DELETE", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Options, "OPTIONS", statusCode, responseType)
return
}
}
func checkSwaggerRouteResponse(t *testing.T, paths map[string]swagger_spec.PathItem, prefix string, statusCode int, responseType string) {
t.Helper()
for pathName, pathData := range paths {
if !strings.HasPrefix(pathName, prefix) {
continue
}
checkSwaggerMethodResponse(t, pathName, pathData.Get, "GET", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Put, "PUT", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Post, "POST", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Patch, "PATCH", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Delete, "DELETE", statusCode, responseType)
checkSwaggerMethodResponse(t, pathName, pathData.Options, "OPTIONS", statusCode, responseType)
}
}
func TestSwaggerUserRoute(t *testing.T) {
defer tests.PrepareTestEnv(t)()
swagger := getSwagger(t)
checkSwaggerPathResponse(t, swagger.Paths.Paths, "/user", http.StatusUnauthorized, "#/responses/unauthorized")
checkSwaggerRouteResponse(t, swagger.Paths.Paths, "/user/", http.StatusUnauthorized, "#/responses/unauthorized")
}
func TestSwaggerUsersRoute(t *testing.T) {
defer tests.PrepareTestEnv(t)()
swagger := getSwagger(t)
checkSwaggerRouteResponse(t, swagger.Paths.Paths, "/users/{username}", http.StatusNotFound, "#/responses/notFound")
}