Swagger info corrections (#9441)

* use numbers and not http.Status___ enum

* fix test

* add many missing swagger responses

* code format

* Deletion Sould return 204 ...

* error handling improvements

* if special error type ... then add it to swagger too

* one smal nit

* invalidTopicsError is []string

* valid swagger specification 2.0
 - if you add responses swagger can tell you if you do it right 👍

* use ctx.InternalServerError

* Revert "use numbers and not http.Status___ enum"

This reverts commit b1ff386e24.

* use http.Status* enum everywhere
This commit is contained in:
6543
2019-12-20 18:07:12 +01:00
committed by Lauris BH
parent 050a8af424
commit 2848c5eb8f
52 changed files with 1262 additions and 648 deletions

View File

@ -5,6 +5,8 @@
package org
import (
"net/http"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
@ -28,17 +30,18 @@ func ListHooks(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/HookList"
org := ctx.Org.Organization
orgHooks, err := models.GetWebhooksByOrgID(org.ID)
if err != nil {
ctx.Error(500, "GetWebhooksByOrgID", err)
ctx.Error(http.StatusInternalServerError, "GetWebhooksByOrgID", err)
return
}
hooks := make([]*api.Hook, len(orgHooks))
for i, hook := range orgHooks {
hooks[i] = convert.ToHook(org.HomeLink(), hook)
}
ctx.JSON(200, hooks)
ctx.JSON(http.StatusOK, hooks)
}
// GetHook get an organization's hook by id
@ -63,13 +66,14 @@ func GetHook(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/Hook"
org := ctx.Org.Organization
hookID := ctx.ParamsInt64(":id")
hook, err := utils.GetOrgHook(ctx, org.ID, hookID)
if err != nil {
return
}
ctx.JSON(200, convert.ToHook(org.HomeLink(), hook))
ctx.JSON(http.StatusOK, convert.ToHook(org.HomeLink(), hook))
}
// CreateHook create a hook for an organization
@ -159,15 +163,16 @@ func DeleteHook(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
org := ctx.Org.Organization
hookID := ctx.ParamsInt64(":id")
if err := models.DeleteWebhookByOrgID(org.ID, hookID); err != nil {
if models.IsErrWebhookNotExist(err) {
ctx.NotFound()
} else {
ctx.Error(500, "DeleteWebhookByOrgID", err)
ctx.Error(http.StatusInternalServerError, "DeleteWebhookByOrgID", err)
}
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}

View File

@ -6,6 +6,7 @@ package org
import (
"fmt"
"net/http"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
@ -23,7 +24,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) {
PublicOnly: publicOnly,
})
if err != nil {
ctx.Error(500, "GetUsersByIDs", err)
ctx.Error(http.StatusInternalServerError, "GetUsersByIDs", err)
return
}
@ -31,7 +32,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) {
for i, member := range members {
apiMembers[i] = convert.ToUser(member, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
}
ctx.JSON(200, apiMembers)
ctx.JSON(http.StatusOK, apiMembers)
}
// ListMembers list an organization's members
@ -50,11 +51,12 @@ func ListMembers(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/UserList"
publicOnly := true
if ctx.User != nil {
isMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID)
if err != nil {
ctx.Error(500, "IsOrgMember", err)
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
return
}
publicOnly = !isMember
@ -78,6 +80,7 @@ func ListPublicMembers(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/UserList"
listMembers(ctx, true)
}
@ -100,8 +103,11 @@ func IsMember(ctx *context.APIContext) {
// responses:
// "204":
// description: user is a member
// "302":
// description: redirection to /orgs/{org}/public_members/{username}
// "404":
// description: user is not a member
userToCheck := user.GetUserByParams(ctx)
if ctx.Written() {
return
@ -109,14 +115,14 @@ func IsMember(ctx *context.APIContext) {
if ctx.User != nil {
userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID)
if err != nil {
ctx.Error(500, "IsOrgMember", err)
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
return
} else if userIsMember {
userToCheckIsMember, err := ctx.Org.Organization.IsOrgMember(userToCheck.ID)
if err != nil {
ctx.Error(500, "IsOrgMember", err)
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
} else if userToCheckIsMember {
ctx.Status(204)
ctx.Status(http.StatusNoContent)
} else {
ctx.NotFound()
}
@ -153,12 +159,13 @@ func IsPublicMember(ctx *context.APIContext) {
// description: user is a public member
// "404":
// description: user is not a public member
userToCheck := user.GetUserByParams(ctx)
if ctx.Written() {
return
}
if userToCheck.IsPublicMember(ctx.Org.Organization.ID) {
ctx.Status(204)
ctx.Status(http.StatusNoContent)
} else {
ctx.NotFound()
}
@ -185,20 +192,23 @@ func PublicizeMember(ctx *context.APIContext) {
// responses:
// "204":
// description: membership publicized
// "403":
// "$ref": "#/responses/forbidden"
userToPublicize := user.GetUserByParams(ctx)
if ctx.Written() {
return
}
if userToPublicize.ID != ctx.User.ID {
ctx.Error(403, "", "Cannot publicize another member")
ctx.Error(http.StatusForbidden, "", "Cannot publicize another member")
return
}
err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToPublicize.ID, true)
if err != nil {
ctx.Error(500, "ChangeOrgUserStatus", err)
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}
// ConcealMember make a member's membership not public
@ -222,20 +232,23 @@ func ConcealMember(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "403":
// "$ref": "#/responses/forbidden"
userToConceal := user.GetUserByParams(ctx)
if ctx.Written() {
return
}
if userToConceal.ID != ctx.User.ID {
ctx.Error(403, "", "Cannot conceal another member")
ctx.Error(http.StatusForbidden, "", "Cannot conceal another member")
return
}
err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToConceal.ID, false)
if err != nil {
ctx.Error(500, "ChangeOrgUserStatus", err)
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}
// DeleteMember remove a member from an organization
@ -259,12 +272,13 @@ func DeleteMember(ctx *context.APIContext) {
// responses:
// "204":
// description: member removed
member := user.GetUserByParams(ctx)
if ctx.Written() {
return
}
if err := ctx.Org.Organization.RemoveMember(member.ID); err != nil {
ctx.Error(500, "RemoveMember", err)
ctx.Error(http.StatusInternalServerError, "RemoveMember", err)
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}

View File

@ -6,6 +6,8 @@
package org
import (
"net/http"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
@ -15,7 +17,7 @@ import (
func listUserOrgs(ctx *context.APIContext, u *models.User, all bool) {
if err := u.GetOrganizations(all); err != nil {
ctx.Error(500, "GetOrganizations", err)
ctx.Error(http.StatusInternalServerError, "GetOrganizations", err)
return
}
@ -23,7 +25,7 @@ func listUserOrgs(ctx *context.APIContext, u *models.User, all bool) {
for i := range u.Orgs {
apiOrgs[i] = convert.ToOrganization(u.Orgs[i])
}
ctx.JSON(200, &apiOrgs)
ctx.JSON(http.StatusOK, &apiOrgs)
}
// ListMyOrgs list all my orgs
@ -36,6 +38,7 @@ func ListMyOrgs(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/OrganizationList"
listUserOrgs(ctx, ctx.User, true)
}
@ -55,6 +58,7 @@ func ListUserOrgs(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/OrganizationList"
u := user.GetUserByParams(ctx)
if ctx.Written() {
return
@ -85,7 +89,7 @@ func Create(ctx *context.APIContext, form api.CreateOrgOption) {
// "$ref": "#/responses/validationError"
if !ctx.User.CanCreateOrganization() {
ctx.Error(403, "Create organization not allowed", nil)
ctx.Error(http.StatusForbidden, "Create organization not allowed", nil)
return
}
@ -109,14 +113,14 @@ func Create(ctx *context.APIContext, form api.CreateOrgOption) {
if models.IsErrUserAlreadyExist(err) ||
models.IsErrNameReserved(err) ||
models.IsErrNamePatternNotAllowed(err) {
ctx.Error(422, "", err)
ctx.Error(http.StatusUnprocessableEntity, "", err)
} else {
ctx.Error(500, "CreateOrganization", err)
ctx.Error(http.StatusInternalServerError, "CreateOrganization", err)
}
return
}
ctx.JSON(201, convert.ToOrganization(org))
ctx.JSON(http.StatusCreated, convert.ToOrganization(org))
}
// Get get an organization
@ -135,11 +139,12 @@ func Get(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/Organization"
if !models.HasOrgVisible(ctx.Org.Organization, ctx.User) {
ctx.NotFound("HasOrgVisible", nil)
return
}
ctx.JSON(200, convert.ToOrganization(ctx.Org.Organization))
ctx.JSON(http.StatusOK, convert.ToOrganization(ctx.Org.Organization))
}
// Edit change an organization's information
@ -165,6 +170,7 @@ func Edit(ctx *context.APIContext, form api.EditOrgOption) {
// responses:
// "200":
// "$ref": "#/responses/Organization"
org := ctx.Org.Organization
org.FullName = form.FullName
org.Description = form.Description
@ -174,11 +180,11 @@ func Edit(ctx *context.APIContext, form api.EditOrgOption) {
org.Visibility = api.VisibilityModes[form.Visibility]
}
if err := models.UpdateUserCols(org, "full_name", "description", "website", "location", "visibility"); err != nil {
ctx.Error(500, "EditOrganization", err)
ctx.Error(http.StatusInternalServerError, "EditOrganization", err)
return
}
ctx.JSON(200, convert.ToOrganization(org))
ctx.JSON(http.StatusOK, convert.ToOrganization(org))
}
//Delete an organization
@ -197,9 +203,10 @@ func Delete(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
if err := models.DeleteOrganization(ctx.Org.Organization); err != nil {
ctx.Error(500, "DeleteOrganization", err)
ctx.Error(http.StatusInternalServerError, "DeleteOrganization", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}

View File

@ -6,6 +6,7 @@
package org
import (
"net/http"
"strings"
"code.gitea.io/gitea/models"
@ -32,22 +33,23 @@ func ListTeams(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/TeamList"
org := ctx.Org.Organization
if err := org.GetTeams(); err != nil {
ctx.Error(500, "GetTeams", err)
ctx.Error(http.StatusInternalServerError, "GetTeams", err)
return
}
apiTeams := make([]*api.Team, len(org.Teams))
for i := range org.Teams {
if err := org.Teams[i].GetUnits(); err != nil {
ctx.Error(500, "GetUnits", err)
ctx.Error(http.StatusInternalServerError, "GetUnits", err)
return
}
apiTeams[i] = convert.ToTeam(org.Teams[i])
}
ctx.JSON(200, apiTeams)
ctx.JSON(http.StatusOK, apiTeams)
}
// ListUserTeams list all the teams a user belongs to
@ -60,9 +62,10 @@ func ListUserTeams(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/TeamList"
teams, err := models.GetUserTeams(ctx.User.ID)
if err != nil {
ctx.Error(500, "GetUserTeams", err)
ctx.Error(http.StatusInternalServerError, "GetUserTeams", err)
return
}
@ -73,7 +76,7 @@ func ListUserTeams(ctx *context.APIContext) {
if !ok {
org, err := models.GetUserByID(teams[i].OrgID)
if err != nil {
ctx.Error(500, "GetUserByID", err)
ctx.Error(http.StatusInternalServerError, "GetUserByID", err)
return
}
apiOrg = convert.ToOrganization(org)
@ -82,7 +85,7 @@ func ListUserTeams(ctx *context.APIContext) {
apiTeams[i] = convert.ToTeam(teams[i])
apiTeams[i].Organization = apiOrg
}
ctx.JSON(200, apiTeams)
ctx.JSON(http.StatusOK, apiTeams)
}
// GetTeam api for get a team
@ -102,7 +105,8 @@ func GetTeam(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/Team"
ctx.JSON(200, convert.ToTeam(ctx.Org.Team))
ctx.JSON(http.StatusOK, convert.ToTeam(ctx.Org.Team))
}
// CreateTeam api for create a team
@ -127,6 +131,9 @@ func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) {
// responses:
// "201":
// "$ref": "#/responses/Team"
// "422":
// "$ref": "#/responses/validationError"
team := &models.Team{
OrgID: ctx.Org.Organization.ID,
Name: form.Name,
@ -151,14 +158,14 @@ func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) {
if err := models.NewTeam(team); err != nil {
if models.IsErrTeamAlreadyExist(err) {
ctx.Error(422, "", err)
ctx.Error(http.StatusUnprocessableEntity, "", err)
} else {
ctx.Error(500, "NewTeam", err)
ctx.Error(http.StatusInternalServerError, "NewTeam", err)
}
return
}
ctx.JSON(201, convert.ToTeam(team))
ctx.JSON(http.StatusCreated, convert.ToTeam(team))
}
// EditTeam api for edit a team
@ -183,6 +190,7 @@ func EditTeam(ctx *context.APIContext, form api.EditTeamOption) {
// responses:
// "200":
// "$ref": "#/responses/Team"
team := ctx.Org.Team
team.Description = form.Description
unitTypes := models.FindUnitTypes(form.Units...)
@ -218,10 +226,10 @@ func EditTeam(ctx *context.APIContext, form api.EditTeamOption) {
}
if err := models.UpdateTeam(team, isAuthChanged, isIncludeAllChanged); err != nil {
ctx.Error(500, "EditTeam", err)
ctx.Error(http.StatusInternalServerError, "EditTeam", err)
return
}
ctx.JSON(200, convert.ToTeam(team))
ctx.JSON(http.StatusOK, convert.ToTeam(team))
}
// DeleteTeam api for delete a team
@ -239,11 +247,12 @@ func DeleteTeam(ctx *context.APIContext) {
// responses:
// "204":
// description: team deleted
if err := models.DeleteTeam(ctx.Org.Team); err != nil {
ctx.Error(500, "DeleteTeam", err)
ctx.Error(http.StatusInternalServerError, "DeleteTeam", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}
// GetTeamMembers api for get a team's members
@ -263,9 +272,10 @@ func GetTeamMembers(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/UserList"
isMember, err := models.IsOrganizationMember(ctx.Org.Team.OrgID, ctx.User.ID)
if err != nil {
ctx.Error(500, "IsOrganizationMember", err)
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
return
} else if !isMember {
ctx.NotFound()
@ -273,14 +283,14 @@ func GetTeamMembers(ctx *context.APIContext) {
}
team := ctx.Org.Team
if err := team.GetMembers(); err != nil {
ctx.Error(500, "GetTeamMembers", err)
ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err)
return
}
members := make([]*api.User, len(team.Members))
for i, member := range team.Members {
members[i] = convert.ToUser(member, ctx.IsSigned, ctx.User.IsAdmin)
}
ctx.JSON(200, members)
ctx.JSON(http.StatusOK, members)
}
// GetTeamMember api for get a particular member of team
@ -305,6 +315,9 @@ func GetTeamMember(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/User"
// "404":
// "$ref": "#/responses/notFound"
u := user.GetUserByParams(ctx)
if ctx.Written() {
return
@ -312,13 +325,13 @@ func GetTeamMember(ctx *context.APIContext) {
teamID := ctx.ParamsInt64("teamid")
isTeamMember, err := models.IsUserInTeams(u.ID, []int64{teamID})
if err != nil {
ctx.Error(500, "IsUserInTeams", err)
ctx.Error(http.StatusInternalServerError, "IsUserInTeams", err)
return
} else if !isTeamMember {
ctx.NotFound()
return
}
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
}
// AddTeamMember api for add a member to a team
@ -343,15 +356,18 @@ func AddTeamMember(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "404":
// "$ref": "#/responses/notFound"
u := user.GetUserByParams(ctx)
if ctx.Written() {
return
}
if err := ctx.Org.Team.AddMember(u.ID); err != nil {
ctx.Error(500, "AddMember", err)
ctx.Error(http.StatusInternalServerError, "AddMember", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}
// RemoveTeamMember api for remove one member from a team
@ -376,16 +392,19 @@ func RemoveTeamMember(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "404":
// "$ref": "#/responses/notFound"
u := user.GetUserByParams(ctx)
if ctx.Written() {
return
}
if err := ctx.Org.Team.RemoveMember(u.ID); err != nil {
ctx.Error(500, "RemoveMember", err)
ctx.Error(http.StatusInternalServerError, "RemoveMember", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}
// GetTeamRepos api for get a team's repos
@ -405,20 +424,21 @@ func GetTeamRepos(ctx *context.APIContext) {
// responses:
// "200":
// "$ref": "#/responses/RepositoryList"
team := ctx.Org.Team
if err := team.GetRepositories(); err != nil {
ctx.Error(500, "GetTeamRepos", err)
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
}
repos := make([]*api.Repository, len(team.Repos))
for i, repo := range team.Repos {
access, err := models.AccessLevel(ctx.User, repo)
if err != nil {
ctx.Error(500, "GetTeamRepos", err)
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
return
}
repos[i] = repo.APIFormat(access)
}
ctx.JSON(200, repos)
ctx.JSON(http.StatusOK, repos)
}
// getRepositoryByParams get repository by a team's organization ID and repo name
@ -428,7 +448,7 @@ func getRepositoryByParams(ctx *context.APIContext) *models.Repository {
if models.IsErrRepoNotExist(err) {
ctx.NotFound()
} else {
ctx.Error(500, "GetRepositoryByName", err)
ctx.Error(http.StatusInternalServerError, "GetRepositoryByName", err)
}
return nil
}
@ -462,22 +482,25 @@ func AddTeamRepository(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "403":
// "$ref": "#/responses/forbidden"
repo := getRepositoryByParams(ctx)
if ctx.Written() {
return
}
if access, err := models.AccessLevel(ctx.User, repo); err != nil {
ctx.Error(500, "AccessLevel", err)
ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
return
} else if access < models.AccessModeAdmin {
ctx.Error(403, "", "Must have admin-level access to the repository")
ctx.Error(http.StatusForbidden, "", "Must have admin-level access to the repository")
return
}
if err := ctx.Org.Team.AddRepository(repo); err != nil {
ctx.Error(500, "AddRepository", err)
ctx.Error(http.StatusInternalServerError, "AddRepository", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}
// RemoveTeamRepository api for removing a repository from a team
@ -509,22 +532,25 @@ func RemoveTeamRepository(ctx *context.APIContext) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "403":
// "$ref": "#/responses/forbidden"
repo := getRepositoryByParams(ctx)
if ctx.Written() {
return
}
if access, err := models.AccessLevel(ctx.User, repo); err != nil {
ctx.Error(500, "AccessLevel", err)
ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
return
} else if access < models.AccessModeAdmin {
ctx.Error(403, "", "Must have admin-level access to the repository")
ctx.Error(http.StatusForbidden, "", "Must have admin-level access to the repository")
return
}
if err := ctx.Org.Team.RemoveRepository(repo.ID); err != nil {
ctx.Error(500, "RemoveRepository", err)
ctx.Error(http.StatusInternalServerError, "RemoveRepository", err)
return
}
ctx.Status(204)
ctx.Status(http.StatusNoContent)
}
// SearchTeam api for searching teams
@ -568,6 +594,7 @@ func SearchTeam(ctx *context.APIContext) {
// type: array
// items:
// "$ref": "#/definitions/Team"
opts := &models.SearchTeamOptions{
UserID: ctx.User.ID,
Keyword: strings.TrimSpace(ctx.Query("q")),
@ -580,7 +607,7 @@ func SearchTeam(ctx *context.APIContext) {
teams, _, err := models.SearchTeam(opts)
if err != nil {
log.Error("SearchTeam failed: %v", err)
ctx.JSON(500, map[string]interface{}{
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"ok": false,
"error": "SearchTeam internal failure",
})
@ -591,7 +618,7 @@ func SearchTeam(ctx *context.APIContext) {
for i := range teams {
if err := teams[i].GetUnits(); err != nil {
log.Error("Team GetUnits failed: %v", err)
ctx.JSON(500, map[string]interface{}{
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"ok": false,
"error": "SearchTeam failed to get units",
})
@ -600,7 +627,7 @@ func SearchTeam(ctx *context.APIContext) {
apiTeams[i] = convert.ToTeam(teams[i])
}
ctx.JSON(200, map[string]interface{}{
ctx.JSON(http.StatusOK, map[string]interface{}{
"ok": true,
"data": apiTeams,
})