* 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 :+1:
* use ctx.InternalServerError
* Revert "use numbers and not http.Status___ enum"
This reverts commit b1ff386e24
.
* use http.Status* enum everywhere
tags/v1.11.0-rc1
URL string `json:"url"` | URL string `json:"url"` | ||||
} | } | ||||
// APIInvalidTopicsError is error format response to invalid topics | |||||
// swagger:response invalidTopicsError | |||||
type APIInvalidTopicsError struct { | |||||
Topics []string `json:"invalidTopics"` | |||||
Message string `json:"message"` | |||||
} | |||||
//APIEmpty is an empty response | //APIEmpty is an empty response | ||||
// swagger:response empty | // swagger:response empty | ||||
type APIEmpty struct{} | type APIEmpty struct{} |
package admin | package admin | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
if models.IsErrUserAlreadyExist(err) || | if models.IsErrUserAlreadyExist(err) || | ||||
models.IsErrNameReserved(err) || | models.IsErrNameReserved(err) || | ||||
models.IsErrNamePatternNotAllowed(err) { | models.IsErrNamePatternNotAllowed(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "CreateOrganization", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateOrganization", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(201, convert.ToOrganization(org)) | |||||
ctx.JSON(http.StatusCreated, convert.ToOrganization(org)) | |||||
} | } | ||||
//GetAllOrgs API for getting information of all the organizations | //GetAllOrgs API for getting information of all the organizations | ||||
// "$ref": "#/responses/OrganizationList" | // "$ref": "#/responses/OrganizationList" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
users, _, err := models.SearchUsers(&models.SearchUserOptions{ | users, _, err := models.SearchUsers(&models.SearchUserOptions{ | ||||
Type: models.UserTypeOrganization, | Type: models.UserTypeOrganization, | ||||
OrderBy: models.SearchOrderByAlphabetically, | OrderBy: models.SearchOrderByAlphabetically, | ||||
Private: true, | Private: true, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "SearchOrganizations", err) | |||||
ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err) | |||||
return | return | ||||
} | } | ||||
orgs := make([]*api.Organization, len(users)) | orgs := make([]*api.Organization, len(users)) | ||||
for i := range users { | for i := range users { | ||||
orgs[i] = convert.ToOrganization(users[i]) | orgs[i] = convert.ToOrganization(users[i]) | ||||
} | } | ||||
ctx.JSON(200, &orgs) | |||||
ctx.JSON(http.StatusOK, &orgs) | |||||
} | } |
// "$ref": "#/responses/Repository" | // "$ref": "#/responses/Repository" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
// "409": | |||||
// "$ref": "#/responses/error" | |||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
owner := user.GetUserByParams(ctx) | owner := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return |
import ( | import ( | ||||
"errors" | "errors" | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
source, err := models.GetLoginSourceByID(sourceID) | source, err := models.GetLoginSourceByID(sourceID) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrLoginSourceNotExist(err) { | if models.IsErrLoginSourceNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetLoginSourceByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLoginSourceByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
// "$ref": "#/responses/User" | // "$ref": "#/responses/User" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
u := &models.User{ | u := &models.User{ | ||||
Name: form.Username, | Name: form.Username, | ||||
FullName: form.FullName, | FullName: form.FullName, | ||||
} | } | ||||
if !password.IsComplexEnough(form.Password) { | if !password.IsComplexEnough(form.Password) { | ||||
err := errors.New("PasswordComplexity") | err := errors.New("PasswordComplexity") | ||||
ctx.Error(400, "PasswordComplexity", err) | |||||
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err) | |||||
return | return | ||||
} | } | ||||
if err := models.CreateUser(u); err != nil { | if err := models.CreateUser(u); err != nil { | ||||
models.IsErrEmailAlreadyUsed(err) || | models.IsErrEmailAlreadyUsed(err) || | ||||
models.IsErrNameReserved(err) || | models.IsErrNameReserved(err) || | ||||
models.IsErrNamePatternNotAllowed(err) { | models.IsErrNamePatternNotAllowed(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "CreateUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateUser", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if form.SendNotify { | if form.SendNotify { | ||||
mailer.SendRegisterNotifyMail(ctx.Locale, u) | mailer.SendRegisterNotifyMail(ctx.Locale, u) | ||||
} | } | ||||
ctx.JSON(201, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin)) | |||||
ctx.JSON(http.StatusCreated, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin)) | |||||
} | } | ||||
// EditUser api for modifying a user's information | // EditUser api for modifying a user's information | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
if len(form.Password) > 0 { | if len(form.Password) > 0 { | ||||
if !password.IsComplexEnough(form.Password) { | if !password.IsComplexEnough(form.Password) { | ||||
err := errors.New("PasswordComplexity") | err := errors.New("PasswordComplexity") | ||||
ctx.Error(400, "PasswordComplexity", err) | |||||
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err) | |||||
return | return | ||||
} | } | ||||
var err error | var err error | ||||
if u.Salt, err = models.GetUserSalt(); err != nil { | if u.Salt, err = models.GetUserSalt(); err != nil { | ||||
ctx.Error(500, "UpdateUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateUser", err) | |||||
return | return | ||||
} | } | ||||
u.HashPassword(form.Password) | u.HashPassword(form.Password) | ||||
if err := models.UpdateUser(u); err != nil { | if err := models.UpdateUser(u); err != nil { | ||||
if models.IsErrEmailAlreadyUsed(err) { | if models.IsErrEmailAlreadyUsed(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "UpdateUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateUser", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name) | log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name) | ||||
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin)) | |||||
ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin)) | |||||
} | } | ||||
// DeleteUser api for deleting a user | // DeleteUser api for deleting a user | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
if err := models.DeleteUser(u); err != nil { | if err := models.DeleteUser(u); err != nil { | ||||
if models.IsErrUserOwnRepos(err) || | if models.IsErrUserOwnRepos(err) || | ||||
models.IsErrUserHasOrgs(err) { | models.IsErrUserHasOrgs(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "DeleteUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteUser", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
log.Trace("Account deleted by admin(%s): %s", ctx.User.Name, u.Name) | log.Trace("Account deleted by admin(%s): %s", ctx.User.Name, u.Name) | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// CreatePublicKey api for creating a public key to a user | // CreatePublicKey api for creating a public key to a user | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
if models.IsErrKeyNotExist(err) { | if models.IsErrKeyNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else if models.IsErrKeyAccessDenied(err) { | } else if models.IsErrKeyAccessDenied(err) { | ||||
ctx.Error(403, "", "You do not have access to this key") | |||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key") | |||||
} else { | } else { | ||||
ctx.Error(500, "DeleteUserPublicKey", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteUserPublicKey", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
log.Trace("Key deleted by admin(%s): %s", ctx.User.Name, u.Name) | log.Trace("Key deleted by admin(%s): %s", ctx.User.Name, u.Name) | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
//GetAllUsers API for getting information of all the users | //GetAllUsers API for getting information of all the users | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
users, _, err := models.SearchUsers(&models.SearchUserOptions{ | users, _, err := models.SearchUsers(&models.SearchUserOptions{ | ||||
Type: models.UserTypeIndividual, | Type: models.UserTypeIndividual, | ||||
OrderBy: models.SearchOrderByAlphabetically, | OrderBy: models.SearchOrderByAlphabetically, | ||||
PageSize: -1, | PageSize: -1, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetAllUsers", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetAllUsers", err) | |||||
return | return | ||||
} | } | ||||
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin) | results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin) | ||||
} | } | ||||
ctx.JSON(200, &results) | |||||
ctx.JSON(http.StatusOK, &results) | |||||
} | } |
package v1 | package v1 | ||||
import ( | import ( | ||||
"net/http" | |||||
"strings" | "strings" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
log.Trace("Sudo from (%s) to: %s", ctx.User.Name, user.Name) | log.Trace("Sudo from (%s) to: %s", ctx.User.Name, user.Name) | ||||
ctx.User = user | ctx.User = user | ||||
} else { | } else { | ||||
ctx.JSON(403, map[string]string{ | |||||
ctx.JSON(http.StatusForbidden, map[string]string{ | |||||
"message": "Only administrators allowed to sudo.", | "message": "Only administrators allowed to sudo.", | ||||
}) | }) | ||||
return | return | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
} else if models.IsErrRepoRedirectNotExist(err) { | } else if models.IsErrRepoRedirectNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "LookupRepoRedirect", err) | |||||
ctx.Error(http.StatusInternalServerError, "LookupRepoRedirect", err) | |||||
} | } | ||||
} else { | } else { | ||||
ctx.Error(500, "GetRepositoryByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetRepositoryByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Repo.Permission, err = models.GetUserRepoPermission(repo, ctx.User) | ctx.Repo.Permission, err = models.GetUserRepoPermission(repo, ctx.User) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserRepoPermission", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) | |||||
return | return | ||||
} | } | ||||
ctx.RequireCSRF() | ctx.RequireCSRF() | ||||
return | return | ||||
} | } | ||||
ctx.Context.Error(401) | |||||
ctx.Context.Error(http.StatusUnauthorized) | |||||
} | } | ||||
} | } | ||||
func reqBasicAuth() macaron.Handler { | func reqBasicAuth() macaron.Handler { | ||||
return func(ctx *context.APIContext) { | return func(ctx *context.APIContext) { | ||||
if !ctx.Context.IsBasicAuth { | if !ctx.Context.IsBasicAuth { | ||||
ctx.Context.Error(401) | |||||
ctx.Context.Error(http.StatusUnauthorized) | |||||
return | return | ||||
} | } | ||||
ctx.CheckForOTP() | ctx.CheckForOTP() | ||||
func reqSiteAdmin() macaron.Handler { | func reqSiteAdmin() macaron.Handler { | ||||
return func(ctx *context.Context) { | return func(ctx *context.Context) { | ||||
if !ctx.IsUserSiteAdmin() { | if !ctx.IsUserSiteAdmin() { | ||||
ctx.Error(403) | |||||
ctx.Error(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
func reqOwner() macaron.Handler { | func reqOwner() macaron.Handler { | ||||
return func(ctx *context.Context) { | return func(ctx *context.Context) { | ||||
if !ctx.IsUserRepoOwner() && !ctx.IsUserSiteAdmin() { | if !ctx.IsUserRepoOwner() && !ctx.IsUserSiteAdmin() { | ||||
ctx.Error(403) | |||||
ctx.Error(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
func reqAdmin() macaron.Handler { | func reqAdmin() macaron.Handler { | ||||
return func(ctx *context.Context) { | return func(ctx *context.Context) { | ||||
if !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { | if !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { | ||||
ctx.Error(403) | |||||
ctx.Error(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
func reqRepoWriter(unitTypes ...models.UnitType) macaron.Handler { | func reqRepoWriter(unitTypes ...models.UnitType) macaron.Handler { | ||||
return func(ctx *context.Context) { | return func(ctx *context.Context) { | ||||
if !ctx.IsUserRepoWriter(unitTypes) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { | if !ctx.IsUserRepoWriter(unitTypes) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { | ||||
ctx.Error(403) | |||||
ctx.Error(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
func reqRepoReader(unitType models.UnitType) macaron.Handler { | func reqRepoReader(unitType models.UnitType) macaron.Handler { | ||||
return func(ctx *context.Context) { | return func(ctx *context.Context) { | ||||
if !ctx.IsUserRepoReaderSpecific(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { | if !ctx.IsUserRepoReaderSpecific(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { | ||||
ctx.Error(403) | |||||
ctx.Error(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
func reqAnyRepoReader() macaron.Handler { | func reqAnyRepoReader() macaron.Handler { | ||||
return func(ctx *context.Context) { | return func(ctx *context.Context) { | ||||
if !ctx.IsUserRepoReaderAny() && !ctx.IsUserSiteAdmin() { | if !ctx.IsUserRepoReaderAny() && !ctx.IsUserSiteAdmin() { | ||||
ctx.Error(403) | |||||
ctx.Error(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
} else if ctx.Org.Team != nil { | } else if ctx.Org.Team != nil { | ||||
orgID = ctx.Org.Team.OrgID | orgID = ctx.Org.Team.OrgID | ||||
} else { | } else { | ||||
ctx.Error(500, "", "reqOrgOwnership: unprepared context") | |||||
ctx.Error(http.StatusInternalServerError, "", "reqOrgOwnership: unprepared context") | |||||
return | return | ||||
} | } | ||||
isOwner, err := models.IsOrganizationOwner(orgID, ctx.User.ID) | isOwner, err := models.IsOrganizationOwner(orgID, ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOrganizationOwner", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err) | |||||
return | return | ||||
} else if !isOwner { | } else if !isOwner { | ||||
if ctx.Org.Organization != nil { | if ctx.Org.Organization != nil { | ||||
ctx.Error(403, "", "Must be an organization owner") | |||||
ctx.Error(http.StatusForbidden, "", "Must be an organization owner") | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
return | return | ||||
} | } | ||||
if ctx.Org.Team == nil { | if ctx.Org.Team == nil { | ||||
ctx.Error(500, "", "reqTeamMembership: unprepared context") | |||||
ctx.Error(http.StatusInternalServerError, "", "reqTeamMembership: unprepared context") | |||||
return | return | ||||
} | } | ||||
var orgID = ctx.Org.Team.OrgID | var orgID = ctx.Org.Team.OrgID | ||||
isOwner, err := models.IsOrganizationOwner(orgID, ctx.User.ID) | isOwner, err := models.IsOrganizationOwner(orgID, ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOrganizationOwner", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err) | |||||
return | return | ||||
} else if isOwner { | } else if isOwner { | ||||
return | return | ||||
} | } | ||||
if isTeamMember, err := models.IsTeamMember(orgID, ctx.Org.Team.ID, ctx.User.ID); err != nil { | if isTeamMember, err := models.IsTeamMember(orgID, ctx.Org.Team.ID, ctx.User.ID); err != nil { | ||||
ctx.Error(500, "IsTeamMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsTeamMember", err) | |||||
return | return | ||||
} else if !isTeamMember { | } else if !isTeamMember { | ||||
isOrgMember, err := models.IsOrganizationMember(orgID, ctx.User.ID) | isOrgMember, err := models.IsOrganizationMember(orgID, ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOrganizationMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err) | |||||
} else if isOrgMember { | } else if isOrgMember { | ||||
ctx.Error(403, "", "Must be a team member") | |||||
ctx.Error(http.StatusForbidden, "", "Must be a team member") | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
} else if ctx.Org.Team != nil { | } else if ctx.Org.Team != nil { | ||||
orgID = ctx.Org.Team.OrgID | orgID = ctx.Org.Team.OrgID | ||||
} else { | } else { | ||||
ctx.Error(500, "", "reqOrgMembership: unprepared context") | |||||
ctx.Error(http.StatusInternalServerError, "", "reqOrgMembership: unprepared context") | |||||
return | return | ||||
} | } | ||||
if isMember, err := models.IsOrganizationMember(orgID, ctx.User.ID); err != nil { | if isMember, err := models.IsOrganizationMember(orgID, ctx.User.ID); err != nil { | ||||
ctx.Error(500, "IsOrganizationMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err) | |||||
return | return | ||||
} else if !isMember { | } else if !isMember { | ||||
if ctx.Org.Organization != nil { | if ctx.Org.Organization != nil { | ||||
ctx.Error(403, "", "Must be an organization member") | |||||
ctx.Error(http.StatusForbidden, "", "Must be an organization member") | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
func reqGitHook() macaron.Handler { | func reqGitHook() macaron.Handler { | ||||
return func(ctx *context.APIContext) { | return func(ctx *context.APIContext) { | ||||
if !ctx.User.CanEditGitHook() { | if !ctx.User.CanEditGitHook() { | ||||
ctx.Error(403, "", "must be allowed to edit Git hooks") | |||||
ctx.Error(http.StatusForbidden, "", "must be allowed to edit Git hooks") | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if models.IsErrOrgNotExist(err) { | if models.IsErrOrgNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetOrgByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetTeamById", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTeamById", err) | |||||
} | } | ||||
return | return | ||||
} | } |
// "$ref": "#/responses/MarkdownRender" | // "$ref": "#/responses/MarkdownRender" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
if ctx.HasAPIError() { | if ctx.HasAPIError() { | ||||
ctx.Error(422, "", ctx.GetErrMsg()) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", ctx.GetErrMsg()) | |||||
return | return | ||||
} | } | ||||
if form.Wiki { | if form.Wiki { | ||||
_, err := ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta))) | _, err := ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta))) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(http.StatusInternalServerError, "", err) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
} else { | } else { | ||||
_, err := ctx.Write(markdown.Render(md, urlPrefix, meta)) | _, err := ctx.Write(markdown.Render(md, urlPrefix, meta)) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(http.StatusInternalServerError, "", err) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
default: | default: | ||||
_, err := ctx.Write(markdown.RenderRaw([]byte(form.Text), "", false)) | _, err := ctx.Write(markdown.RenderRaw([]byte(form.Text), "", false)) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(http.StatusInternalServerError, "", err) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
// "$ref": "#/responses/MarkdownRender" | // "$ref": "#/responses/MarkdownRender" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
body, err := ctx.Req.Body().Bytes() | body, err := ctx.Req.Body().Bytes() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
return | return | ||||
} | } | ||||
_, err = ctx.Write(markdown.RenderRaw(body, "", false)) | _, err = ctx.Write(markdown.RenderRaw(body, "", false)) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(http.StatusInternalServerError, "", err) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
} | } |
package misc | package misc | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
) | ) | ||||
// Swagger render swagger-ui page with v1 json | // Swagger render swagger-ui page with v1 json | ||||
func Swagger(ctx *context.Context) { | func Swagger(ctx *context.Context) { | ||||
ctx.Data["APIJSONVersion"] = "v1" | ctx.Data["APIJSONVersion"] = "v1" | ||||
ctx.HTML(200, tplSwagger) | |||||
ctx.HTML(http.StatusOK, tplSwagger) | |||||
} | } |
package misc | package misc | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/structs" | "code.gitea.io/gitea/modules/structs" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/ServerVersion" | // "$ref": "#/responses/ServerVersion" | ||||
ctx.JSON(200, &structs.ServerVersion{Version: setting.AppVer}) | |||||
ctx.JSON(http.StatusOK, &structs.ServerVersion{Version: setting.AppVer}) | |||||
} | } |
package org | package org | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/HookList" | // "$ref": "#/responses/HookList" | ||||
org := ctx.Org.Organization | org := ctx.Org.Organization | ||||
orgHooks, err := models.GetWebhooksByOrgID(org.ID) | orgHooks, err := models.GetWebhooksByOrgID(org.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetWebhooksByOrgID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetWebhooksByOrgID", err) | |||||
return | return | ||||
} | } | ||||
hooks := make([]*api.Hook, len(orgHooks)) | hooks := make([]*api.Hook, len(orgHooks)) | ||||
for i, hook := range orgHooks { | for i, hook := range orgHooks { | ||||
hooks[i] = convert.ToHook(org.HomeLink(), hook) | hooks[i] = convert.ToHook(org.HomeLink(), hook) | ||||
} | } | ||||
ctx.JSON(200, hooks) | |||||
ctx.JSON(http.StatusOK, hooks) | |||||
} | } | ||||
// GetHook get an organization's hook by id | // GetHook get an organization's hook by id | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Hook" | // "$ref": "#/responses/Hook" | ||||
org := ctx.Org.Organization | org := ctx.Org.Organization | ||||
hookID := ctx.ParamsInt64(":id") | hookID := ctx.ParamsInt64(":id") | ||||
hook, err := utils.GetOrgHook(ctx, org.ID, hookID) | hook, err := utils.GetOrgHook(ctx, org.ID, hookID) | ||||
if err != nil { | if err != nil { | ||||
return | 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 | // CreateHook create a hook for an organization | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
org := ctx.Org.Organization | org := ctx.Org.Organization | ||||
hookID := ctx.ParamsInt64(":id") | hookID := ctx.ParamsInt64(":id") | ||||
if err := models.DeleteWebhookByOrgID(org.ID, hookID); err != nil { | if err := models.DeleteWebhookByOrgID(org.ID, hookID); err != nil { | ||||
if models.IsErrWebhookNotExist(err) { | if models.IsErrWebhookNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "DeleteWebhookByOrgID", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteWebhookByOrgID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
PublicOnly: publicOnly, | PublicOnly: publicOnly, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUsersByIDs", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUsersByIDs", err) | |||||
return | return | ||||
} | } | ||||
for i, member := range members { | for i, member := range members { | ||||
apiMembers[i] = convert.ToUser(member, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | 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 | // ListMembers list an organization's members | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
publicOnly := true | publicOnly := true | ||||
if ctx.User != nil { | if ctx.User != nil { | ||||
isMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID) | isMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOrgMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) | |||||
return | return | ||||
} | } | ||||
publicOnly = !isMember | publicOnly = !isMember | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
listMembers(ctx, true) | listMembers(ctx, true) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// description: user is a member | // description: user is a member | ||||
// "302": | |||||
// description: redirection to /orgs/{org}/public_members/{username} | |||||
// "404": | // "404": | ||||
// description: user is not a member | // description: user is not a member | ||||
userToCheck := user.GetUserByParams(ctx) | userToCheck := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
if ctx.User != nil { | if ctx.User != nil { | ||||
userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID) | userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOrgMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) | |||||
return | return | ||||
} else if userIsMember { | } else if userIsMember { | ||||
userToCheckIsMember, err := ctx.Org.Organization.IsOrgMember(userToCheck.ID) | userToCheckIsMember, err := ctx.Org.Organization.IsOrgMember(userToCheck.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOrgMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) | |||||
} else if userToCheckIsMember { | } else if userToCheckIsMember { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
// description: user is a public member | // description: user is a public member | ||||
// "404": | // "404": | ||||
// description: user is not a public member | // description: user is not a public member | ||||
userToCheck := user.GetUserByParams(ctx) | userToCheck := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if userToCheck.IsPublicMember(ctx.Org.Organization.ID) { | if userToCheck.IsPublicMember(ctx.Org.Organization.ID) { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// description: membership publicized | // description: membership publicized | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
userToPublicize := user.GetUserByParams(ctx) | userToPublicize := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if userToPublicize.ID != ctx.User.ID { | if userToPublicize.ID != ctx.User.ID { | ||||
ctx.Error(403, "", "Cannot publicize another member") | |||||
ctx.Error(http.StatusForbidden, "", "Cannot publicize another member") | |||||
return | return | ||||
} | } | ||||
err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToPublicize.ID, true) | err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToPublicize.ID, true) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ChangeOrgUserStatus", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// ConcealMember make a member's membership not public | // ConcealMember make a member's membership not public | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
userToConceal := user.GetUserByParams(ctx) | userToConceal := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if userToConceal.ID != ctx.User.ID { | if userToConceal.ID != ctx.User.ID { | ||||
ctx.Error(403, "", "Cannot conceal another member") | |||||
ctx.Error(http.StatusForbidden, "", "Cannot conceal another member") | |||||
return | return | ||||
} | } | ||||
err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToConceal.ID, false) | err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToConceal.ID, false) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ChangeOrgUserStatus", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// DeleteMember remove a member from an organization | // DeleteMember remove a member from an organization | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// description: member removed | // description: member removed | ||||
member := user.GetUserByParams(ctx) | member := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if err := ctx.Org.Organization.RemoveMember(member.ID); err != nil { | 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) | |||||
} | } |
package org | package org | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
func listUserOrgs(ctx *context.APIContext, u *models.User, all bool) { | func listUserOrgs(ctx *context.APIContext, u *models.User, all bool) { | ||||
if err := u.GetOrganizations(all); err != nil { | if err := u.GetOrganizations(all); err != nil { | ||||
ctx.Error(500, "GetOrganizations", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetOrganizations", err) | |||||
return | return | ||||
} | } | ||||
for i := range u.Orgs { | for i := range u.Orgs { | ||||
apiOrgs[i] = convert.ToOrganization(u.Orgs[i]) | apiOrgs[i] = convert.ToOrganization(u.Orgs[i]) | ||||
} | } | ||||
ctx.JSON(200, &apiOrgs) | |||||
ctx.JSON(http.StatusOK, &apiOrgs) | |||||
} | } | ||||
// ListMyOrgs list all my orgs | // ListMyOrgs list all my orgs | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/OrganizationList" | // "$ref": "#/responses/OrganizationList" | ||||
listUserOrgs(ctx, ctx.User, true) | listUserOrgs(ctx, ctx.User, true) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/OrganizationList" | // "$ref": "#/responses/OrganizationList" | ||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
if !ctx.User.CanCreateOrganization() { | if !ctx.User.CanCreateOrganization() { | ||||
ctx.Error(403, "Create organization not allowed", nil) | |||||
ctx.Error(http.StatusForbidden, "Create organization not allowed", nil) | |||||
return | return | ||||
} | } | ||||
if models.IsErrUserAlreadyExist(err) || | if models.IsErrUserAlreadyExist(err) || | ||||
models.IsErrNameReserved(err) || | models.IsErrNameReserved(err) || | ||||
models.IsErrNamePatternNotAllowed(err) { | models.IsErrNamePatternNotAllowed(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "CreateOrganization", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateOrganization", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(201, convert.ToOrganization(org)) | |||||
ctx.JSON(http.StatusCreated, convert.ToOrganization(org)) | |||||
} | } | ||||
// Get get an organization | // Get get an organization | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Organization" | // "$ref": "#/responses/Organization" | ||||
if !models.HasOrgVisible(ctx.Org.Organization, ctx.User) { | if !models.HasOrgVisible(ctx.Org.Organization, ctx.User) { | ||||
ctx.NotFound("HasOrgVisible", nil) | ctx.NotFound("HasOrgVisible", nil) | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToOrganization(ctx.Org.Organization)) | |||||
ctx.JSON(http.StatusOK, convert.ToOrganization(ctx.Org.Organization)) | |||||
} | } | ||||
// Edit change an organization's information | // Edit change an organization's information | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Organization" | // "$ref": "#/responses/Organization" | ||||
org := ctx.Org.Organization | org := ctx.Org.Organization | ||||
org.FullName = form.FullName | org.FullName = form.FullName | ||||
org.Description = form.Description | org.Description = form.Description | ||||
org.Visibility = api.VisibilityModes[form.Visibility] | org.Visibility = api.VisibilityModes[form.Visibility] | ||||
} | } | ||||
if err := models.UpdateUserCols(org, "full_name", "description", "website", "location", "visibility"); err != nil { | 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 | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToOrganization(org)) | |||||
ctx.JSON(http.StatusOK, convert.ToOrganization(org)) | |||||
} | } | ||||
//Delete an organization | //Delete an organization | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
if err := models.DeleteOrganization(ctx.Org.Organization); err != nil { | if err := models.DeleteOrganization(ctx.Org.Organization); err != nil { | ||||
ctx.Error(500, "DeleteOrganization", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteOrganization", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package org | package org | ||||
import ( | import ( | ||||
"net/http" | |||||
"strings" | "strings" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TeamList" | // "$ref": "#/responses/TeamList" | ||||
org := ctx.Org.Organization | org := ctx.Org.Organization | ||||
if err := org.GetTeams(); err != nil { | if err := org.GetTeams(); err != nil { | ||||
ctx.Error(500, "GetTeams", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTeams", err) | |||||
return | return | ||||
} | } | ||||
apiTeams := make([]*api.Team, len(org.Teams)) | apiTeams := make([]*api.Team, len(org.Teams)) | ||||
for i := range org.Teams { | for i := range org.Teams { | ||||
if err := org.Teams[i].GetUnits(); err != nil { | if err := org.Teams[i].GetUnits(); err != nil { | ||||
ctx.Error(500, "GetUnits", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUnits", err) | |||||
return | return | ||||
} | } | ||||
apiTeams[i] = convert.ToTeam(org.Teams[i]) | 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 | // ListUserTeams list all the teams a user belongs to | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TeamList" | // "$ref": "#/responses/TeamList" | ||||
teams, err := models.GetUserTeams(ctx.User.ID) | teams, err := models.GetUserTeams(ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserTeams", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserTeams", err) | |||||
return | return | ||||
} | } | ||||
if !ok { | if !ok { | ||||
org, err := models.GetUserByID(teams[i].OrgID) | org, err := models.GetUserByID(teams[i].OrgID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByID", err) | |||||
return | return | ||||
} | } | ||||
apiOrg = convert.ToOrganization(org) | apiOrg = convert.ToOrganization(org) | ||||
apiTeams[i] = convert.ToTeam(teams[i]) | apiTeams[i] = convert.ToTeam(teams[i]) | ||||
apiTeams[i].Organization = apiOrg | apiTeams[i].Organization = apiOrg | ||||
} | } | ||||
ctx.JSON(200, apiTeams) | |||||
ctx.JSON(http.StatusOK, apiTeams) | |||||
} | } | ||||
// GetTeam api for get a team | // GetTeam api for get a team | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Team" | // "$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 | // CreateTeam api for create a team | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Team" | // "$ref": "#/responses/Team" | ||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
team := &models.Team{ | team := &models.Team{ | ||||
OrgID: ctx.Org.Organization.ID, | OrgID: ctx.Org.Organization.ID, | ||||
Name: form.Name, | Name: form.Name, | ||||
if err := models.NewTeam(team); err != nil { | if err := models.NewTeam(team); err != nil { | ||||
if models.IsErrTeamAlreadyExist(err) { | if models.IsErrTeamAlreadyExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "NewTeam", err) | |||||
ctx.Error(http.StatusInternalServerError, "NewTeam", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(201, convert.ToTeam(team)) | |||||
ctx.JSON(http.StatusCreated, convert.ToTeam(team)) | |||||
} | } | ||||
// EditTeam api for edit a team | // EditTeam api for edit a team | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Team" | // "$ref": "#/responses/Team" | ||||
team := ctx.Org.Team | team := ctx.Org.Team | ||||
team.Description = form.Description | team.Description = form.Description | ||||
unitTypes := models.FindUnitTypes(form.Units...) | unitTypes := models.FindUnitTypes(form.Units...) | ||||
} | } | ||||
if err := models.UpdateTeam(team, isAuthChanged, isIncludeAllChanged); err != nil { | if err := models.UpdateTeam(team, isAuthChanged, isIncludeAllChanged); err != nil { | ||||
ctx.Error(500, "EditTeam", err) | |||||
ctx.Error(http.StatusInternalServerError, "EditTeam", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToTeam(team)) | |||||
ctx.JSON(http.StatusOK, convert.ToTeam(team)) | |||||
} | } | ||||
// DeleteTeam api for delete a team | // DeleteTeam api for delete a team | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// description: team deleted | // description: team deleted | ||||
if err := models.DeleteTeam(ctx.Org.Team); err != nil { | if err := models.DeleteTeam(ctx.Org.Team); err != nil { | ||||
ctx.Error(500, "DeleteTeam", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteTeam", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// GetTeamMembers api for get a team's members | // GetTeamMembers api for get a team's members | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
isMember, err := models.IsOrganizationMember(ctx.Org.Team.OrgID, ctx.User.ID) | isMember, err := models.IsOrganizationMember(ctx.Org.Team.OrgID, ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOrganizationMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err) | |||||
return | return | ||||
} else if !isMember { | } else if !isMember { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
team := ctx.Org.Team | team := ctx.Org.Team | ||||
if err := team.GetMembers(); err != nil { | if err := team.GetMembers(); err != nil { | ||||
ctx.Error(500, "GetTeamMembers", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err) | |||||
return | return | ||||
} | } | ||||
members := make([]*api.User, len(team.Members)) | members := make([]*api.User, len(team.Members)) | ||||
for i, member := range team.Members { | for i, member := range team.Members { | ||||
members[i] = convert.ToUser(member, ctx.IsSigned, ctx.User.IsAdmin) | 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 | // GetTeamMember api for get a particular member of team | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/User" | // "$ref": "#/responses/User" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
teamID := ctx.ParamsInt64("teamid") | teamID := ctx.ParamsInt64("teamid") | ||||
isTeamMember, err := models.IsUserInTeams(u.ID, []int64{teamID}) | isTeamMember, err := models.IsUserInTeams(u.ID, []int64{teamID}) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsUserInTeams", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsUserInTeams", err) | |||||
return | return | ||||
} else if !isTeamMember { | } else if !isTeamMember { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
return | 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 | // AddTeamMember api for add a member to a team | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if err := ctx.Org.Team.AddMember(u.ID); err != nil { | if err := ctx.Org.Team.AddMember(u.ID); err != nil { | ||||
ctx.Error(500, "AddMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddMember", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// RemoveTeamMember api for remove one member from a team | // RemoveTeamMember api for remove one member from a team | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
u := user.GetUserByParams(ctx) | u := user.GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if err := ctx.Org.Team.RemoveMember(u.ID); err != nil { | if err := ctx.Org.Team.RemoveMember(u.ID); err != nil { | ||||
ctx.Error(500, "RemoveMember", err) | |||||
ctx.Error(http.StatusInternalServerError, "RemoveMember", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// GetTeamRepos api for get a team's repos | // GetTeamRepos api for get a team's repos | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
team := ctx.Org.Team | team := ctx.Org.Team | ||||
if err := team.GetRepositories(); err != nil { | if err := team.GetRepositories(); err != nil { | ||||
ctx.Error(500, "GetTeamRepos", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) | |||||
} | } | ||||
repos := make([]*api.Repository, len(team.Repos)) | repos := make([]*api.Repository, len(team.Repos)) | ||||
for i, repo := range team.Repos { | for i, repo := range team.Repos { | ||||
access, err := models.AccessLevel(ctx.User, repo) | access, err := models.AccessLevel(ctx.User, repo) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetTeamRepos", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) | |||||
return | return | ||||
} | } | ||||
repos[i] = repo.APIFormat(access) | 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 | // getRepositoryByParams get repository by a team's organization ID and repo name | ||||
if models.IsErrRepoNotExist(err) { | if models.IsErrRepoNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetRepositoryByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetRepositoryByName", err) | |||||
} | } | ||||
return nil | return nil | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
repo := getRepositoryByParams(ctx) | repo := getRepositoryByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if access, err := models.AccessLevel(ctx.User, repo); err != nil { | if access, err := models.AccessLevel(ctx.User, repo); err != nil { | ||||
ctx.Error(500, "AccessLevel", err) | |||||
ctx.Error(http.StatusInternalServerError, "AccessLevel", err) | |||||
return | return | ||||
} else if access < models.AccessModeAdmin { | } 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 | return | ||||
} | } | ||||
if err := ctx.Org.Team.AddRepository(repo); err != nil { | if err := ctx.Org.Team.AddRepository(repo); err != nil { | ||||
ctx.Error(500, "AddRepository", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddRepository", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// RemoveTeamRepository api for removing a repository from a team | // RemoveTeamRepository api for removing a repository from a team | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
repo := getRepositoryByParams(ctx) | repo := getRepositoryByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if access, err := models.AccessLevel(ctx.User, repo); err != nil { | if access, err := models.AccessLevel(ctx.User, repo); err != nil { | ||||
ctx.Error(500, "AccessLevel", err) | |||||
ctx.Error(http.StatusInternalServerError, "AccessLevel", err) | |||||
return | return | ||||
} else if access < models.AccessModeAdmin { | } 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 | return | ||||
} | } | ||||
if err := ctx.Org.Team.RemoveRepository(repo.ID); err != nil { | if err := ctx.Org.Team.RemoveRepository(repo.ID); err != nil { | ||||
ctx.Error(500, "RemoveRepository", err) | |||||
ctx.Error(http.StatusInternalServerError, "RemoveRepository", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// SearchTeam api for searching teams | // SearchTeam api for searching teams | ||||
// type: array | // type: array | ||||
// items: | // items: | ||||
// "$ref": "#/definitions/Team" | // "$ref": "#/definitions/Team" | ||||
opts := &models.SearchTeamOptions{ | opts := &models.SearchTeamOptions{ | ||||
UserID: ctx.User.ID, | UserID: ctx.User.ID, | ||||
Keyword: strings.TrimSpace(ctx.Query("q")), | Keyword: strings.TrimSpace(ctx.Query("q")), | ||||
teams, _, err := models.SearchTeam(opts) | teams, _, err := models.SearchTeam(opts) | ||||
if err != nil { | if err != nil { | ||||
log.Error("SearchTeam failed: %v", err) | log.Error("SearchTeam failed: %v", err) | ||||
ctx.JSON(500, map[string]interface{}{ | |||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"ok": false, | "ok": false, | ||||
"error": "SearchTeam internal failure", | "error": "SearchTeam internal failure", | ||||
}) | }) | ||||
for i := range teams { | for i := range teams { | ||||
if err := teams[i].GetUnits(); err != nil { | if err := teams[i].GetUnits(); err != nil { | ||||
log.Error("Team GetUnits failed: %v", err) | log.Error("Team GetUnits failed: %v", err) | ||||
ctx.JSON(500, map[string]interface{}{ | |||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"ok": false, | "ok": false, | ||||
"error": "SearchTeam failed to get units", | "error": "SearchTeam failed to get units", | ||||
}) | }) | ||||
apiTeams[i] = convert.ToTeam(teams[i]) | apiTeams[i] = convert.ToTeam(teams[i]) | ||||
} | } | ||||
ctx.JSON(200, map[string]interface{}{ | |||||
ctx.JSON(http.StatusOK, map[string]interface{}{ | |||||
"ok": true, | "ok": true, | ||||
"data": apiTeams, | "data": apiTeams, | ||||
}) | }) |
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/GitBlobResponse" | // "$ref": "#/responses/GitBlobResponse" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
sha := ctx.Params("sha") | sha := ctx.Params("sha") | ||||
if len(sha) == 0 { | if len(sha) == 0 { |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Branch" | // "$ref": "#/responses/Branch" | ||||
if ctx.Repo.TreePath != "" { | if ctx.Repo.TreePath != "" { | ||||
// if TreePath != "", then URL contained extra slashes | // if TreePath != "", then URL contained extra slashes | ||||
// (i.e. "master/subbranch" instead of "master"), so branch does | // (i.e. "master/subbranch" instead of "master"), so branch does | ||||
if git.IsErrBranchNotExist(err) { | if git.IsErrBranchNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetBranch", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetBranch", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
c, err := branch.GetCommit() | c, err := branch.GetCommit() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetCommit", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetCommit", err) | |||||
return | return | ||||
} | } | ||||
branchProtection, err := ctx.Repo.Repository.GetBranchProtection(ctx.Repo.BranchName) | branchProtection, err := ctx.Repo.Repository.GetBranchProtection(ctx.Repo.BranchName) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetBranchProtection", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.User)) | |||||
ctx.JSON(http.StatusOK, convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.User)) | |||||
} | } | ||||
// ListBranches list all the branches of a repository | // ListBranches list all the branches of a repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/BranchList" | // "$ref": "#/responses/BranchList" | ||||
branches, err := ctx.Repo.Repository.GetBranches() | branches, err := ctx.Repo.Repository.GetBranches() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetBranches", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetBranches", err) | |||||
return | return | ||||
} | } | ||||
for i := range branches { | for i := range branches { | ||||
c, err := branches[i].GetCommit() | c, err := branches[i].GetCommit() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetCommit", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetCommit", err) | |||||
return | return | ||||
} | } | ||||
branchProtection, err := ctx.Repo.Repository.GetBranchProtection(branches[i].Name) | branchProtection, err := ctx.Repo.Repository.GetBranchProtection(branches[i].Name) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetBranchProtection", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err) | |||||
return | return | ||||
} | } | ||||
apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.User) | apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.User) | ||||
} | } | ||||
ctx.JSON(200, &apiBranches) | |||||
ctx.JSON(http.StatusOK, &apiBranches) | |||||
} | } |
import ( | import ( | ||||
"errors" | "errors" | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
collaborators, err := ctx.Repo.Repository.GetCollaborators() | collaborators, err := ctx.Repo.Repository.GetCollaborators() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ListCollaborators", err) | |||||
ctx.Error(http.StatusInternalServerError, "ListCollaborators", err) | |||||
return | return | ||||
} | } | ||||
users := make([]*api.User, len(collaborators)) | users := make([]*api.User, len(collaborators)) | ||||
for i, collaborator := range collaborators { | for i, collaborator := range collaborators { | ||||
users[i] = convert.ToUser(collaborator.User, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | users[i] = convert.ToUser(collaborator.User, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | ||||
} | } | ||||
ctx.JSON(200, users) | |||||
ctx.JSON(http.StatusOK, users) | |||||
} | } | ||||
// IsCollaborator check if a user is a collaborator of a repository | // IsCollaborator check if a user is a collaborator of a repository | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/empty" | |||||
// "$ref": "#/responses/notFound" | |||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
user, err := models.GetUserByName(ctx.Params(":collaborator")) | user, err := models.GetUserByName(ctx.Params(":collaborator")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
isColab, err := ctx.Repo.Repository.IsCollaborator(user.ID) | isColab, err := ctx.Repo.Repository.IsCollaborator(user.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsCollaborator", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsCollaborator", err) | |||||
return | return | ||||
} | } | ||||
if isColab { | if isColab { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
collaborator, err := models.GetUserByName(ctx.Params(":collaborator")) | collaborator, err := models.GetUserByName(ctx.Params(":collaborator")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !collaborator.IsActive { | if !collaborator.IsActive { | ||||
ctx.Error(500, "InactiveCollaborator", errors.New("collaborator's account is inactive")) | |||||
ctx.Error(http.StatusInternalServerError, "InactiveCollaborator", errors.New("collaborator's account is inactive")) | |||||
return | return | ||||
} | } | ||||
if err := ctx.Repo.Repository.AddCollaborator(collaborator); err != nil { | if err := ctx.Repo.Repository.AddCollaborator(collaborator); err != nil { | ||||
ctx.Error(500, "AddCollaborator", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddCollaborator", err) | |||||
return | return | ||||
} | } | ||||
if form.Permission != nil { | if form.Permission != nil { | ||||
if err := ctx.Repo.Repository.ChangeCollaborationAccessMode(collaborator.ID, models.ParseAccessMode(*form.Permission)); err != nil { | if err := ctx.Repo.Repository.ChangeCollaborationAccessMode(collaborator.ID, models.ParseAccessMode(*form.Permission)); err != nil { | ||||
ctx.Error(500, "ChangeCollaborationAccessMode", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeCollaborationAccessMode", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// DeleteCollaborator delete a collaborator from a repository | // DeleteCollaborator delete a collaborator from a repository | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
collaborator, err := models.GetUserByName(ctx.Params(":collaborator")) | collaborator, err := models.GetUserByName(ctx.Params(":collaborator")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if err := ctx.Repo.Repository.DeleteCollaboration(collaborator.ID); err != nil { | if err := ctx.Repo.Repository.DeleteCollaboration(collaborator.ID); err != nil { | ||||
ctx.Error(500, "DeleteCollaboration", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteCollaboration", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
import ( | import ( | ||||
"math" | "math" | ||||
"net/http" | |||||
"strconv" | "strconv" | ||||
"time" | "time" | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, json) | |||||
ctx.JSON(http.StatusOK, json) | |||||
} | } | ||||
// GetAllCommits get all commits via | // GetAllCommits get all commits via | ||||
// "$ref": "#/responses/EmptyRepository" | // "$ref": "#/responses/EmptyRepository" | ||||
if ctx.Repo.Repository.IsEmpty { | if ctx.Repo.Repository.IsEmpty { | ||||
ctx.JSON(409, api.APIError{ | |||||
ctx.JSON(http.StatusConflict, api.APIError{ | |||||
Message: "Git Repository is empty.", | Message: "Git Repository is empty.", | ||||
URL: setting.API.SwaggerURL, | URL: setting.API.SwaggerURL, | ||||
}) | }) | ||||
ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount)) | ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount)) | ||||
ctx.Header().Set("X-HasMore", strconv.FormatBool(page < pageCount)) | ctx.Header().Set("X-HasMore", strconv.FormatBool(page < pageCount)) | ||||
ctx.JSON(200, &apiCommits) | |||||
ctx.JSON(http.StatusOK, &apiCommits) | |||||
} | } | ||||
func toCommit(ctx *context.APIContext, repo *models.Repository, commit *git.Commit, userCache map[string]*models.User) (*api.Commit, error) { | func toCommit(ctx *context.APIContext, repo *models.Repository, commit *git.Commit, userCache map[string]*models.User) (*api.Commit, error) { |
// responses: | // responses: | ||||
// 200: | // 200: | ||||
// description: success | // description: success | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
if ctx.Repo.Repository.IsEmpty { | if ctx.Repo.Repository.IsEmpty { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
return | return | ||||
// responses: | // responses: | ||||
// 200: | // 200: | ||||
// description: success | // description: success | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
repoPath := models.RepoPath(ctx.Params(":username"), ctx.Params(":reponame")) | repoPath := models.RepoPath(ctx.Params(":username"), ctx.Params(":reponame")) | ||||
gitRepo, err := git.OpenRepository(repoPath) | gitRepo, err := git.OpenRepository(repoPath) | ||||
if err != nil { | if err != nil { | ||||
// responses: | // responses: | ||||
// 200: | // 200: | ||||
// description: success | // description: success | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
ec, err := ctx.Repo.GetEditorconfig() | ec, err := ctx.Repo.GetEditorconfig() | ||||
if err != nil { | if err != nil { | ||||
if git.IsErrNotExist(err) { | if git.IsErrNotExist(err) { | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/FileDeleteResponse" | // "$ref": "#/responses/FileDeleteResponse" | ||||
if !CanWriteFiles(ctx.Repo) { | if !CanWriteFiles(ctx.Repo) { | ||||
ctx.Error(http.StatusInternalServerError, "DeleteFile", models.ErrUserDoesNotHaveAccessToRepo{ | ctx.Error(http.StatusInternalServerError, "DeleteFile", models.ErrUserDoesNotHaveAccessToRepo{ | ||||
UserID: ctx.User.ID, | UserID: ctx.User.ID, |
package repo | package repo | ||||
import ( | import ( | ||||
"fmt" | |||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
forks, err := ctx.Repo.Repository.GetForks() | forks, err := ctx.Repo.Repository.GetForks() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetForks", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetForks", err) | |||||
return | return | ||||
} | } | ||||
apiForks := make([]*api.Repository, len(forks)) | apiForks := make([]*api.Repository, len(forks)) | ||||
for i, fork := range forks { | for i, fork := range forks { | ||||
access, err := models.AccessLevel(ctx.User, fork) | access, err := models.AccessLevel(ctx.User, fork) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "AccessLevel", err) | |||||
ctx.Error(http.StatusInternalServerError, "AccessLevel", err) | |||||
return | return | ||||
} | } | ||||
apiForks[i] = fork.APIFormat(access) | apiForks[i] = fork.APIFormat(access) | ||||
} | } | ||||
ctx.JSON(200, apiForks) | |||||
ctx.JSON(http.StatusOK, apiForks) | |||||
} | } | ||||
// CreateFork create a fork of a repo | // CreateFork create a fork of a repo | ||||
// responses: | // responses: | ||||
// "202": | // "202": | ||||
// "$ref": "#/responses/Repository" | // "$ref": "#/responses/Repository" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
var forker *models.User // user/org that will own the fork | var forker *models.User // user/org that will own the fork | ||||
if form.Organization == nil { | if form.Organization == nil { | ||||
org, err := models.GetOrgByName(*form.Organization) | org, err := models.GetOrgByName(*form.Organization) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrOrgNotExist(err) { | if models.IsErrOrgNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetOrgByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.ServerError("IsOrgMember", err) | ctx.ServerError("IsOrgMember", err) | ||||
return | return | ||||
} else if !isMember { | } else if !isMember { | ||||
ctx.Status(403) | |||||
ctx.Error(http.StatusForbidden, "isMemberNot", fmt.Sprintf("User is no Member of Organisation '%s'", org.Name)) | |||||
return | return | ||||
} | } | ||||
forker = org | forker = org | ||||
fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description) | fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ForkRepository", err) | |||||
ctx.Error(http.StatusInternalServerError, "ForkRepository", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(202, fork.APIFormat(models.AccessModeOwner)) | |||||
//TODO change back to 201 | |||||
ctx.JSON(http.StatusAccepted, fork.APIFormat(models.AccessModeOwner)) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/GitHookList" | // "$ref": "#/responses/GitHookList" | ||||
hooks, err := ctx.Repo.GitRepo.Hooks() | hooks, err := ctx.Repo.GitRepo.Hooks() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "Hooks", err) | |||||
ctx.Error(http.StatusInternalServerError, "Hooks", err) | |||||
return | return | ||||
} | } | ||||
for i := range hooks { | for i := range hooks { | ||||
apiHooks[i] = convert.ToGitHook(hooks[i]) | apiHooks[i] = convert.ToGitHook(hooks[i]) | ||||
} | } | ||||
ctx.JSON(200, &apiHooks) | |||||
ctx.JSON(http.StatusOK, &apiHooks) | |||||
} | } | ||||
// GetGitHook get a repo's Git hook by id | // GetGitHook get a repo's Git hook by id | ||||
// "$ref": "#/responses/GitHook" | // "$ref": "#/responses/GitHook" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
hookID := ctx.Params(":id") | hookID := ctx.Params(":id") | ||||
hook, err := ctx.Repo.GitRepo.GetHook(hookID) | hook, err := ctx.Repo.GitRepo.GetHook(hookID) | ||||
if err != nil { | if err != nil { | ||||
if err == git.ErrNotValidHook { | if err == git.ErrNotValidHook { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetHook", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetHook", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToGitHook(hook)) | |||||
ctx.JSON(http.StatusOK, convert.ToGitHook(hook)) | |||||
} | } | ||||
// EditGitHook modify a Git hook of a repository | // EditGitHook modify a Git hook of a repository | ||||
// "$ref": "#/responses/GitHook" | // "$ref": "#/responses/GitHook" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
hookID := ctx.Params(":id") | hookID := ctx.Params(":id") | ||||
hook, err := ctx.Repo.GitRepo.GetHook(hookID) | hook, err := ctx.Repo.GitRepo.GetHook(hookID) | ||||
if err != nil { | if err != nil { | ||||
if err == git.ErrNotValidHook { | if err == git.ErrNotValidHook { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetHook", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetHook", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
hook.Content = form.Content | hook.Content = form.Content | ||||
if err = hook.Update(); err != nil { | if err = hook.Update(); err != nil { | ||||
ctx.Error(500, "hook.Update", err) | |||||
ctx.Error(http.StatusInternalServerError, "hook.Update", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToGitHook(hook)) | |||||
ctx.JSON(http.StatusOK, convert.ToGitHook(hook)) | |||||
} | } | ||||
// DeleteGitHook delete a Git hook of a repository | // DeleteGitHook delete a Git hook of a repository | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
hookID := ctx.Params(":id") | hookID := ctx.Params(":id") | ||||
hook, err := ctx.Repo.GitRepo.GetHook(hookID) | hook, err := ctx.Repo.GitRepo.GetHook(hookID) | ||||
if err != nil { | if err != nil { | ||||
if err == git.ErrNotValidHook { | if err == git.ErrNotValidHook { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetHook", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetHook", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
hook.Content = "" | hook.Content = "" | ||||
if err = hook.Update(); err != nil { | if err = hook.Update(); err != nil { | ||||
ctx.Error(500, "hook.Update", err) | |||||
ctx.Error(http.StatusInternalServerError, "hook.Update", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
func getGitRefsInternal(ctx *context.APIContext, filter string) { | func getGitRefsInternal(ctx *context.APIContext, filter string) { | ||||
refs, lastMethodName, err := getGitRefs(ctx, filter) | refs, lastMethodName, err := getGitRefs(ctx, filter) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, lastMethodName, err) | |||||
ctx.Error(http.StatusInternalServerError, lastMethodName, err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
// If single reference is found and it matches filter exactly return it as object | // If single reference is found and it matches filter exactly return it as object | ||||
if len(apiRefs) == 1 && apiRefs[0].Ref == filter { | if len(apiRefs) == 1 && apiRefs[0].Ref == filter { | ||||
ctx.JSON(200, &apiRefs[0]) | |||||
ctx.JSON(http.StatusOK, &apiRefs[0]) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, &apiRefs) | |||||
ctx.JSON(http.StatusOK, &apiRefs) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/HookList" | // "$ref": "#/responses/HookList" | ||||
hooks, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID) | hooks, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetWebhooksByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetWebhooksByRepoID", err) | |||||
return | return | ||||
} | } | ||||
for i := range hooks { | for i := range hooks { | ||||
apiHooks[i] = convert.ToHook(ctx.Repo.RepoLink, hooks[i]) | apiHooks[i] = convert.ToHook(ctx.Repo.RepoLink, hooks[i]) | ||||
} | } | ||||
ctx.JSON(200, &apiHooks) | |||||
ctx.JSON(http.StatusOK, &apiHooks) | |||||
} | } | ||||
// GetHook get a repo's hook by id | // GetHook get a repo's hook by id | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Hook" | // "$ref": "#/responses/Hook" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
repo := ctx.Repo | repo := ctx.Repo | ||||
hookID := ctx.ParamsInt64(":id") | hookID := ctx.ParamsInt64(":id") | ||||
hook, err := utils.GetRepoHook(ctx, repo.Repository.ID, hookID) | hook, err := utils.GetRepoHook(ctx, repo.Repository.ID, hookID) | ||||
if err != nil { | if err != nil { | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToHook(repo.RepoLink, hook)) | |||||
ctx.JSON(http.StatusOK, convert.ToHook(repo.RepoLink, hook)) | |||||
} | } | ||||
// TestHook tests a hook | // TestHook tests a hook | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
if ctx.Repo.Commit == nil { | if ctx.Repo.Commit == nil { | ||||
// if repo does not have any commits, then don't send a webhook | // if repo does not have any commits, then don't send a webhook | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
return | return | ||||
} | } | ||||
Pusher: convert.ToUser(ctx.User, ctx.IsSigned, false), | Pusher: convert.ToUser(ctx.User, ctx.IsSigned, false), | ||||
Sender: convert.ToUser(ctx.User, ctx.IsSigned, false), | Sender: convert.ToUser(ctx.User, ctx.IsSigned, false), | ||||
}); err != nil { | }); err != nil { | ||||
ctx.Error(500, "PrepareWebhook: ", err) | |||||
ctx.Error(http.StatusInternalServerError, "PrepareWebhook: ", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// CreateHook create a hook for a repository | // CreateHook create a hook for a repository | ||||
if models.IsErrWebhookNotExist(err) { | if models.IsErrWebhookNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "DeleteWebhookByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteWebhookByRepoID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/IssueList" | // "$ref": "#/responses/IssueList" | ||||
var isClosed util.OptionalBool | var isClosed util.OptionalBool | ||||
switch ctx.Query("state") { | switch ctx.Query("state") { | ||||
case "closed": | case "closed": | ||||
OrderBy: models.SearchOrderByRecentUpdated, | OrderBy: models.SearchOrderByRecentUpdated, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "SearchRepositoryByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err) | |||||
return | return | ||||
} | } | ||||
if splitted := strings.Split(labels, ","); labels != "" && len(splitted) > 0 { | if splitted := strings.Split(labels, ","); labels != "" && len(splitted) > 0 { | ||||
labelIDs, err = models.GetLabelIDsInReposByNames(repoIDs, splitted) | labelIDs, err = models.GetLabelIDsInReposByNames(repoIDs, splitted) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelIDsInRepoByNames", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "Issues", err) | |||||
ctx.Error(http.StatusInternalServerError, "Issues", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
ctx.SetLinkHeader(issueCount, setting.UI.IssuePagingNum) | ctx.SetLinkHeader(issueCount, setting.UI.IssuePagingNum) | ||||
ctx.JSON(200, &apiIssues) | |||||
ctx.JSON(http.StatusOK, &apiIssues) | |||||
} | } | ||||
// ListIssues list the issues of a repository | // ListIssues list the issues of a repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/IssueList" | // "$ref": "#/responses/IssueList" | ||||
var isClosed util.OptionalBool | var isClosed util.OptionalBool | ||||
switch ctx.Query("state") { | switch ctx.Query("state") { | ||||
case "closed": | case "closed": | ||||
if splitted := strings.Split(ctx.Query("labels"), ","); len(splitted) > 0 { | if splitted := strings.Split(ctx.Query("labels"), ","); len(splitted) > 0 { | ||||
labelIDs, err = models.GetLabelIDsInRepoByNames(ctx.Repo.Repository.ID, splitted) | labelIDs, err = models.GetLabelIDsInRepoByNames(ctx.Repo.Repository.ID, splitted) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelIDsInRepoByNames", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "Issues", err) | |||||
ctx.Error(http.StatusInternalServerError, "Issues", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
ctx.SetLinkHeader(ctx.Repo.Repository.NumIssues, setting.UI.IssuePagingNum) | ctx.SetLinkHeader(ctx.Repo.Repository.NumIssues, setting.UI.IssuePagingNum) | ||||
ctx.JSON(200, &apiIssues) | |||||
ctx.JSON(http.StatusOK, &apiIssues) | |||||
} | } | ||||
// GetIssue get an issue of a repository | // GetIssue get an issue of a repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Issue" | // "$ref": "#/responses/Issue" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, issue.APIFormat()) | |||||
ctx.JSON(http.StatusOK, issue.APIFormat()) | |||||
} | } | ||||
// CreateIssue create an issue of a repository | // CreateIssue create an issue of a repository | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Issue" | // "$ref": "#/responses/Issue" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
// "412": | |||||
// "$ref": "#/responses/error" | |||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
var deadlineUnix timeutil.TimeStamp | var deadlineUnix timeutil.TimeStamp | ||||
if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { | if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { | ||||
assigneeIDs, err = models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) | assigneeIDs, err = models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) | |||||
} else { | } else { | ||||
ctx.Error(500, "AddAssigneeByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddAssigneeByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
for _, aID := range assigneeIDs { | for _, aID := range assigneeIDs { | ||||
assignee, err := models.GetUserByID(aID) | assignee, err := models.GetUserByID(aID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByID", err) | |||||
return | return | ||||
} | } | ||||
valid, err := models.CanBeAssigned(assignee, ctx.Repo.Repository, false) | valid, err := models.CanBeAssigned(assignee, ctx.Repo.Repository, false) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "canBeAssigned", err) | |||||
ctx.Error(http.StatusInternalServerError, "canBeAssigned", err) | |||||
return | return | ||||
} | } | ||||
if !valid { | if !valid { | ||||
ctx.Error(422, "canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: aID, RepoName: ctx.Repo.Repository.Name}) | |||||
ctx.Error(http.StatusUnprocessableEntity, "canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: aID, RepoName: ctx.Repo.Repository.Name}) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err := issue_service.NewIssue(ctx.Repo.Repository, issue, form.Labels, nil, assigneeIDs); err != nil { | if err := issue_service.NewIssue(ctx.Repo.Repository, issue, form.Labels, nil, assigneeIDs); err != nil { | ||||
if models.IsErrUserDoesNotHaveAccessToRepo(err) { | if models.IsErrUserDoesNotHaveAccessToRepo(err) { | ||||
ctx.Error(400, "UserDoesNotHaveAccessToRepo", err) | |||||
ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err) | |||||
return | return | ||||
} | } | ||||
ctx.Error(500, "NewIssue", err) | |||||
ctx.Error(http.StatusInternalServerError, "NewIssue", err) | |||||
return | return | ||||
} | } | ||||
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") | ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") | ||||
return | return | ||||
} | } | ||||
ctx.Error(500, "ChangeStatus", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeStatus", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
// Refetch from database to assign some automatic values | // Refetch from database to assign some automatic values | ||||
issue, err = models.GetIssueByID(issue.ID) | issue, err = models.GetIssueByID(issue.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetIssueByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByID", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, issue.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, issue.APIFormat()) | |||||
} | } | ||||
// EditIssue modify an issue of a repository | // EditIssue modify an issue of a repository | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Issue" | // "$ref": "#/responses/Issue" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
// "412": | |||||
// "$ref": "#/responses/error" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
err = issue.LoadAttributes() | err = issue.LoadAttributes() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "LoadAttributes", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) | |||||
return | return | ||||
} | } | ||||
if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypeIssues) { | if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypeIssues) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | ||||
ctx.Error(500, "UpdateIssueDeadline", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err) | |||||
return | return | ||||
} | } | ||||
issue.DeadlineUnix = deadlineUnix | issue.DeadlineUnix = deadlineUnix | ||||
err = issue_service.UpdateAssignees(issue, oneAssignee, form.Assignees, ctx.User) | err = issue_service.UpdateAssignees(issue, oneAssignee, form.Assignees, ctx.User) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "UpdateAssignees", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateAssignees", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
oldMilestoneID := issue.MilestoneID | oldMilestoneID := issue.MilestoneID | ||||
issue.MilestoneID = *form.Milestone | issue.MilestoneID = *form.Milestone | ||||
if err = issue_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil { | if err = issue_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil { | ||||
ctx.Error(500, "ChangeMilestoneAssign", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeMilestoneAssign", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err = models.UpdateIssue(issue); err != nil { | if err = models.UpdateIssue(issue); err != nil { | ||||
ctx.Error(500, "UpdateIssue", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateIssue", err) | |||||
return | return | ||||
} | } | ||||
if form.State != nil { | if form.State != nil { | ||||
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") | ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") | ||||
return | return | ||||
} | } | ||||
ctx.Error(500, "ChangeStatus", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeStatus", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
// Refetch from database to assign some automatic values | // Refetch from database to assign some automatic values | ||||
issue, err = models.GetIssueByID(issue.ID) | issue, err = models.GetIssueByID(issue.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetIssueByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByID", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, issue.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, issue.APIFormat()) | |||||
} | } | ||||
// UpdateIssueDeadline updates an issue deadline | // UpdateIssueDeadline updates an issue deadline | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/IssueDeadline" | // "$ref": "#/responses/IssueDeadline" | ||||
// "403": | // "403": | ||||
// description: Not repo writer | |||||
// "$ref": "#/responses/forbidden" | |||||
// "404": | // "404": | ||||
// description: Issue not found | |||||
// "$ref": "#/responses/notFound" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) { | if !ctx.Repo.CanWrite(models.UnitTypeIssues) { | ||||
ctx.Status(403) | |||||
ctx.Error(http.StatusForbidden, "", "Not repo writer") | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | ||||
ctx.Error(500, "UpdateIssueDeadline", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, api.IssueDeadline{Deadline: &deadline}) | |||||
ctx.JSON(http.StatusCreated, api.IssueDeadline{Deadline: &deadline}) | |||||
} | } |
import ( | import ( | ||||
"errors" | "errors" | ||||
"net/http" | |||||
"time" | "time" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/CommentList" | // "$ref": "#/responses/CommentList" | ||||
var since time.Time | var since time.Time | ||||
if len(ctx.Query("since")) > 0 { | if len(ctx.Query("since")) > 0 { | ||||
since, _ = time.Parse(time.RFC3339, ctx.Query("since")) | since, _ = time.Parse(time.RFC3339, ctx.Query("since")) | ||||
// comments,err:=models.GetCommentsByIssueIDSince(, since) | // comments,err:=models.GetCommentsByIssueIDSince(, since) | ||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetRawIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetRawIssueByIndex", err) | |||||
return | return | ||||
} | } | ||||
issue.Repo = ctx.Repo.Repository | issue.Repo = ctx.Repo.Repository | ||||
Type: models.CommentTypeComment, | Type: models.CommentTypeComment, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "FindComments", err) | |||||
ctx.Error(http.StatusInternalServerError, "FindComments", err) | |||||
return | return | ||||
} | } | ||||
if err := models.CommentList(comments).LoadPosters(); err != nil { | if err := models.CommentList(comments).LoadPosters(); err != nil { | ||||
ctx.Error(500, "LoadPosters", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadPosters", err) | |||||
return | return | ||||
} | } | ||||
comment.Issue = issue | comment.Issue = issue | ||||
apiComments[i] = comments[i].APIFormat() | apiComments[i] = comments[i].APIFormat() | ||||
} | } | ||||
ctx.JSON(200, &apiComments) | |||||
ctx.JSON(http.StatusOK, &apiComments) | |||||
} | } | ||||
// ListRepoIssueComments returns all issue-comments for a repo | // ListRepoIssueComments returns all issue-comments for a repo | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/CommentList" | // "$ref": "#/responses/CommentList" | ||||
var since time.Time | var since time.Time | ||||
if len(ctx.Query("since")) > 0 { | if len(ctx.Query("since")) > 0 { | ||||
since, _ = time.Parse(time.RFC3339, ctx.Query("since")) | since, _ = time.Parse(time.RFC3339, ctx.Query("since")) | ||||
Type: models.CommentTypeComment, | Type: models.CommentTypeComment, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "FindComments", err) | |||||
ctx.Error(http.StatusInternalServerError, "FindComments", err) | |||||
return | return | ||||
} | } | ||||
if err = models.CommentList(comments).LoadPosters(); err != nil { | if err = models.CommentList(comments).LoadPosters(); err != nil { | ||||
ctx.Error(500, "LoadPosters", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadPosters", err) | |||||
return | return | ||||
} | } | ||||
apiComments := make([]*api.Comment, len(comments)) | apiComments := make([]*api.Comment, len(comments)) | ||||
if err := models.CommentList(comments).LoadIssues(); err != nil { | if err := models.CommentList(comments).LoadIssues(); err != nil { | ||||
ctx.Error(500, "LoadIssues", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadIssues", err) | |||||
return | return | ||||
} | } | ||||
if err := models.CommentList(comments).LoadPosters(); err != nil { | if err := models.CommentList(comments).LoadPosters(); err != nil { | ||||
ctx.Error(500, "LoadPosters", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadPosters", err) | |||||
return | return | ||||
} | } | ||||
if _, err := models.CommentList(comments).Issues().LoadRepositories(); err != nil { | if _, err := models.CommentList(comments).Issues().LoadRepositories(); err != nil { | ||||
ctx.Error(500, "LoadRepositories", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadRepositories", err) | |||||
return | return | ||||
} | } | ||||
for i := range comments { | for i := range comments { | ||||
apiComments[i] = comments[i].APIFormat() | apiComments[i] = comments[i].APIFormat() | ||||
} | } | ||||
ctx.JSON(200, &apiComments) | |||||
ctx.JSON(http.StatusOK, &apiComments) | |||||
} | } | ||||
// CreateIssueComment create a comment for an issue | // CreateIssueComment create a comment for an issue | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Comment" | // "$ref": "#/responses/Comment" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
return | return | ||||
} | } | ||||
if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { | if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { | ||||
ctx.Error(403, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked"))) | |||||
ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked"))) | |||||
return | return | ||||
} | } | ||||
comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil) | comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "CreateIssueComment", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateIssueComment", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, comment.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, comment.APIFormat()) | |||||
} | } | ||||
// EditIssueComment modify a comment of an issue | // EditIssueComment modify a comment of an issue | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Comment" | // "$ref": "#/responses/Comment" | ||||
// "204": | |||||
// "$ref": "#/responses/empty" | |||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
editIssueComment(ctx, form) | editIssueComment(ctx, form) | ||||
} | } | ||||
if models.IsErrCommentNotExist(err) { | if models.IsErrCommentNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetCommentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetCommentByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} else if comment.Type != models.CommentTypeComment { | } else if comment.Type != models.CommentTypeComment { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
return | return | ||||
} | } | ||||
oldContent := comment.Content | oldContent := comment.Content | ||||
comment.Content = form.Body | comment.Content = form.Body | ||||
if err := comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil { | if err := comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil { | ||||
ctx.Error(500, "UpdateComment", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateComment", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, comment.APIFormat()) | |||||
ctx.JSON(http.StatusOK, comment.APIFormat()) | |||||
} | } | ||||
// DeleteIssueComment delete a comment from an issue | // DeleteIssueComment delete a comment from an issue | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
deleteIssueComment(ctx) | deleteIssueComment(ctx) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
deleteIssueComment(ctx) | deleteIssueComment(ctx) | ||||
} | } | ||||
if models.IsErrCommentNotExist(err) { | if models.IsErrCommentNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetCommentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetCommentByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} else if comment.Type != models.CommentTypeComment { | } else if comment.Type != models.CommentTypeComment { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
return | return | ||||
} | } | ||||
if err = comment_service.DeleteComment(comment, ctx.User); err != nil { | if err = comment_service.DeleteComment(comment, ctx.User); err != nil { | ||||
ctx.Error(500, "DeleteCommentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteCommentByID", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// "$ref": "#/responses/LabelList" | // "$ref": "#/responses/LabelList" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if err := issue.LoadAttributes(); err != nil { | if err := issue.LoadAttributes(); err != nil { | ||||
ctx.Error(500, "LoadAttributes", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) | |||||
return | return | ||||
} | } | ||||
for i := range issue.Labels { | for i := range issue.Labels { | ||||
apiLabels[i] = issue.Labels[i].APIFormat() | apiLabels[i] = issue.Labels[i].APIFormat() | ||||
} | } | ||||
ctx.JSON(200, &apiLabels) | |||||
ctx.JSON(http.StatusOK, &apiLabels) | |||||
} | } | ||||
// AddIssueLabels add labels for an issue | // AddIssueLabels add labels for an issue | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/LabelList" | // "$ref": "#/responses/LabelList" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsInRepoByIDs", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDs", err) | |||||
return | return | ||||
} | } | ||||
if err = issue_service.AddLabels(issue, ctx.User, labels); err != nil { | if err = issue_service.AddLabels(issue, ctx.User, labels); err != nil { | ||||
ctx.Error(500, "AddLabels", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddLabels", err) | |||||
return | return | ||||
} | } | ||||
labels, err = models.GetLabelsByIssueID(issue.ID) | labels, err = models.GetLabelsByIssueID(issue.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsByIssueID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelsByIssueID", err) | |||||
return | return | ||||
} | } | ||||
for i := range labels { | for i := range labels { | ||||
apiLabels[i] = labels[i].APIFormat() | apiLabels[i] = labels[i].APIFormat() | ||||
} | } | ||||
ctx.JSON(200, &apiLabels) | |||||
ctx.JSON(http.StatusOK, &apiLabels) | |||||
} | } | ||||
// DeleteIssueLabel delete a label for an issue | // DeleteIssueLabel delete a label for an issue | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
label, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | label, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrLabelNotExist(err) { | if models.IsErrLabelNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetLabelInRepoByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelInRepoByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if err := models.DeleteIssueLabel(issue, label, ctx.User); err != nil { | if err := models.DeleteIssueLabel(issue, label, ctx.User); err != nil { | ||||
ctx.Error(500, "DeleteIssueLabel", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteIssueLabel", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// ReplaceIssueLabels replace labels for an issue | // ReplaceIssueLabels replace labels for an issue | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/LabelList" | // "$ref": "#/responses/LabelList" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsInRepoByIDs", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDs", err) | |||||
return | return | ||||
} | } | ||||
if err := issue.ReplaceLabels(labels, ctx.User); err != nil { | if err := issue.ReplaceLabels(labels, ctx.User); err != nil { | ||||
ctx.Error(500, "ReplaceLabels", err) | |||||
ctx.Error(http.StatusInternalServerError, "ReplaceLabels", err) | |||||
return | return | ||||
} | } | ||||
labels, err = models.GetLabelsByIssueID(issue.ID) | labels, err = models.GetLabelsByIssueID(issue.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsByIssueID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelsByIssueID", err) | |||||
return | return | ||||
} | } | ||||
for i := range labels { | for i := range labels { | ||||
apiLabels[i] = labels[i].APIFormat() | apiLabels[i] = labels[i].APIFormat() | ||||
} | } | ||||
ctx.JSON(200, &apiLabels) | |||||
ctx.JSON(http.StatusOK, &apiLabels) | |||||
} | } | ||||
// ClearIssueLabels delete all the labels for an issue | // ClearIssueLabels delete all the labels for an issue | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
if err := issue_service.ClearLabels(issue, ctx.User); err != nil { | if err := issue_service.ClearLabels(issue, ctx.User); err != nil { | ||||
ctx.Error(500, "ClearLabels", err) | |||||
ctx.Error(http.StatusInternalServerError, "ClearLabels", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
import ( | import ( | ||||
"errors" | "errors" | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/ReactionResponseList" | // "$ref": "#/responses/ReactionResponseList" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
comment, err := models.GetCommentByID(ctx.ParamsInt64(":id")) | comment, err := models.GetCommentByID(ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrCommentNotExist(err) { | if models.IsErrCommentNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetCommentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetCommentByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanRead(models.UnitTypeIssues) && !ctx.User.IsAdmin { | if !ctx.Repo.CanRead(models.UnitTypeIssues) && !ctx.User.IsAdmin { | ||||
ctx.Error(403, "GetIssueCommentReactions", errors.New("no permission to get reactions")) | |||||
ctx.Error(http.StatusForbidden, "GetIssueCommentReactions", errors.New("no permission to get reactions")) | |||||
return | return | ||||
} | } | ||||
reactions, err := models.FindCommentReactions(comment) | reactions, err := models.FindCommentReactions(comment) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "FindIssueReactions", err) | |||||
ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err) | |||||
return | return | ||||
} | } | ||||
_, err = reactions.LoadUsers() | _, err = reactions.LoadUsers() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ReactionList.LoadUsers()", err) | |||||
ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err) | |||||
return | return | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
ctx.JSON(200, result) | |||||
ctx.JSON(http.StatusOK, result) | |||||
} | } | ||||
// PostIssueCommentReaction add a reaction to a comment of a issue | // PostIssueCommentReaction add a reaction to a comment of a issue | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/ReactionResponse" | // "$ref": "#/responses/ReactionResponse" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
changeIssueCommentReaction(ctx, form, true) | changeIssueCommentReaction(ctx, form, true) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
changeIssueCommentReaction(ctx, form, false) | changeIssueCommentReaction(ctx, form, false) | ||||
} | } | ||||
if models.IsErrCommentNotExist(err) { | if models.IsErrCommentNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetCommentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetCommentByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
err = comment.LoadIssue() | err = comment.LoadIssue() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "comment.LoadIssue() failed", err) | |||||
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err) | |||||
} | } | ||||
if comment.Issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { | if comment.Issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { | ||||
ctx.Error(403, "ChangeIssueCommentReaction", errors.New("no permission to change reaction")) | |||||
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction")) | |||||
return | return | ||||
} | } | ||||
reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Reaction) | reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Reaction) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrForbiddenIssueReaction(err) { | if models.IsErrForbiddenIssueReaction(err) { | ||||
ctx.Error(403, err.Error(), err) | |||||
ctx.Error(http.StatusForbidden, err.Error(), err) | |||||
} else { | } else { | ||||
ctx.Error(500, "CreateCommentReaction", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
_, err = reaction.LoadUser() | _, err = reaction.LoadUser() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "Reaction.LoadUser()", err) | |||||
ctx.Error(http.StatusInternalServerError, "Reaction.LoadUser()", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, api.ReactionResponse{ | |||||
ctx.JSON(http.StatusCreated, api.ReactionResponse{ | |||||
User: reaction.User.APIFormat(), | User: reaction.User.APIFormat(), | ||||
Reaction: reaction.Type, | Reaction: reaction.Type, | ||||
Created: reaction.CreatedUnix.AsTime(), | Created: reaction.CreatedUnix.AsTime(), | ||||
// DeleteIssueCommentReaction part | // DeleteIssueCommentReaction part | ||||
err = models.DeleteCommentReaction(ctx.User, comment.Issue, comment, form.Reaction) | err = models.DeleteCommentReaction(ctx.User, comment.Issue, comment, form.Reaction) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "DeleteCommentReaction", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteCommentReaction", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(200) | |||||
//ToDo respond 204 | |||||
ctx.Status(http.StatusOK) | |||||
} | } | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/ReactionResponseList" | // "$ref": "#/responses/ReactionResponseList" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanRead(models.UnitTypeIssues) && !ctx.User.IsAdmin { | if !ctx.Repo.CanRead(models.UnitTypeIssues) && !ctx.User.IsAdmin { | ||||
ctx.Error(403, "GetIssueReactions", errors.New("no permission to get reactions")) | |||||
ctx.Error(http.StatusForbidden, "GetIssueReactions", errors.New("no permission to get reactions")) | |||||
return | return | ||||
} | } | ||||
reactions, err := models.FindIssueReactions(issue) | reactions, err := models.FindIssueReactions(issue) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "FindIssueReactions", err) | |||||
ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err) | |||||
return | return | ||||
} | } | ||||
_, err = reactions.LoadUsers() | _, err = reactions.LoadUsers() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ReactionList.LoadUsers()", err) | |||||
ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err) | |||||
return | return | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
ctx.JSON(200, result) | |||||
ctx.JSON(http.StatusOK, result) | |||||
} | } | ||||
// PostIssueReaction add a reaction to a comment of a issue | // PostIssueReaction add a reaction to a comment of a issue | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/ReactionResponse" | // "$ref": "#/responses/ReactionResponse" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
changeIssueReaction(ctx, form, true) | changeIssueReaction(ctx, form, true) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
changeIssueReaction(ctx, form, false) | changeIssueReaction(ctx, form, false) | ||||
} | } | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { | if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { | ||||
ctx.Error(403, "ChangeIssueCommentReaction", errors.New("no permission to change reaction")) | |||||
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction")) | |||||
return | return | ||||
} | } | ||||
reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Reaction) | reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Reaction) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrForbiddenIssueReaction(err) { | if models.IsErrForbiddenIssueReaction(err) { | ||||
ctx.Error(403, err.Error(), err) | |||||
ctx.Error(http.StatusForbidden, err.Error(), err) | |||||
} else { | } else { | ||||
ctx.Error(500, "CreateCommentReaction", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
_, err = reaction.LoadUser() | _, err = reaction.LoadUser() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "Reaction.LoadUser()", err) | |||||
ctx.Error(http.StatusInternalServerError, "Reaction.LoadUser()", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, api.ReactionResponse{ | |||||
ctx.JSON(http.StatusCreated, api.ReactionResponse{ | |||||
User: reaction.User.APIFormat(), | User: reaction.User.APIFormat(), | ||||
Reaction: reaction.Type, | Reaction: reaction.Type, | ||||
Created: reaction.CreatedUnix.AsTime(), | Created: reaction.CreatedUnix.AsTime(), | ||||
// DeleteIssueReaction part | // DeleteIssueReaction part | ||||
err = models.DeleteIssueReaction(ctx.User, issue, form.Reaction) | err = models.DeleteIssueReaction(ctx.User, issue, form.Reaction) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "DeleteIssueReaction", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteIssueReaction", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(200) | |||||
//ToDo respond 204 | |||||
ctx.Status(http.StatusOK) | |||||
} | } | ||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
) | ) | ||||
// "403": | // "403": | ||||
// description: Not repo writer, user does not have rights to toggle stopwatch | // description: Not repo writer, user does not have rights to toggle stopwatch | ||||
// "404": | // "404": | ||||
// description: Issue not found | |||||
// "$ref": "#/responses/notFound" | |||||
// "409": | // "409": | ||||
// description: Cannot start a stopwatch again if it already exists | // description: Cannot start a stopwatch again if it already exists | ||||
issue, err := prepareIssueStopwatch(ctx, false) | issue, err := prepareIssueStopwatch(ctx, false) | ||||
if err != nil { | if err != nil { | ||||
return | return | ||||
} | } | ||||
if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil { | if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil { | ||||
ctx.Error(500, "CreateOrStopIssueStopwatch", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(201) | |||||
ctx.Status(http.StatusCreated) | |||||
} | } | ||||
// StopIssueStopwatch stops a stopwatch for the given issue. | // StopIssueStopwatch stops a stopwatch for the given issue. | ||||
// "403": | // "403": | ||||
// description: Not repo writer, user does not have rights to toggle stopwatch | // description: Not repo writer, user does not have rights to toggle stopwatch | ||||
// "404": | // "404": | ||||
// description: Issue not found | |||||
// "$ref": "#/responses/notFound" | |||||
// "409": | // "409": | ||||
// description: Cannot stop a non existent stopwatch | // description: Cannot stop a non existent stopwatch | ||||
issue, err := prepareIssueStopwatch(ctx, true) | issue, err := prepareIssueStopwatch(ctx, true) | ||||
if err != nil { | if err != nil { | ||||
return | return | ||||
} | } | ||||
if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil { | if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil { | ||||
ctx.Error(500, "CreateOrStopIssueStopwatch", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(201) | |||||
ctx.Status(http.StatusCreated) | |||||
} | } | ||||
// DeleteIssueStopwatch delete a specific stopwatch | // DeleteIssueStopwatch delete a specific stopwatch | ||||
// "403": | // "403": | ||||
// description: Not repo writer, user does not have rights to toggle stopwatch | // description: Not repo writer, user does not have rights to toggle stopwatch | ||||
// "404": | // "404": | ||||
// description: Issue not found | |||||
// "$ref": "#/responses/notFound" | |||||
// "409": | // "409": | ||||
// description: Cannot cancel a non existent stopwatch | // description: Cannot cancel a non existent stopwatch | ||||
issue, err := prepareIssueStopwatch(ctx, true) | issue, err := prepareIssueStopwatch(ctx, true) | ||||
if err != nil { | if err != nil { | ||||
return | return | ||||
} | } | ||||
if err := models.CancelStopwatch(ctx.User, issue); err != nil { | if err := models.CancelStopwatch(ctx.User, issue); err != nil { | ||||
ctx.Error(500, "CancelStopwatch", err) | |||||
ctx.Error(http.StatusInternalServerError, "CancelStopwatch", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.Issue, error) { | func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.Issue, error) { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return nil, err | return nil, err | ||||
} | } | ||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) { | if !ctx.Repo.CanWrite(models.UnitTypeIssues) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return nil, err | return nil, err | ||||
} | } | ||||
if !ctx.Repo.CanUseTimetracker(issue, ctx.User) { | if !ctx.Repo.CanUseTimetracker(issue, ctx.User) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return nil, err | return nil, err | ||||
} | } | ||||
if models.StopwatchExists(ctx.User.ID, issue.ID) != shouldExist { | if models.StopwatchExists(ctx.User.ID, issue.ID) != shouldExist { | ||||
if shouldExist { | if shouldExist { | ||||
ctx.Error(409, "StopwatchExists", "cannot stop/cancel a non existent stopwatch") | |||||
ctx.Error(http.StatusConflict, "StopwatchExists", "cannot stop/cancel a non existent stopwatch") | |||||
} else { | } else { | ||||
ctx.Error(409, "StopwatchExists", "cannot start a stopwatch again if it already exists") | |||||
ctx.Error(http.StatusConflict, "StopwatchExists", "cannot start a stopwatch again if it already exists") | |||||
} | } | ||||
return nil, err | return nil, err | ||||
} | } | ||||
sws, err := models.GetUserStopwatches(ctx.User.ID) | sws, err := models.GetUserStopwatches(ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserStopwatches", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserStopwatches", err) | |||||
return | return | ||||
} | } | ||||
apiSWs, err := sws.APIFormat() | apiSWs, err := sws.APIFormat() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "APIFormat", err) | |||||
ctx.Error(http.StatusInternalServerError, "APIFormat", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, apiSWs) | |||||
ctx.JSON(http.StatusOK, apiSWs) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
) | ) | ||||
// "304": | // "304": | ||||
// description: User can only subscribe itself if he is no admin | // description: User can only subscribe itself if he is no admin | ||||
// "404": | // "404": | ||||
// description: Issue not found | |||||
// "$ref": "#/responses/notFound" | |||||
setIssueSubscription(ctx, true) | setIssueSubscription(ctx, true) | ||||
} | } | ||||
// "304": | // "304": | ||||
// description: User can only subscribe itself if he is no admin | // description: User can only subscribe itself if he is no admin | ||||
// "404": | // "404": | ||||
// description: Issue not found | |||||
// "$ref": "#/responses/notFound" | |||||
setIssueSubscription(ctx, false) | setIssueSubscription(ctx, false) | ||||
} | } | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
//only admin and user for itself can change subscription | //only admin and user for itself can change subscription | ||||
if user.ID != ctx.User.ID && !ctx.User.IsAdmin { | if user.ID != ctx.User.ID && !ctx.User.IsAdmin { | ||||
ctx.Error(403, "User", nil) | |||||
ctx.Error(http.StatusForbidden, "User", nil) | |||||
return | return | ||||
} | } | ||||
if err := models.CreateOrUpdateIssueWatch(user.ID, issue.ID, watch); err != nil { | if err := models.CreateOrUpdateIssueWatch(user.ID, issue.ID, watch); err != nil { | ||||
ctx.Error(500, "CreateOrUpdateIssueWatch", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateOrUpdateIssueWatch", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(201) | |||||
ctx.Status(http.StatusCreated) | |||||
} | } | ||||
// GetIssueSubscribers return subscribers of an issue | // GetIssueSubscribers return subscribers of an issue | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
// "404": | // "404": | ||||
// description: Issue not found | |||||
// "$ref": "#/responses/notFound" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
iwl, err := models.GetIssueWatchers(issue.ID) | iwl, err := models.GetIssueWatchers(issue.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetIssueWatchers", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueWatchers", err) | |||||
return | return | ||||
} | } | ||||
users, err := iwl.LoadWatchUsers() | users, err := iwl.LoadWatchUsers() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "LoadWatchUsers", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadWatchUsers", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, users.APIFormat()) | |||||
ctx.JSON(http.StatusOK, users.APIFormat()) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TrackedTimeList" | // "$ref": "#/responses/TrackedTimeList" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
if !ctx.Repo.Repository.IsTimetrackerEnabled() { | if !ctx.Repo.Repository.IsTimetrackerEnabled() { | ||||
ctx.NotFound("Timetracker is disabled") | ctx.NotFound("Timetracker is disabled") | ||||
return | return | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{IssueID: issue.ID}) | trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{IssueID: issue.ID}) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetTrackedTimesByIssue", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByIssue", err) | |||||
return | return | ||||
} | } | ||||
apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | ||||
ctx.JSON(200, &apiTrackedTimes) | |||||
ctx.JSON(http.StatusOK, &apiTrackedTimes) | |||||
} | } | ||||
// AddTime adds time manual to the given issue | // AddTime adds time manual to the given issue | ||||
// "400": | // "400": | ||||
// "$ref": "#/responses/error" | // "$ref": "#/responses/error" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/error" | |||||
// "$ref": "#/responses/forbidden" | |||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrIssueNotExist(err) { | if models.IsErrIssueNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetIssueByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if !ctx.Repo.CanUseTimetracker(issue, ctx.User) { | if !ctx.Repo.CanUseTimetracker(issue, ctx.User) { | ||||
if !ctx.Repo.Repository.IsTimetrackerEnabled() { | if !ctx.Repo.Repository.IsTimetrackerEnabled() { | ||||
ctx.JSON(400, struct{ Message string }{Message: "time tracking disabled"}) | |||||
ctx.Error(http.StatusBadRequest, "", "time tracking disabled") | |||||
return | return | ||||
} | } | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
trackedTime, err := models.AddTime(ctx.User, issue, form.Time) | trackedTime, err := models.AddTime(ctx.User, issue, form.Time) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "AddTime", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddTime", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, trackedTime.APIFormat()) | |||||
ctx.JSON(http.StatusOK, trackedTime.APIFormat()) | |||||
} | } | ||||
// ListTrackedTimesByUser lists all tracked times of the user | // ListTrackedTimesByUser lists all tracked times of the user | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TrackedTimeList" | // "$ref": "#/responses/TrackedTimeList" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
if !ctx.Repo.Repository.IsTimetrackerEnabled() { | if !ctx.Repo.Repository.IsTimetrackerEnabled() { | ||||
ctx.JSON(400, struct{ Message string }{Message: "time tracking disabled"}) | |||||
ctx.Error(http.StatusBadRequest, "", "time tracking disabled") | |||||
return | return | ||||
} | } | ||||
user, err := models.GetUserByName(ctx.Params(":timetrackingusername")) | user, err := models.GetUserByName(ctx.Params(":timetrackingusername")) | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.NotFound(err) | ctx.NotFound(err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
UserID: user.ID, | UserID: user.ID, | ||||
RepositoryID: ctx.Repo.Repository.ID}) | RepositoryID: ctx.Repo.Repository.ID}) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetTrackedTimesByUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err) | |||||
return | return | ||||
} | } | ||||
apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | ||||
ctx.JSON(200, &apiTrackedTimes) | |||||
ctx.JSON(http.StatusOK, &apiTrackedTimes) | |||||
} | } | ||||
// ListTrackedTimesByRepository lists all tracked times of the repository | // ListTrackedTimesByRepository lists all tracked times of the repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TrackedTimeList" | // "$ref": "#/responses/TrackedTimeList" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
if !ctx.Repo.Repository.IsTimetrackerEnabled() { | if !ctx.Repo.Repository.IsTimetrackerEnabled() { | ||||
ctx.JSON(400, struct{ Message string }{Message: "time tracking disabled"}) | |||||
ctx.Error(http.StatusBadRequest, "", "time tracking disabled") | |||||
return | return | ||||
} | } | ||||
trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{ | trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{ | ||||
RepositoryID: ctx.Repo.Repository.ID}) | RepositoryID: ctx.Repo.Repository.ID}) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetTrackedTimesByUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err) | |||||
return | return | ||||
} | } | ||||
apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | ||||
ctx.JSON(200, &apiTrackedTimes) | |||||
ctx.JSON(http.StatusOK, &apiTrackedTimes) | |||||
} | } | ||||
// ListMyTrackedTimes lists all tracked times of the current user | // ListMyTrackedTimes lists all tracked times of the current user | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TrackedTimeList" | // "$ref": "#/responses/TrackedTimeList" | ||||
trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{UserID: ctx.User.ID}) | trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{UserID: ctx.User.ID}) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetTrackedTimesByUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err) | |||||
return | return | ||||
} | } | ||||
apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes) | ||||
ctx.JSON(200, &apiTrackedTimes) | |||||
ctx.JSON(http.StatusOK, &apiTrackedTimes) | |||||
} | } |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/DeployKeyList" | // "$ref": "#/responses/DeployKeyList" | ||||
var keys []*models.DeployKey | var keys []*models.DeployKey | ||||
var err error | var err error | ||||
} | } | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ListDeployKeys", err) | |||||
ctx.Error(http.StatusInternalServerError, "ListDeployKeys", err) | |||||
return | return | ||||
} | } | ||||
apiKeys := make([]*api.DeployKey, len(keys)) | apiKeys := make([]*api.DeployKey, len(keys)) | ||||
for i := range keys { | for i := range keys { | ||||
if err = keys[i].GetContent(); err != nil { | if err = keys[i].GetContent(); err != nil { | ||||
ctx.Error(500, "GetContent", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetContent", err) | |||||
return | return | ||||
} | } | ||||
apiKeys[i] = convert.ToDeployKey(apiLink, keys[i]) | apiKeys[i] = convert.ToDeployKey(apiLink, keys[i]) | ||||
} | } | ||||
} | } | ||||
ctx.JSON(200, &apiKeys) | |||||
ctx.JSON(http.StatusOK, &apiKeys) | |||||
} | } | ||||
// GetDeployKey get a deploy key by id | // GetDeployKey get a deploy key by id | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/DeployKey" | // "$ref": "#/responses/DeployKey" | ||||
key, err := models.GetDeployKeyByID(ctx.ParamsInt64(":id")) | key, err := models.GetDeployKeyByID(ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrDeployKeyNotExist(err) { | if models.IsErrDeployKeyNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetDeployKeyByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetDeployKeyByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if err = key.GetContent(); err != nil { | if err = key.GetContent(); err != nil { | ||||
ctx.Error(500, "GetContent", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetContent", err) | |||||
return | return | ||||
} | } | ||||
if ctx.User.IsAdmin || ((ctx.Repo.Repository.ID == key.RepoID) && (ctx.User.ID == ctx.Repo.Owner.ID)) { | if ctx.User.IsAdmin || ((ctx.Repo.Repository.ID == key.RepoID) && (ctx.User.ID == ctx.Repo.Owner.ID)) { | ||||
apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Repo.Repository) | apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Repo.Repository) | ||||
} | } | ||||
ctx.JSON(200, apiKey) | |||||
ctx.JSON(http.StatusOK, apiKey) | |||||
} | } | ||||
// HandleCheckKeyStringError handle check key error | // HandleCheckKeyStringError handle check key error | ||||
func HandleCheckKeyStringError(ctx *context.APIContext, err error) { | func HandleCheckKeyStringError(ctx *context.APIContext, err error) { | ||||
if models.IsErrSSHDisabled(err) { | if models.IsErrSSHDisabled(err) { | ||||
ctx.Error(422, "", "SSH is disabled") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "SSH is disabled") | |||||
} else if models.IsErrKeyUnableVerify(err) { | } else if models.IsErrKeyUnableVerify(err) { | ||||
ctx.Error(422, "", "Unable to verify key content") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Unable to verify key content") | |||||
} else { | } else { | ||||
ctx.Error(422, "", fmt.Errorf("Invalid key content: %v", err)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("Invalid key content: %v", err)) | |||||
} | } | ||||
} | } | ||||
func HandleAddKeyError(ctx *context.APIContext, err error) { | func HandleAddKeyError(ctx *context.APIContext, err error) { | ||||
switch { | switch { | ||||
case models.IsErrDeployKeyAlreadyExist(err): | case models.IsErrDeployKeyAlreadyExist(err): | ||||
ctx.Error(422, "", "This key has already been added to this repository") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "This key has already been added to this repository") | |||||
case models.IsErrKeyAlreadyExist(err): | case models.IsErrKeyAlreadyExist(err): | ||||
ctx.Error(422, "", "Key content has been used as non-deploy key") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Key content has been used as non-deploy key") | |||||
case models.IsErrKeyNameAlreadyUsed(err): | case models.IsErrKeyNameAlreadyUsed(err): | ||||
ctx.Error(422, "", "Key title has been used") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Key title has been used") | |||||
default: | default: | ||||
ctx.Error(500, "AddKey", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddKey", err) | |||||
} | } | ||||
} | } | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/DeployKey" | // "$ref": "#/responses/DeployKey" | ||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
content, err := models.CheckPublicKeyString(form.Key) | content, err := models.CheckPublicKeyString(form.Key) | ||||
if err != nil { | if err != nil { | ||||
HandleCheckKeyStringError(ctx, err) | HandleCheckKeyStringError(ctx, err) | ||||
key.Content = content | key.Content = content | ||||
apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name) | apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name) | ||||
ctx.JSON(201, convert.ToDeployKey(apiLink, key)) | |||||
ctx.JSON(http.StatusCreated, convert.ToDeployKey(apiLink, key)) | |||||
} | } | ||||
// DeleteDeploykey delete deploy key for a repository | // DeleteDeploykey delete deploy key for a repository | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
if err := models.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | if err := models.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | ||||
if models.IsErrKeyAccessDenied(err) { | if models.IsErrKeyAccessDenied(err) { | ||||
ctx.Error(403, "", "You do not have access to this key") | |||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key") | |||||
} else { | } else { | ||||
ctx.Error(500, "DeleteDeployKey", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteDeployKey", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"strconv" | "strconv" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/LabelList" | // "$ref": "#/responses/LabelList" | ||||
labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort")) | labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort")) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelsByRepoID", err) | |||||
return | return | ||||
} | } | ||||
for i := range labels { | for i := range labels { | ||||
apiLabels[i] = labels[i].APIFormat() | apiLabels[i] = labels[i].APIFormat() | ||||
} | } | ||||
ctx.JSON(200, &apiLabels) | |||||
ctx.JSON(http.StatusOK, &apiLabels) | |||||
} | } | ||||
// GetLabel get label by repository and label id | // GetLabel get label by repository and label id | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Label" | // "$ref": "#/responses/Label" | ||||
var ( | var ( | ||||
label *models.Label | label *models.Label | ||||
err error | err error | ||||
if models.IsErrLabelNotExist(err) { | if models.IsErrLabelNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetLabelByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelByRepoID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, label.APIFormat()) | |||||
ctx.JSON(http.StatusOK, label.APIFormat()) | |||||
} | } | ||||
// CreateLabel create a label for a repository | // CreateLabel create a label for a repository | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Label" | // "$ref": "#/responses/Label" | ||||
label := &models.Label{ | label := &models.Label{ | ||||
Name: form.Name, | Name: form.Name, | ||||
Color: form.Color, | Color: form.Color, | ||||
Description: form.Description, | Description: form.Description, | ||||
} | } | ||||
if err := models.NewLabel(label); err != nil { | if err := models.NewLabel(label); err != nil { | ||||
ctx.Error(500, "NewLabel", err) | |||||
ctx.Error(http.StatusInternalServerError, "NewLabel", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, label.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, label.APIFormat()) | |||||
} | } | ||||
// EditLabel modify a label for a repository | // EditLabel modify a label for a repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Label" | // "$ref": "#/responses/Label" | ||||
label, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | label, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrLabelNotExist(err) { | if models.IsErrLabelNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetLabelByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelByRepoID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.ServerError("UpdateLabel", err) | ctx.ServerError("UpdateLabel", err) | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, label.APIFormat()) | |||||
ctx.JSON(http.StatusOK, label.APIFormat()) | |||||
} | } | ||||
// DeleteLabel delete a label for a repository | // DeleteLabel delete a label for a repository | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
if err := models.DeleteLabel(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { | if err := models.DeleteLabel(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { | ||||
ctx.Error(500, "DeleteLabel", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteLabel", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"time" | "time" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/MilestoneList" | // "$ref": "#/responses/MilestoneList" | ||||
milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state"))) | milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state"))) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetMilestonesByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetMilestonesByRepoID", err) | |||||
return | return | ||||
} | } | ||||
for i := range milestones { | for i := range milestones { | ||||
apiMilestones[i] = milestones[i].APIFormat() | apiMilestones[i] = milestones[i].APIFormat() | ||||
} | } | ||||
ctx.JSON(200, &apiMilestones) | |||||
ctx.JSON(http.StatusOK, &apiMilestones) | |||||
} | } | ||||
// GetMilestone get a milestone for a repository | // GetMilestone get a milestone for a repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Milestone" | // "$ref": "#/responses/Milestone" | ||||
milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrMilestoneNotExist(err) { | if models.IsErrMilestoneNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetMilestoneByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetMilestoneByRepoID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, milestone.APIFormat()) | |||||
ctx.JSON(http.StatusOK, milestone.APIFormat()) | |||||
} | } | ||||
// CreateMilestone create a milestone for a repository | // CreateMilestone create a milestone for a repository | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Milestone" | // "$ref": "#/responses/Milestone" | ||||
if form.Deadline == nil { | if form.Deadline == nil { | ||||
defaultDeadline, _ := time.ParseInLocation("2006-01-02", "9999-12-31", time.Local) | defaultDeadline, _ := time.ParseInLocation("2006-01-02", "9999-12-31", time.Local) | ||||
form.Deadline = &defaultDeadline | form.Deadline = &defaultDeadline | ||||
} | } | ||||
if err := models.NewMilestone(milestone); err != nil { | if err := models.NewMilestone(milestone); err != nil { | ||||
ctx.Error(500, "NewMilestone", err) | |||||
ctx.Error(http.StatusInternalServerError, "NewMilestone", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, milestone.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, milestone.APIFormat()) | |||||
} | } | ||||
// EditMilestone modify a milestone for a repository | // EditMilestone modify a milestone for a repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Milestone" | // "$ref": "#/responses/Milestone" | ||||
milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrMilestoneNotExist(err) { | if models.IsErrMilestoneNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetMilestoneByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetMilestoneByRepoID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.ServerError("UpdateMilestone", err) | ctx.ServerError("UpdateMilestone", err) | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, milestone.APIFormat()) | |||||
ctx.JSON(http.StatusOK, milestone.APIFormat()) | |||||
} | } | ||||
// DeleteMilestone delete a milestone for a repository | // DeleteMilestone delete a milestone for a repository | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
if err := models.DeleteMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { | if err := models.DeleteMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { | ||||
ctx.Error(500, "DeleteMilestoneByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteMilestoneByRepoID", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/PullRequestList" | // "$ref": "#/responses/PullRequestList" | ||||
prs, maxResults, err := models.PullRequests(ctx.Repo.Repository.ID, &models.PullRequestsOptions{ | prs, maxResults, err := models.PullRequests(ctx.Repo.Repository.ID, &models.PullRequestsOptions{ | ||||
Page: ctx.QueryInt("page"), | Page: ctx.QueryInt("page"), | ||||
State: ctx.QueryTrim("state"), | State: ctx.QueryTrim("state"), | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "PullRequests", err) | |||||
ctx.Error(http.StatusInternalServerError, "PullRequests", err) | |||||
return | return | ||||
} | } | ||||
apiPrs := make([]*api.PullRequest, len(prs)) | apiPrs := make([]*api.PullRequest, len(prs)) | ||||
for i := range prs { | for i := range prs { | ||||
if err = prs[i].LoadIssue(); err != nil { | if err = prs[i].LoadIssue(); err != nil { | ||||
ctx.Error(500, "LoadIssue", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadIssue", err) | |||||
return | return | ||||
} | } | ||||
if err = prs[i].LoadAttributes(); err != nil { | if err = prs[i].LoadAttributes(); err != nil { | ||||
ctx.Error(500, "LoadAttributes", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) | |||||
return | return | ||||
} | } | ||||
if err = prs[i].GetBaseRepo(); err != nil { | if err = prs[i].GetBaseRepo(); err != nil { | ||||
ctx.Error(500, "GetBaseRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetBaseRepo", err) | |||||
return | return | ||||
} | } | ||||
if err = prs[i].GetHeadRepo(); err != nil { | if err = prs[i].GetHeadRepo(); err != nil { | ||||
ctx.Error(500, "GetHeadRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetHeadRepo", err) | |||||
return | return | ||||
} | } | ||||
apiPrs[i] = prs[i].APIFormat() | apiPrs[i] = prs[i].APIFormat() | ||||
} | } | ||||
ctx.SetLinkHeader(int(maxResults), models.ItemsPerPage) | ctx.SetLinkHeader(int(maxResults), models.ItemsPerPage) | ||||
ctx.JSON(200, &apiPrs) | |||||
ctx.JSON(http.StatusOK, &apiPrs) | |||||
} | } | ||||
// GetPullRequest returns a single PR based on index | // GetPullRequest returns a single PR based on index | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/PullRequest" | // "$ref": "#/responses/PullRequest" | ||||
pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrPullRequestNotExist(err) { | if models.IsErrPullRequestNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetPullRequestByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if err = pr.GetBaseRepo(); err != nil { | if err = pr.GetBaseRepo(); err != nil { | ||||
ctx.Error(500, "GetBaseRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetBaseRepo", err) | |||||
return | return | ||||
} | } | ||||
if err = pr.GetHeadRepo(); err != nil { | if err = pr.GetHeadRepo(); err != nil { | ||||
ctx.Error(500, "GetHeadRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetHeadRepo", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, pr.APIFormat()) | |||||
ctx.JSON(http.StatusOK, pr.APIFormat()) | |||||
} | } | ||||
// CreatePullRequest does what it says | // CreatePullRequest does what it says | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/PullRequest" | // "$ref": "#/responses/PullRequest" | ||||
// "409": | |||||
// "$ref": "#/responses/error" | |||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
var ( | var ( | ||||
repo = ctx.Repo.Repository | repo = ctx.Repo.Repository | ||||
labelIDs []int64 | labelIDs []int64 | ||||
existingPr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch) | existingPr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch) | ||||
if err != nil { | if err != nil { | ||||
if !models.IsErrPullRequestNotExist(err) { | if !models.IsErrPullRequestNotExist(err) { | ||||
ctx.Error(500, "GetUnmergedPullRequest", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUnmergedPullRequest", err) | |||||
return | return | ||||
} | } | ||||
} else { | } else { | ||||
HeadBranch: existingPr.HeadBranch, | HeadBranch: existingPr.HeadBranch, | ||||
BaseBranch: existingPr.BaseBranch, | BaseBranch: existingPr.BaseBranch, | ||||
} | } | ||||
ctx.Error(409, "GetUnmergedPullRequest", err) | |||||
ctx.Error(http.StatusConflict, "GetUnmergedPullRequest", err) | |||||
return | return | ||||
} | } | ||||
if len(form.Labels) > 0 { | if len(form.Labels) > 0 { | ||||
labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsInRepoByIDs", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDs", err) | |||||
return | return | ||||
} | } | ||||
if models.IsErrMilestoneNotExist(err) { | if models.IsErrMilestoneNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetMilestoneByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetMilestoneByRepoID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
assigneeIDs, err := models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) | assigneeIDs, err := models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) | |||||
} else { | } else { | ||||
ctx.Error(500, "AddAssigneeByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddAssigneeByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
for _, aID := range assigneeIDs { | for _, aID := range assigneeIDs { | ||||
assignee, err := models.GetUserByID(aID) | assignee, err := models.GetUserByID(aID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByID", err) | |||||
return | return | ||||
} | } | ||||
valid, err := models.CanBeAssigned(assignee, repo, true) | valid, err := models.CanBeAssigned(assignee, repo, true) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "canBeAssigned", err) | |||||
ctx.Error(http.StatusInternalServerError, "canBeAssigned", err) | |||||
return | return | ||||
} | } | ||||
if !valid { | if !valid { | ||||
ctx.Error(422, "canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: aID, RepoName: repo.Name}) | |||||
ctx.Error(http.StatusUnprocessableEntity, "canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: aID, RepoName: repo.Name}) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err := pull_service.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, assigneeIDs); err != nil { | if err := pull_service.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, assigneeIDs); err != nil { | ||||
if models.IsErrUserDoesNotHaveAccessToRepo(err) { | if models.IsErrUserDoesNotHaveAccessToRepo(err) { | ||||
ctx.Error(400, "UserDoesNotHaveAccessToRepo", err) | |||||
ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err) | |||||
return | return | ||||
} | } | ||||
ctx.Error(500, "NewPullRequest", err) | |||||
ctx.Error(http.StatusInternalServerError, "NewPullRequest", err) | |||||
return | return | ||||
} | } | ||||
notification.NotifyNewPullRequest(pr) | notification.NotifyNewPullRequest(pr) | ||||
log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID) | log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID) | ||||
ctx.JSON(201, pr.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, pr.APIFormat()) | |||||
} | } | ||||
// EditPullRequest does what it says | // EditPullRequest does what it says | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/PullRequest" | // "$ref": "#/responses/PullRequest" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
// "412": | |||||
// "$ref": "#/responses/error" | |||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrPullRequestNotExist(err) { | if models.IsErrPullRequestNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetPullRequestByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
issue.Repo = ctx.Repo.Repository | issue.Repo = ctx.Repo.Repository | ||||
if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypePullRequests) { | if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypePullRequests) { | ||||
ctx.Status(403) | |||||
ctx.Status(http.StatusForbidden) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | ||||
ctx.Error(500, "UpdateIssueDeadline", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err) | |||||
return | return | ||||
} | } | ||||
issue.DeadlineUnix = deadlineUnix | issue.DeadlineUnix = deadlineUnix | ||||
err = issue_service.UpdateAssignees(issue, form.Assignee, form.Assignees, ctx.User) | err = issue_service.UpdateAssignees(issue, form.Assignee, form.Assignees, ctx.User) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) | |||||
} else { | } else { | ||||
ctx.Error(500, "UpdateAssignees", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateAssignees", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
oldMilestoneID := issue.MilestoneID | oldMilestoneID := issue.MilestoneID | ||||
issue.MilestoneID = form.Milestone | issue.MilestoneID = form.Milestone | ||||
if err = issue_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil { | if err = issue_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil { | ||||
ctx.Error(500, "ChangeMilestoneAssign", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeMilestoneAssign", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if ctx.Repo.CanWrite(models.UnitTypePullRequests) && form.Labels != nil { | if ctx.Repo.CanWrite(models.UnitTypePullRequests) && form.Labels != nil { | ||||
labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsInRepoByIDsError", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDsError", err) | |||||
return | return | ||||
} | } | ||||
if err = issue.ReplaceLabels(labels, ctx.User); err != nil { | if err = issue.ReplaceLabels(labels, ctx.User); err != nil { | ||||
ctx.Error(500, "ReplaceLabelsError", err) | |||||
ctx.Error(http.StatusInternalServerError, "ReplaceLabelsError", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err = models.UpdateIssue(issue); err != nil { | if err = models.UpdateIssue(issue); err != nil { | ||||
ctx.Error(500, "UpdateIssue", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateIssue", err) | |||||
return | return | ||||
} | } | ||||
if form.State != nil { | if form.State != nil { | ||||
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies") | ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies") | ||||
return | return | ||||
} | } | ||||
ctx.Error(500, "ChangeStatus", err) | |||||
ctx.Error(http.StatusInternalServerError, "ChangeStatus", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if models.IsErrPullRequestNotExist(err) { | if models.IsErrPullRequestNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetPullRequestByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
// TODO this should be 200, not 201 | // TODO this should be 200, not 201 | ||||
ctx.JSON(201, pr.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, pr.APIFormat()) | |||||
} | } | ||||
// IsPullRequestMerged checks if a PR exists given an index | // IsPullRequestMerged checks if a PR exists given an index | ||||
// description: pull request has been merged | // description: pull request has been merged | ||||
// "404": | // "404": | ||||
// description: pull request has not been merged | // description: pull request has not been merged | ||||
pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrPullRequestNotExist(err) { | if models.IsErrPullRequestNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetPullRequestByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if pr.HasMerged { | if pr.HasMerged { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "405": | // "405": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "409": | |||||
// "$ref": "#/responses/error" | |||||
pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrPullRequestNotExist(err) { | if models.IsErrPullRequestNotExist(err) { | ||||
ctx.NotFound("GetPullRequestByIndex", err) | ctx.NotFound("GetPullRequestByIndex", err) | ||||
} else { | } else { | ||||
ctx.Error(500, "GetPullRequestByIndex", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if ctx.IsSigned { | if ctx.IsSigned { | ||||
// Update issue-user. | // Update issue-user. | ||||
if err = pr.Issue.ReadBy(ctx.User.ID); err != nil { | if err = pr.Issue.ReadBy(ctx.User.ID); err != nil { | ||||
ctx.Error(500, "ReadBy", err) | |||||
ctx.Error(http.StatusInternalServerError, "ReadBy", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if !pr.CanAutoMerge() || pr.HasMerged || pr.IsWorkInProgress() { | if !pr.CanAutoMerge() || pr.HasMerged || pr.IsWorkInProgress() { | ||||
ctx.Status(405) | |||||
ctx.Status(http.StatusMethodNotAllowed) | |||||
return | return | ||||
} | } | ||||
isPass, err := pull_service.IsPullCommitStatusPass(pr) | isPass, err := pull_service.IsPullCommitStatusPass(pr) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsPullCommitStatusPass", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsPullCommitStatusPass", err) | |||||
return | return | ||||
} | } | ||||
if !isPass && !ctx.IsUserRepoAdmin() { | if !isPass && !ctx.IsUserRepoAdmin() { | ||||
ctx.Status(405) | |||||
ctx.Status(http.StatusMethodNotAllowed) | |||||
return | return | ||||
} | } | ||||
if err := pull_service.Merge(pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil { | if err := pull_service.Merge(pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil { | ||||
if models.IsErrInvalidMergeStyle(err) { | if models.IsErrInvalidMergeStyle(err) { | ||||
ctx.Status(405) | |||||
ctx.Status(http.StatusMethodNotAllowed) | |||||
return | return | ||||
} else if models.IsErrMergeConflicts(err) { | } else if models.IsErrMergeConflicts(err) { | ||||
conflictError := err.(models.ErrMergeConflicts) | conflictError := err.(models.ErrMergeConflicts) | ||||
conflictError := err.(models.ErrMergeUnrelatedHistories) | conflictError := err.(models.ErrMergeUnrelatedHistories) | ||||
ctx.JSON(http.StatusConflict, conflictError) | ctx.JSON(http.StatusConflict, conflictError) | ||||
} else if models.IsErrMergePushOutOfDate(err) { | } else if models.IsErrMergePushOutOfDate(err) { | ||||
ctx.Status(http.StatusConflict) | |||||
ctx.Error(http.StatusConflict, "Merge", "merge push out of date") | |||||
return | return | ||||
} | } | ||||
ctx.Error(500, "Merge", err) | |||||
ctx.Error(http.StatusInternalServerError, "Merge", err) | |||||
return | return | ||||
} | } | ||||
log.Trace("Pull request merged: %d", pr.ID) | log.Trace("Pull request merged: %d", pr.ID) | ||||
ctx.Status(200) | |||||
ctx.Status(http.StatusOK) | |||||
} | } | ||||
func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) (*models.User, *models.Repository, *git.Repository, *git.CompareInfo, string, string) { | func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) (*models.User, *models.Repository, *git.Repository, *git.CompareInfo, string, string) { | ||||
} else { | } else { | ||||
headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name)) | headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name)) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "OpenRepository", err) | |||||
ctx.Error(http.StatusInternalServerError, "OpenRepository", err) | |||||
return nil, nil, nil, nil, "", "" | return nil, nil, nil, nil, "", "" | ||||
} | } | ||||
} | } | ||||
compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) | compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) | ||||
if err != nil { | if err != nil { | ||||
headGitRepo.Close() | headGitRepo.Close() | ||||
ctx.Error(500, "GetCompareInfo", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetCompareInfo", err) | |||||
return nil, nil, nil, nil, "", "" | return nil, nil, nil, nil, "", "" | ||||
} | } | ||||
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Release" | // "$ref": "#/responses/Release" | ||||
id := ctx.ParamsInt64(":id") | id := ctx.ParamsInt64(":id") | ||||
release, err := models.GetReleaseByID(id) | release, err := models.GetReleaseByID(id) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetReleaseByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) | |||||
return | return | ||||
} | } | ||||
if release.RepoID != ctx.Repo.Repository.ID { | if release.RepoID != ctx.Repo.Repository.ID { | ||||
return | return | ||||
} | } | ||||
if err := release.LoadAttributes(); err != nil { | if err := release.LoadAttributes(); err != nil { | ||||
ctx.Error(500, "LoadAttributes", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, release.APIFormat()) | |||||
ctx.JSON(http.StatusOK, release.APIFormat()) | |||||
} | } | ||||
func getPagesInfo(ctx *context.APIContext) (int, int) { | func getPagesInfo(ctx *context.APIContext) (int, int) { | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/ReleaseList" | // "$ref": "#/responses/ReleaseList" | ||||
page, limit := getPagesInfo(ctx) | page, limit := getPagesInfo(ctx) | ||||
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ | releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ | ||||
IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite, | IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite, | ||||
IncludeTags: false, | IncludeTags: false, | ||||
}, page, limit) | }, page, limit) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetReleasesByRepoID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) | |||||
return | return | ||||
} | } | ||||
rels := make([]*api.Release, len(releases)) | rels := make([]*api.Release, len(releases)) | ||||
for i, release := range releases { | for i, release := range releases { | ||||
if err := release.LoadAttributes(); err != nil { | if err := release.LoadAttributes(); err != nil { | ||||
ctx.Error(500, "LoadAttributes", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) | |||||
return | return | ||||
} | } | ||||
rels[i] = release.APIFormat() | rels[i] = release.APIFormat() | ||||
} | } | ||||
ctx.JSON(200, rels) | |||||
ctx.JSON(http.StatusOK, rels) | |||||
} | } | ||||
// CreateRelease create a release | // CreateRelease create a release | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Release" | // "$ref": "#/responses/Release" | ||||
// "409": | |||||
// "$ref": "#/responses/error" | |||||
rel, err := models.GetRelease(ctx.Repo.Repository.ID, form.TagName) | rel, err := models.GetRelease(ctx.Repo.Repository.ID, form.TagName) | ||||
if err != nil { | if err != nil { | ||||
if !models.IsErrReleaseNotExist(err) { | if !models.IsErrReleaseNotExist(err) { | ||||
} | } | ||||
if err := releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, nil); err != nil { | if err := releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, nil); err != nil { | ||||
if models.IsErrReleaseAlreadyExist(err) { | if models.IsErrReleaseAlreadyExist(err) { | ||||
ctx.Status(409) | |||||
ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "CreateRelease", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateRelease", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
} else { | } else { | ||||
if !rel.IsTag { | if !rel.IsTag { | ||||
ctx.Status(409) | |||||
ctx.Error(http.StatusConflict, "GetRelease", "Release is has no Tag") | |||||
return | return | ||||
} | } | ||||
return | return | ||||
} | } | ||||
} | } | ||||
ctx.JSON(201, rel.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, rel.APIFormat()) | |||||
} | } | ||||
// EditRelease edit a release | // EditRelease edit a release | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Release" | // "$ref": "#/responses/Release" | ||||
id := ctx.ParamsInt64(":id") | id := ctx.ParamsInt64(":id") | ||||
rel, err := models.GetReleaseByID(id) | rel, err := models.GetReleaseByID(id) | ||||
if err != nil && !models.IsErrReleaseNotExist(err) { | if err != nil && !models.IsErrReleaseNotExist(err) { | ||||
ctx.Error(500, "GetReleaseByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) | |||||
return | return | ||||
} | } | ||||
if err != nil && models.IsErrReleaseNotExist(err) || | if err != nil && models.IsErrReleaseNotExist(err) || | ||||
rel.IsPrerelease = *form.IsPrerelease | rel.IsPrerelease = *form.IsPrerelease | ||||
} | } | ||||
if err := releaseservice.UpdateRelease(ctx.User, ctx.Repo.GitRepo, rel, nil); err != nil { | if err := releaseservice.UpdateRelease(ctx.User, ctx.Repo.GitRepo, rel, nil); err != nil { | ||||
ctx.Error(500, "UpdateRelease", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateRelease", err) | |||||
return | return | ||||
} | } | ||||
rel, err = models.GetReleaseByID(id) | rel, err = models.GetReleaseByID(id) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetReleaseByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) | |||||
return | return | ||||
} | } | ||||
if err := rel.LoadAttributes(); err != nil { | if err := rel.LoadAttributes(); err != nil { | ||||
ctx.Error(500, "LoadAttributes", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, rel.APIFormat()) | |||||
ctx.JSON(http.StatusOK, rel.APIFormat()) | |||||
} | } | ||||
// DeleteRelease delete a release from a repository | // DeleteRelease delete a release from a repository | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
id := ctx.ParamsInt64(":id") | id := ctx.ParamsInt64(":id") | ||||
rel, err := models.GetReleaseByID(id) | rel, err := models.GetReleaseByID(id) | ||||
if err != nil && !models.IsErrReleaseNotExist(err) { | if err != nil && !models.IsErrReleaseNotExist(err) { | ||||
ctx.Error(500, "GetReleaseByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) | |||||
return | return | ||||
} | } | ||||
if err != nil && models.IsErrReleaseNotExist(err) || | if err != nil && models.IsErrReleaseNotExist(err) || | ||||
return | return | ||||
} | } | ||||
if err := releaseservice.DeleteReleaseByID(id, ctx.User, false); err != nil { | if err := releaseservice.DeleteReleaseByID(id, ctx.User, false); err != nil { | ||||
ctx.Error(500, "DeleteReleaseByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"strings" | "strings" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Attachment" | // "$ref": "#/responses/Attachment" | ||||
releaseID := ctx.ParamsInt64(":id") | releaseID := ctx.ParamsInt64(":id") | ||||
attachID := ctx.ParamsInt64(":asset") | attachID := ctx.ParamsInt64(":asset") | ||||
attach, err := models.GetAttachmentByID(attachID) | attach, err := models.GetAttachmentByID(attachID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetAttachmentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err) | |||||
return | return | ||||
} | } | ||||
if attach.ReleaseID != releaseID { | if attach.ReleaseID != releaseID { | ||||
return | return | ||||
} | } | ||||
// FIXME Should prove the existence of the given repo, but results in unnecessary database requests | // FIXME Should prove the existence of the given repo, but results in unnecessary database requests | ||||
ctx.JSON(200, attach.APIFormat()) | |||||
ctx.JSON(http.StatusOK, attach.APIFormat()) | |||||
} | } | ||||
// ListReleaseAttachments lists all attachments of the release | // ListReleaseAttachments lists all attachments of the release | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/AttachmentList" | // "$ref": "#/responses/AttachmentList" | ||||
releaseID := ctx.ParamsInt64(":id") | releaseID := ctx.ParamsInt64(":id") | ||||
release, err := models.GetReleaseByID(releaseID) | release, err := models.GetReleaseByID(releaseID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetReleaseByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) | |||||
return | return | ||||
} | } | ||||
if release.RepoID != ctx.Repo.Repository.ID { | if release.RepoID != ctx.Repo.Repository.ID { | ||||
return | return | ||||
} | } | ||||
if err := release.LoadAttributes(); err != nil { | if err := release.LoadAttributes(); err != nil { | ||||
ctx.Error(500, "LoadAttributes", err) | |||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, release.APIFormat().Attachments) | |||||
ctx.JSON(http.StatusOK, release.APIFormat().Attachments) | |||||
} | } | ||||
// CreateReleaseAttachment creates an attachment and saves the given file | // CreateReleaseAttachment creates an attachment and saves the given file | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Attachment" | // "$ref": "#/responses/Attachment" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
// Check if attachments are enabled | // Check if attachments are enabled | ||||
if !setting.AttachmentEnabled { | if !setting.AttachmentEnabled { | ||||
releaseID := ctx.ParamsInt64(":id") | releaseID := ctx.ParamsInt64(":id") | ||||
release, err := models.GetReleaseByID(releaseID) | release, err := models.GetReleaseByID(releaseID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetReleaseByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) | |||||
return | return | ||||
} | } | ||||
// Get uploaded file from request | // Get uploaded file from request | ||||
file, header, err := ctx.GetFile("attachment") | file, header, err := ctx.GetFile("attachment") | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetFile", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetFile", err) | |||||
return | return | ||||
} | } | ||||
defer file.Close() | defer file.Close() | ||||
// Check if the filetype is allowed by the settings | // Check if the filetype is allowed by the settings | ||||
err = upload.VerifyAllowedContentType(buf, strings.Split(setting.AttachmentAllowedTypes, ",")) | err = upload.VerifyAllowedContentType(buf, strings.Split(setting.AttachmentAllowedTypes, ",")) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(400, "DetectContentType", err) | |||||
ctx.Error(http.StatusBadRequest, "DetectContentType", err) | |||||
return | return | ||||
} | } | ||||
ReleaseID: release.ID, | ReleaseID: release.ID, | ||||
}, buf, file) | }, buf, file) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "NewAttachment", err) | |||||
ctx.Error(http.StatusInternalServerError, "NewAttachment", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, attach.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, attach.APIFormat()) | |||||
} | } | ||||
// EditReleaseAttachment updates the given attachment | // EditReleaseAttachment updates the given attachment | ||||
attachID := ctx.ParamsInt64(":asset") | attachID := ctx.ParamsInt64(":asset") | ||||
attach, err := models.GetAttachmentByID(attachID) | attach, err := models.GetAttachmentByID(attachID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetAttachmentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err) | |||||
return | return | ||||
} | } | ||||
if attach.ReleaseID != releaseID { | if attach.ReleaseID != releaseID { | ||||
} | } | ||||
if err := models.UpdateAttachment(attach); err != nil { | if err := models.UpdateAttachment(attach); err != nil { | ||||
ctx.Error(500, "UpdateAttachment", attach) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateAttachment", attach) | |||||
} | } | ||||
ctx.JSON(201, attach.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, attach.APIFormat()) | |||||
} | } | ||||
// DeleteReleaseAttachment delete a given attachment | // DeleteReleaseAttachment delete a given attachment | ||||
attachID := ctx.ParamsInt64(":asset") | attachID := ctx.ParamsInt64(":asset") | ||||
attach, err := models.GetAttachmentByID(attachID) | attach, err := models.GetAttachmentByID(attachID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetAttachmentByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err) | |||||
return | return | ||||
} | } | ||||
if attach.ReleaseID != releaseID { | if attach.ReleaseID != releaseID { | ||||
// FIXME Should prove the existence of the given repo, but results in unnecessary database requests | // FIXME Should prove the existence of the given repo, but results in unnecessary database requests | ||||
if err := models.DeleteAttachment(attach, true); err != nil { | if err := models.DeleteAttachment(attach, true); err != nil { | ||||
ctx.Error(500, "DeleteAttachment", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteAttachment", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
// "$ref": "#/responses/SearchResults" | // "$ref": "#/responses/SearchResults" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
opts := &models.SearchRepoOptions{ | opts := &models.SearchRepoOptions{ | ||||
Keyword: strings.Trim(ctx.Query("q"), " "), | Keyword: strings.Trim(ctx.Query("q"), " "), | ||||
OwnerID: ctx.QueryInt64("uid"), | OwnerID: ctx.QueryInt64("uid"), | ||||
var err error | var err error | ||||
repos, count, err := models.SearchRepository(opts) | repos, count, err := models.SearchRepository(opts) | ||||
if err != nil { | if err != nil { | ||||
ctx.JSON(500, api.SearchError{ | |||||
ctx.JSON(http.StatusInternalServerError, api.SearchError{ | |||||
OK: false, | OK: false, | ||||
Error: err.Error(), | Error: err.Error(), | ||||
}) | }) | ||||
results := make([]*api.Repository, len(repos)) | results := make([]*api.Repository, len(repos)) | ||||
for i, repo := range repos { | for i, repo := range repos { | ||||
if err = repo.GetOwner(); err != nil { | if err = repo.GetOwner(); err != nil { | ||||
ctx.JSON(500, api.SearchError{ | |||||
ctx.JSON(http.StatusInternalServerError, api.SearchError{ | |||||
OK: false, | OK: false, | ||||
Error: err.Error(), | Error: err.Error(), | ||||
}) | }) | ||||
} | } | ||||
accessMode, err := models.AccessLevel(ctx.User, repo) | accessMode, err := models.AccessLevel(ctx.User, repo) | ||||
if err != nil { | if err != nil { | ||||
ctx.JSON(500, api.SearchError{ | |||||
ctx.JSON(http.StatusInternalServerError, api.SearchError{ | |||||
OK: false, | OK: false, | ||||
Error: err.Error(), | Error: err.Error(), | ||||
}) | }) | ||||
ctx.SetLinkHeader(int(count), setting.API.MaxResponseItems) | ctx.SetLinkHeader(int(count), setting.API.MaxResponseItems) | ||||
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", count)) | ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", count)) | ||||
ctx.JSON(200, api.SearchResults{ | |||||
ctx.JSON(http.StatusOK, api.SearchResults{ | |||||
OK: true, | OK: true, | ||||
Data: results, | Data: results, | ||||
}) | }) | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrRepoAlreadyExist(err) { | if models.IsErrRepoAlreadyExist(err) { | ||||
ctx.Error(409, "", "The repository with the same name already exists.") | |||||
ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.") | |||||
} else if models.IsErrNameReserved(err) || | } else if models.IsErrNameReserved(err) || | ||||
models.IsErrNamePatternNotAllowed(err) { | models.IsErrNamePatternNotAllowed(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "CreateRepository", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateRepository", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(201, repo.APIFormat(models.AccessModeOwner)) | |||||
ctx.JSON(http.StatusCreated, repo.APIFormat(models.AccessModeOwner)) | |||||
} | } | ||||
// Create one repository of mine | // Create one repository of mine | ||||
// description: The repository with the same name already exists. | // description: The repository with the same name already exists. | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
if ctx.User.IsOrganization() { | if ctx.User.IsOrganization() { | ||||
// Shouldn't reach this condition, but just in case. | // Shouldn't reach this condition, but just in case. | ||||
ctx.Error(422, "", "not allowed creating repository for organization") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization") | |||||
return | return | ||||
} | } | ||||
CreateUserRepo(ctx, ctx.User, opt) | CreateUserRepo(ctx, ctx.User, opt) | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
org, err := models.GetOrgByName(ctx.Params(":org")) | org, err := models.GetOrgByName(ctx.Params(":org")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrOrgNotExist(err) { | if models.IsErrOrgNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetOrgByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.ServerError("CanCreateOrgRepo", err) | ctx.ServerError("CanCreateOrgRepo", err) | ||||
return | return | ||||
} else if !canCreate { | } else if !canCreate { | ||||
ctx.Error(403, "", "Given user is not allowed to create repository in organization.") | |||||
ctx.Error(http.StatusForbidden, "", "Given user is not allowed to create repository in organization.") | |||||
return | return | ||||
} | } | ||||
} | } | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Repository" | // "$ref": "#/responses/Repository" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
ctxUser := ctx.User | ctxUser := ctx.User | ||||
// Not equal means context user is an organization, | // Not equal means context user is an organization, | ||||
// or is another user/organization if current user is admin. | // or is another user/organization if current user is admin. | ||||
org, err := models.GetUserByID(form.UID) | org, err := models.GetUserByID(form.UID) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
} | } | ||||
if ctx.HasError() { | if ctx.HasError() { | ||||
ctx.Error(422, "", ctx.GetErrMsg()) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", ctx.GetErrMsg()) | |||||
return | return | ||||
} | } | ||||
if !ctx.User.IsAdmin { | if !ctx.User.IsAdmin { | ||||
if !ctxUser.IsOrganization() && ctx.User.ID != ctxUser.ID { | if !ctxUser.IsOrganization() && ctx.User.ID != ctxUser.ID { | ||||
ctx.Error(403, "", "Given user is not an organization.") | |||||
ctx.Error(http.StatusForbidden, "", "Given user is not an organization.") | |||||
return | return | ||||
} | } | ||||
// Check ownership of organization. | // Check ownership of organization. | ||||
isOwner, err := ctxUser.IsOwnedBy(ctx.User.ID) | isOwner, err := ctxUser.IsOwnedBy(ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "IsOwnedBy", err) | |||||
ctx.Error(http.StatusInternalServerError, "IsOwnedBy", err) | |||||
return | return | ||||
} else if !isOwner { | } else if !isOwner { | ||||
ctx.Error(403, "", "Given user is not owner of organization.") | |||||
ctx.Error(http.StatusForbidden, "", "Given user is not owner of organization.") | |||||
return | return | ||||
} | } | ||||
} | } | ||||
addrErr := err.(models.ErrInvalidCloneAddr) | addrErr := err.(models.ErrInvalidCloneAddr) | ||||
switch { | switch { | ||||
case addrErr.IsURLError: | case addrErr.IsURLError: | ||||
ctx.Error(422, "", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", err) | |||||
case addrErr.IsPermissionDenied: | case addrErr.IsPermissionDenied: | ||||
ctx.Error(422, "", "You are not allowed to import local repositories.") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "You are not allowed to import local repositories.") | |||||
case addrErr.IsInvalidPath: | case addrErr.IsInvalidPath: | ||||
ctx.Error(422, "", "Invalid local path, it does not exist or not a directory.") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid local path, it does not exist or not a directory.") | |||||
default: | default: | ||||
ctx.Error(500, "ParseRemoteAddr", "Unknown error type (ErrInvalidCloneAddr): "+err.Error()) | |||||
ctx.Error(http.StatusInternalServerError, "ParseRemoteAddr", "Unknown error type (ErrInvalidCloneAddr): "+err.Error()) | |||||
} | } | ||||
} else { | } else { | ||||
ctx.Error(500, "ParseRemoteAddr", err) | |||||
ctx.Error(http.StatusInternalServerError, "ParseRemoteAddr", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
} | } | ||||
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) | log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) | ||||
ctx.JSON(201, repo.APIFormat(models.AccessModeAdmin)) | |||||
ctx.JSON(http.StatusCreated, repo.APIFormat(models.AccessModeAdmin)) | |||||
} | } | ||||
func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteAddr string, err error) { | func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteAddr string, err error) { | ||||
switch { | switch { | ||||
case models.IsErrRepoAlreadyExist(err): | case models.IsErrRepoAlreadyExist(err): | ||||
ctx.Error(409, "", "The repository with the same name already exists.") | |||||
ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.") | |||||
case migrations.IsRateLimitError(err): | case migrations.IsRateLimitError(err): | ||||
ctx.Error(422, "", "Remote visit addressed rate limitation.") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Remote visit addressed rate limitation.") | |||||
case migrations.IsTwoFactorAuthError(err): | case migrations.IsTwoFactorAuthError(err): | ||||
ctx.Error(422, "", "Remote visit required two factors authentication.") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Remote visit required two factors authentication.") | |||||
case models.IsErrReachLimitOfRepo(err): | case models.IsErrReachLimitOfRepo(err): | ||||
ctx.Error(422, "", fmt.Sprintf("You have already reached your limit of %d repositories.", repoOwner.MaxCreationLimit())) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("You have already reached your limit of %d repositories.", repoOwner.MaxCreationLimit())) | |||||
case models.IsErrNameReserved(err): | case models.IsErrNameReserved(err): | ||||
ctx.Error(422, "", fmt.Sprintf("The username '%s' is reserved.", err.(models.ErrNameReserved).Name)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The username '%s' is reserved.", err.(models.ErrNameReserved).Name)) | |||||
case models.IsErrNamePatternNotAllowed(err): | case models.IsErrNamePatternNotAllowed(err): | ||||
ctx.Error(422, "", fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(models.ErrNamePatternNotAllowed).Pattern)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(models.ErrNamePatternNotAllowed).Pattern)) | |||||
default: | default: | ||||
err = util.URLSanitizedError(err, remoteAddr) | err = util.URLSanitizedError(err, remoteAddr) | ||||
if strings.Contains(err.Error(), "Authentication failed") || | if strings.Contains(err.Error(), "Authentication failed") || | ||||
strings.Contains(err.Error(), "Bad credentials") || | strings.Contains(err.Error(), "Bad credentials") || | ||||
strings.Contains(err.Error(), "could not read Username") { | strings.Contains(err.Error(), "could not read Username") { | ||||
ctx.Error(422, "", fmt.Sprintf("Authentication failed: %v.", err)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Authentication failed: %v.", err)) | |||||
} else if strings.Contains(err.Error(), "fatal:") { | } else if strings.Contains(err.Error(), "fatal:") { | ||||
ctx.Error(422, "", fmt.Sprintf("Migration failed: %v.", err)) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Migration failed: %v.", err)) | |||||
} else { | } else { | ||||
ctx.Error(500, "MigrateRepository", err) | |||||
ctx.Error(http.StatusInternalServerError, "MigrateRepository", err) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Repository" | // "$ref": "#/responses/Repository" | ||||
ctx.JSON(200, ctx.Repo.Repository.APIFormat(ctx.Repo.AccessMode)) | |||||
ctx.JSON(http.StatusOK, ctx.Repo.Repository.APIFormat(ctx.Repo.AccessMode)) | |||||
} | } | ||||
// GetByID returns a single Repository | // GetByID returns a single Repository | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Repository" | // "$ref": "#/responses/Repository" | ||||
repo, err := models.GetRepositoryByID(ctx.ParamsInt64(":id")) | repo, err := models.GetRepositoryByID(ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrRepoNotExist(err) { | if models.IsErrRepoNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetRepositoryByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetRepositoryByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
perm, err := models.GetUserRepoPermission(repo, ctx.User) | perm, err := models.GetUserRepoPermission(repo, ctx.User) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "AccessLevel", err) | |||||
ctx.Error(http.StatusInternalServerError, "AccessLevel", err) | |||||
return | return | ||||
} else if !perm.HasAccess() { | } else if !perm.HasAccess() { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, repo.APIFormat(perm.AccessMode)) | |||||
ctx.JSON(http.StatusOK, repo.APIFormat(perm.AccessMode)) | |||||
} | } | ||||
// Edit edit repository properties | // Edit edit repository properties | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
if err := updateBasicProperties(ctx, opts); err != nil { | if err := updateBasicProperties(ctx, opts); err != nil { | ||||
return | return | ||||
} | } | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
owner := ctx.Repo.Owner | owner := ctx.Repo.Owner | ||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
canDelete, err := repo.CanUserDelete(ctx.User) | canDelete, err := repo.CanUserDelete(ctx.User) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "CanUserDelete", err) | |||||
ctx.Error(http.StatusInternalServerError, "CanUserDelete", err) | |||||
return | return | ||||
} else if !canDelete { | } else if !canDelete { | ||||
ctx.Error(403, "", "Given user is not owner of organization.") | |||||
ctx.Error(http.StatusForbidden, "", "Given user is not owner of organization.") | |||||
return | return | ||||
} | } | ||||
if err := repo_service.DeleteRepository(ctx.User, repo); err != nil { | if err := repo_service.DeleteRepository(ctx.User, repo); err != nil { | ||||
ctx.Error(500, "DeleteRepository", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteRepository", err) | |||||
return | return | ||||
} | } | ||||
log.Trace("Repository deleted: %s/%s", owner.Name, repo.Name) | log.Trace("Repository deleted: %s/%s", owner.Name, repo.Name) | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// MirrorSync adds a mirrored repository to the sync queue | // MirrorSync adds a mirrored repository to the sync queue | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
if !ctx.Repo.CanWrite(models.UnitTypeCode) { | if !ctx.Repo.CanWrite(models.UnitTypeCode) { | ||||
ctx.Error(403, "MirrorSync", "Must have write access") | |||||
ctx.Error(http.StatusForbidden, "MirrorSync", "Must have write access") | |||||
} | } | ||||
mirror_service.StartToMirror(repo.ID) | mirror_service.StartToMirror(repo.ID) | ||||
ctx.Status(200) | |||||
ctx.Status(http.StatusOK) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
stargazers, err := ctx.Repo.Repository.GetStargazers(-1) | stargazers, err := ctx.Repo.Repository.GetStargazers(-1) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetStargazers", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetStargazers", err) | |||||
return | return | ||||
} | } | ||||
users := make([]*api.User, len(stargazers)) | users := make([]*api.User, len(stargazers)) | ||||
for i, stargazer := range stargazers { | for i, stargazer := range stargazers { | ||||
users[i] = convert.ToUser(stargazer, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | users[i] = convert.ToUser(stargazer, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | ||||
} | } | ||||
ctx.JSON(200, users) | |||||
ctx.JSON(http.StatusOK, users) | |||||
} | } |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
// responses: | // responses: | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Status" | // "$ref": "#/responses/Status" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
sha := ctx.Params("sha") | sha := ctx.Params("sha") | ||||
if len(sha) == 0 { | if len(sha) == 0 { | ||||
ctx.Error(400, "sha not given", nil) | |||||
ctx.Error(http.StatusBadRequest, "sha not given", nil) | |||||
return | return | ||||
} | } | ||||
status := &models.CommitStatus{ | status := &models.CommitStatus{ | ||||
Context: form.Context, | Context: form.Context, | ||||
} | } | ||||
if err := repofiles.CreateCommitStatus(ctx.Repo.Repository, ctx.User, sha, status); err != nil { | if err := repofiles.CreateCommitStatus(ctx.Repo.Repository, ctx.User, sha, status); err != nil { | ||||
ctx.Error(500, "CreateCommitStatus", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateCommitStatus", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, status.APIFormat()) | |||||
ctx.JSON(http.StatusCreated, status.APIFormat()) | |||||
} | } | ||||
// GetCommitStatuses returns all statuses for any given commit hash | // GetCommitStatuses returns all statuses for any given commit hash | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/StatusList" | // "$ref": "#/responses/StatusList" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
getCommitStatuses(ctx, ctx.Params("sha")) | getCommitStatuses(ctx, ctx.Params("sha")) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/StatusList" | // "$ref": "#/responses/StatusList" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
filter := ctx.Params("ref") | filter := ctx.Params("ref") | ||||
if len(filter) == 0 { | if len(filter) == 0 { | ||||
ctx.Error(400, "ref not given", nil) | |||||
ctx.Error(http.StatusBadRequest, "ref not given", nil) | |||||
return | return | ||||
} | } | ||||
for _, reftype := range []string{"heads", "tags"} { //Search branches and tags | for _, reftype := range []string{"heads", "tags"} { //Search branches and tags | ||||
refSHA, lastMethodName, err := searchRefCommitByType(ctx, reftype, filter) | refSHA, lastMethodName, err := searchRefCommitByType(ctx, reftype, filter) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, lastMethodName, err) | |||||
ctx.Error(http.StatusInternalServerError, lastMethodName, err) | |||||
return | return | ||||
} | } | ||||
if refSHA != "" { | if refSHA != "" { | ||||
func getCommitStatuses(ctx *context.APIContext, sha string) { | func getCommitStatuses(ctx *context.APIContext, sha string) { | ||||
if len(sha) == 0 { | if len(sha) == 0 { | ||||
ctx.Error(400, "ref/sha not given", nil) | |||||
ctx.Error(http.StatusBadRequest, "ref/sha not given", nil) | |||||
return | return | ||||
} | } | ||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
State: ctx.QueryTrim("state"), | State: ctx.QueryTrim("state"), | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetCommitStatuses", fmt.Errorf("GetCommitStatuses[%s, %s, %d]: %v", repo.FullName(), sha, ctx.QueryInt("page"), err)) | |||||
ctx.Error(http.StatusInternalServerError, "GetCommitStatuses", fmt.Errorf("GetCommitStatuses[%s, %s, %d]: %v", repo.FullName(), sha, ctx.QueryInt("page"), err)) | |||||
return | return | ||||
} | } | ||||
apiStatuses = append(apiStatuses, status.APIFormat()) | apiStatuses = append(apiStatuses, status.APIFormat()) | ||||
} | } | ||||
ctx.JSON(200, apiStatuses) | |||||
ctx.JSON(http.StatusOK, apiStatuses) | |||||
} | } | ||||
type combinedCommitStatus struct { | type combinedCommitStatus struct { | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/Status" | // "$ref": "#/responses/Status" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
sha := ctx.Params("ref") | sha := ctx.Params("ref") | ||||
if len(sha) == 0 { | if len(sha) == 0 { | ||||
ctx.Error(400, "ref/sha not given", nil) | |||||
ctx.Error(http.StatusBadRequest, "ref/sha not given", nil) | |||||
return | return | ||||
} | } | ||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
statuses, err := models.GetLatestCommitStatus(repo, sha, page) | statuses, err := models.GetLatestCommitStatus(repo, sha, page) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLatestCommitStatus", fmt.Errorf("GetLatestCommitStatus[%s, %s, %d]: %v", repo.FullName(), sha, page, err)) | |||||
ctx.Error(http.StatusInternalServerError, "GetLatestCommitStatus", fmt.Errorf("GetLatestCommitStatus[%s, %s, %d]: %v", repo.FullName(), sha, page, err)) | |||||
return | return | ||||
} | } | ||||
if len(statuses) == 0 { | if len(statuses) == 0 { | ||||
ctx.Status(200) | |||||
ctx.Status(http.StatusOK) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
} | } | ||||
ctx.JSON(200, retStatus) | |||||
ctx.JSON(http.StatusOK, retStatus) | |||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
subscribers, err := ctx.Repo.Repository.GetWatchers(0) | subscribers, err := ctx.Repo.Repository.GetWatchers(0) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetWatchers", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetWatchers", err) | |||||
return | return | ||||
} | } | ||||
users := make([]*api.User, len(subscribers)) | users := make([]*api.User, len(subscribers)) | ||||
for i, subscriber := range subscribers { | for i, subscriber := range subscribers { | ||||
users[i] = convert.ToUser(subscriber, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | users[i] = convert.ToUser(subscriber, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | ||||
} | } | ||||
ctx.JSON(200, users) | |||||
ctx.JSON(http.StatusOK, users) | |||||
} | } |
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TagList" | // "$ref": "#/responses/TagList" | ||||
tags, err := ctx.Repo.GitRepo.GetTagInfos() | tags, err := ctx.Repo.GitRepo.GetTagInfos() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetTags", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetTags", err) | |||||
return | return | ||||
} | } | ||||
apiTags[i] = convert.ToTag(ctx.Repo.Repository, tags[i]) | apiTags[i] = convert.ToTag(ctx.Repo.Repository, tags[i]) | ||||
} | } | ||||
ctx.JSON(200, &apiTags) | |||||
ctx.JSON(http.StatusOK, &apiTags) | |||||
} | } | ||||
// GetTag get the tag of a repository. | // GetTag get the tag of a repository. | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/AnnotatedTag" | // "$ref": "#/responses/AnnotatedTag" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
sha := ctx.Params("sha") | sha := ctx.Params("sha") | ||||
if len(sha) == 0 { | if len(sha) == 0 { |
}) | }) | ||||
if err != nil { | if err != nil { | ||||
log.Error("ListTopics failed: %v", err) | log.Error("ListTopics failed: %v", err) | ||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"message": "ListTopics failed.", | |||||
}) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "422": | |||||
// "$ref": "#/responses/invalidTopicsError" | |||||
topicNames := form.Topics | topicNames := form.Topics | ||||
validTopics, invalidTopics := models.SanitizeAndValidateTopics(topicNames) | validTopics, invalidTopics := models.SanitizeAndValidateTopics(topicNames) | ||||
err := models.SaveTopics(ctx.Repo.Repository.ID, validTopics...) | err := models.SaveTopics(ctx.Repo.Repository.ID, validTopics...) | ||||
if err != nil { | if err != nil { | ||||
log.Error("SaveTopics failed: %v", err) | log.Error("SaveTopics failed: %v", err) | ||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"message": "Save topics failed.", | |||||
}) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "422": | |||||
// "$ref": "#/responses/invalidTopicsError" | |||||
topicName := strings.TrimSpace(strings.ToLower(ctx.Params(":topic"))) | topicName := strings.TrimSpace(strings.ToLower(ctx.Params(":topic"))) | ||||
if !models.ValidateTopic(topicName) { | if !models.ValidateTopic(topicName) { | ||||
ctx.Error(http.StatusUnprocessableEntity, "", "Topic name is invalid") | |||||
ctx.JSON(http.StatusUnprocessableEntity, map[string]interface{}{ | |||||
"invalidTopics": topicName, | |||||
"message": "Topic name is invalid", | |||||
}) | |||||
return | return | ||||
} | } | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
log.Error("AddTopic failed: %v", err) | log.Error("AddTopic failed: %v", err) | ||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"message": "ListTopics failed.", | |||||
}) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
if len(topics) >= 25 { | if len(topics) >= 25 { | ||||
_, err = models.AddTopic(ctx.Repo.Repository.ID, topicName) | _, err = models.AddTopic(ctx.Repo.Repository.ID, topicName) | ||||
if err != nil { | if err != nil { | ||||
log.Error("AddTopic failed: %v", err) | log.Error("AddTopic failed: %v", err) | ||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"message": "AddTopic failed.", | |||||
}) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "422": | |||||
// "$ref": "#/responses/invalidTopicsError" | |||||
topicName := strings.TrimSpace(strings.ToLower(ctx.Params(":topic"))) | topicName := strings.TrimSpace(strings.ToLower(ctx.Params(":topic"))) | ||||
if !models.ValidateTopic(topicName) { | if !models.ValidateTopic(topicName) { | ||||
ctx.Error(http.StatusUnprocessableEntity, "", "Topic name is invalid") | |||||
ctx.JSON(http.StatusUnprocessableEntity, map[string]interface{}{ | |||||
"invalidTopics": topicName, | |||||
"message": "Topic name is invalid", | |||||
}) | |||||
return | return | ||||
} | } | ||||
topic, err := models.DeleteTopic(ctx.Repo.Repository.ID, topicName) | topic, err := models.DeleteTopic(ctx.Repo.Repository.ID, topicName) | ||||
if err != nil { | if err != nil { | ||||
log.Error("DeleteTopic failed: %v", err) | log.Error("DeleteTopic failed: %v", err) | ||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"message": "DeleteTopic failed.", | |||||
}) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TopicListResponse" | // "$ref": "#/responses/TopicListResponse" | ||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
if ctx.User == nil { | if ctx.User == nil { | ||||
ctx.JSON(http.StatusForbidden, map[string]interface{}{ | |||||
"message": "Only owners could change the topics.", | |||||
}) | |||||
ctx.Error(http.StatusForbidden, "UserIsNil", "Only owners could change the topics.") | |||||
return | return | ||||
} | } | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
log.Error("SearchTopics failed: %v", err) | log.Error("SearchTopics failed: %v", err) | ||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"message": "Search topics failed.", | |||||
}) | |||||
ctx.InternalServerError(err) | |||||
return | return | ||||
} | } | ||||
package repo | package repo | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/repofiles" | "code.gitea.io/gitea/modules/repofiles" | ||||
) | ) | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/GitTreeResponse" | // "$ref": "#/responses/GitTreeResponse" | ||||
// "400": | |||||
// "$ref": "#/responses/error" | |||||
sha := ctx.Params(":sha") | sha := ctx.Params(":sha") | ||||
if len(sha) == 0 { | if len(sha) == 0 { | ||||
ctx.Error(400, "", "sha not provided") | |||||
ctx.Error(http.StatusBadRequest, "", "sha not provided") | |||||
return | return | ||||
} | } | ||||
if tree, err := repofiles.GetTreeBySHA(ctx.Repo.Repository, sha, ctx.QueryInt("page"), ctx.QueryInt("per_page"), ctx.QueryBool("recursive")); err != nil { | if tree, err := repofiles.GetTreeBySHA(ctx.Repo.Repository, sha, ctx.QueryInt("page"), ctx.QueryInt("per_page"), ctx.QueryBool("recursive")); err != nil { | ||||
ctx.Error(400, "", err.Error()) | |||||
ctx.Error(http.StatusBadRequest, "", err.Error()) | |||||
} else { | } else { | ||||
ctx.JSON(200, tree) | |||||
ctx.JSON(http.StatusOK, tree) | |||||
} | } | ||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/AccessTokenList" | // "$ref": "#/responses/AccessTokenList" | ||||
tokens, err := models.ListAccessTokens(ctx.User.ID) | tokens, err := models.ListAccessTokens(ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ListAccessTokens", err) | |||||
ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err) | |||||
return | return | ||||
} | } | ||||
TokenLastEight: tokens[i].TokenLastEight, | TokenLastEight: tokens[i].TokenLastEight, | ||||
} | } | ||||
} | } | ||||
ctx.JSON(200, &apiTokens) | |||||
ctx.JSON(http.StatusOK, &apiTokens) | |||||
} | } | ||||
// CreateAccessToken create access tokens | // CreateAccessToken create access tokens | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/AccessToken" | // "$ref": "#/responses/AccessToken" | ||||
t := &models.AccessToken{ | t := &models.AccessToken{ | ||||
UID: ctx.User.ID, | UID: ctx.User.ID, | ||||
Name: form.Name, | Name: form.Name, | ||||
} | } | ||||
if err := models.NewAccessToken(t); err != nil { | if err := models.NewAccessToken(t); err != nil { | ||||
ctx.Error(500, "NewAccessToken", err) | |||||
ctx.Error(http.StatusInternalServerError, "NewAccessToken", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(201, &api.AccessToken{ | |||||
ctx.JSON(http.StatusCreated, &api.AccessToken{ | |||||
Name: t.Name, | Name: t.Name, | ||||
Token: t.Token, | Token: t.Token, | ||||
ID: t.ID, | ID: t.ID, | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
tokenID := ctx.ParamsInt64(":id") | tokenID := ctx.ParamsInt64(":id") | ||||
if err := models.DeleteAccessTokenByID(tokenID, ctx.User.ID); err != nil { | if err := models.DeleteAccessTokenByID(tokenID, ctx.User.ID); err != nil { | ||||
if models.IsErrAccessTokenNotExist(err) { | if models.IsErrAccessTokenNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "DeleteAccessTokenByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteAccessTokenByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/EmailList" | // "$ref": "#/responses/EmailList" | ||||
emails, err := models.GetEmailAddresses(ctx.User.ID) | emails, err := models.GetEmailAddresses(ctx.User.ID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetEmailAddresses", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetEmailAddresses", err) | |||||
return | return | ||||
} | } | ||||
apiEmails := make([]*api.Email, len(emails)) | apiEmails := make([]*api.Email, len(emails)) | ||||
for i := range emails { | for i := range emails { | ||||
apiEmails[i] = convert.ToEmail(emails[i]) | apiEmails[i] = convert.ToEmail(emails[i]) | ||||
} | } | ||||
ctx.JSON(200, &apiEmails) | |||||
ctx.JSON(http.StatusOK, &apiEmails) | |||||
} | } | ||||
// AddEmail add an email address | // AddEmail add an email address | ||||
// responses: | // responses: | ||||
// '201': | // '201': | ||||
// "$ref": "#/responses/EmailList" | // "$ref": "#/responses/EmailList" | ||||
// "422": | |||||
// "$ref": "#/responses/validationError" | |||||
if len(form.Emails) == 0 { | if len(form.Emails) == 0 { | ||||
ctx.Status(422) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Email list empty") | |||||
return | return | ||||
} | } | ||||
if err := models.AddEmailAddresses(emails); err != nil { | if err := models.AddEmailAddresses(emails); err != nil { | ||||
if models.IsErrEmailAlreadyUsed(err) { | if models.IsErrEmailAlreadyUsed(err) { | ||||
ctx.Error(422, "", "Email address has been used: "+err.(models.ErrEmailAlreadyUsed).Email) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Email address has been used: "+err.(models.ErrEmailAlreadyUsed).Email) | |||||
} else { | } else { | ||||
ctx.Error(500, "AddEmailAddresses", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddEmailAddresses", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
for i := range emails { | for i := range emails { | ||||
apiEmails[i] = convert.ToEmail(emails[i]) | apiEmails[i] = convert.ToEmail(emails[i]) | ||||
} | } | ||||
ctx.JSON(201, &apiEmails) | |||||
ctx.JSON(http.StatusCreated, &apiEmails) | |||||
} | } | ||||
// DeleteEmail delete email | // DeleteEmail delete email | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
if len(form.Emails) == 0 { | if len(form.Emails) == 0 { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
if err := models.DeleteEmailAddresses(emails); err != nil { | if err := models.DeleteEmailAddresses(emails); err != nil { | ||||
ctx.Error(500, "DeleteEmailAddresses", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteEmailAddresses", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
for i := range users { | for i := range users { | ||||
apiUsers[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | apiUsers[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | ||||
} | } | ||||
ctx.JSON(200, &apiUsers) | |||||
ctx.JSON(http.StatusOK, &apiUsers) | |||||
} | } | ||||
func listUserFollowers(ctx *context.APIContext, u *models.User) { | func listUserFollowers(ctx *context.APIContext, u *models.User) { | ||||
users, err := u.GetFollowers(ctx.QueryInt("page")) | users, err := u.GetFollowers(ctx.QueryInt("page")) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserFollowers", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err) | |||||
return | return | ||||
} | } | ||||
responseAPIUsers(ctx, users) | responseAPIUsers(ctx, users) | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
listUserFollowers(ctx, ctx.User) | listUserFollowers(ctx, ctx.User) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
u := GetUserByParams(ctx) | u := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
func listUserFollowing(ctx *context.APIContext, u *models.User) { | func listUserFollowing(ctx *context.APIContext, u *models.User) { | ||||
users, err := u.GetFollowing(ctx.QueryInt("page")) | users, err := u.GetFollowing(ctx.QueryInt("page")) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetFollowing", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetFollowing", err) | |||||
return | return | ||||
} | } | ||||
responseAPIUsers(ctx, users) | responseAPIUsers(ctx, users) | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
listUserFollowing(ctx, ctx.User) | listUserFollowing(ctx, ctx.User) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/UserList" | // "$ref": "#/responses/UserList" | ||||
u := GetUserByParams(ctx) | u := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
func checkUserFollowing(ctx *context.APIContext, u *models.User, followID int64) { | func checkUserFollowing(ctx *context.APIContext, u *models.User, followID int64) { | ||||
if u.IsFollowing(followID) { | if u.IsFollowing(followID) { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
target := GetUserByParams(ctx) | target := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
u := GetUserByParams(ctx) | u := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
target := GetUserByParams(ctx) | target := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if err := models.FollowUser(ctx.User.ID, target.ID); err != nil { | if err := models.FollowUser(ctx.User.ID, target.ID); err != nil { | ||||
ctx.Error(500, "FollowUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "FollowUser", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// Unfollow unfollow a user | // Unfollow unfollow a user | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
target := GetUserByParams(ctx) | target := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if err := models.UnfollowUser(ctx.User.ID, target.ID); err != nil { | if err := models.UnfollowUser(ctx.User.ID, target.ID); err != nil { | ||||
ctx.Error(500, "UnfollowUser", err) | |||||
ctx.Error(http.StatusInternalServerError, "UnfollowUser", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
func listGPGKeys(ctx *context.APIContext, uid int64) { | func listGPGKeys(ctx *context.APIContext, uid int64) { | ||||
keys, err := models.ListGPGKeys(uid) | keys, err := models.ListGPGKeys(uid) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ListGPGKeys", err) | |||||
ctx.Error(http.StatusInternalServerError, "ListGPGKeys", err) | |||||
return | return | ||||
} | } | ||||
apiKeys[i] = convert.ToGPGKey(keys[i]) | apiKeys[i] = convert.ToGPGKey(keys[i]) | ||||
} | } | ||||
ctx.JSON(200, &apiKeys) | |||||
ctx.JSON(http.StatusOK, &apiKeys) | |||||
} | } | ||||
//ListGPGKeys get the GPG key list of a user | //ListGPGKeys get the GPG key list of a user | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/GPGKeyList" | // "$ref": "#/responses/GPGKeyList" | ||||
user := GetUserByParams(ctx) | user := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/GPGKeyList" | // "$ref": "#/responses/GPGKeyList" | ||||
listGPGKeys(ctx, ctx.User.ID) | listGPGKeys(ctx, ctx.User.ID) | ||||
} | } | ||||
// "$ref": "#/responses/GPGKey" | // "$ref": "#/responses/GPGKey" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
key, err := models.GetGPGKeyByID(ctx.ParamsInt64(":id")) | key, err := models.GetGPGKeyByID(ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrGPGKeyNotExist(err) { | if models.IsErrGPGKeyNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetGPGKeyByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetGPGKeyByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToGPGKey(key)) | |||||
ctx.JSON(http.StatusOK, convert.ToGPGKey(key)) | |||||
} | } | ||||
// CreateUserGPGKey creates new GPG key to given user by ID. | // CreateUserGPGKey creates new GPG key to given user by ID. | ||||
HandleAddGPGKeyError(ctx, err) | HandleAddGPGKeyError(ctx, err) | ||||
return | return | ||||
} | } | ||||
ctx.JSON(201, convert.ToGPGKey(key)) | |||||
ctx.JSON(http.StatusCreated, convert.ToGPGKey(key)) | |||||
} | } | ||||
// swagger:parameters userCurrentPostGPGKey | // swagger:parameters userCurrentPostGPGKey | ||||
// "$ref": "#/responses/GPGKey" | // "$ref": "#/responses/GPGKey" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
CreateUserGPGKey(ctx, form, ctx.User.ID) | CreateUserGPGKey(ctx, form, ctx.User.ID) | ||||
} | } | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
if err := models.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | if err := models.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | ||||
if models.IsErrGPGKeyAccessDenied(err) { | if models.IsErrGPGKeyAccessDenied(err) { | ||||
ctx.Error(403, "", "You do not have access to this key") | |||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key") | |||||
} else { | } else { | ||||
ctx.Error(500, "DeleteGPGKey", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeleteGPGKey", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// HandleAddGPGKeyError handle add GPGKey error | // HandleAddGPGKeyError handle add GPGKey error | ||||
func HandleAddGPGKeyError(ctx *context.APIContext, err error) { | func HandleAddGPGKeyError(ctx *context.APIContext, err error) { | ||||
switch { | switch { | ||||
case models.IsErrGPGKeyAccessDenied(err): | case models.IsErrGPGKeyAccessDenied(err): | ||||
ctx.Error(422, "", "You do not have access to this GPG key") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "You do not have access to this GPG key") | |||||
case models.IsErrGPGKeyIDAlreadyUsed(err): | case models.IsErrGPGKeyIDAlreadyUsed(err): | ||||
ctx.Error(422, "", "A key with the same id already exists") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "A key with the same id already exists") | |||||
default: | default: | ||||
ctx.Error(500, "AddGPGKey", err) | |||||
ctx.Error(http.StatusInternalServerError, "AddGPGKey", err) | |||||
} | } | ||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/convert" | "code.gitea.io/gitea/modules/convert" | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return nil | return nil | ||||
} | } | ||||
} | } | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "ListPublicKeys", err) | |||||
ctx.Error(http.StatusInternalServerError, "ListPublicKeys", err) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
} | } | ||||
ctx.JSON(200, &apiKeys) | |||||
ctx.JSON(http.StatusOK, &apiKeys) | |||||
} | } | ||||
// ListMyPublicKeys list all of the authenticated user's public keys | // ListMyPublicKeys list all of the authenticated user's public keys | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/PublicKeyList" | // "$ref": "#/responses/PublicKeyList" | ||||
listPublicKeys(ctx, ctx.User) | listPublicKeys(ctx, ctx.User) | ||||
} | } | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/PublicKeyList" | // "$ref": "#/responses/PublicKeyList" | ||||
user := GetUserByParams(ctx) | user := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
// "$ref": "#/responses/PublicKey" | // "$ref": "#/responses/PublicKey" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
key, err := models.GetPublicKeyByID(ctx.ParamsInt64(":id")) | key, err := models.GetPublicKeyByID(ctx.ParamsInt64(":id")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrKeyNotExist(err) { | if models.IsErrKeyNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetPublicKeyByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetPublicKeyByID", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
if ctx.User.IsAdmin || ctx.User.ID == key.OwnerID { | if ctx.User.IsAdmin || ctx.User.ID == key.OwnerID { | ||||
apiKey, _ = appendPrivateInformation(apiKey, key, ctx.User) | apiKey, _ = appendPrivateInformation(apiKey, key, ctx.User) | ||||
} | } | ||||
ctx.JSON(200, apiKey) | |||||
ctx.JSON(http.StatusOK, apiKey) | |||||
} | } | ||||
// CreateUserPublicKey creates new public key to given user by ID. | // CreateUserPublicKey creates new public key to given user by ID. | ||||
if ctx.User.IsAdmin || ctx.User.ID == key.OwnerID { | if ctx.User.IsAdmin || ctx.User.ID == key.OwnerID { | ||||
apiKey, _ = appendPrivateInformation(apiKey, key, ctx.User) | apiKey, _ = appendPrivateInformation(apiKey, key, ctx.User) | ||||
} | } | ||||
ctx.JSON(201, apiKey) | |||||
ctx.JSON(http.StatusCreated, apiKey) | |||||
} | } | ||||
// CreatePublicKey create one public key for me | // CreatePublicKey create one public key for me | ||||
// "$ref": "#/responses/PublicKey" | // "$ref": "#/responses/PublicKey" | ||||
// "422": | // "422": | ||||
// "$ref": "#/responses/validationError" | // "$ref": "#/responses/validationError" | ||||
CreateUserPublicKey(ctx, form, ctx.User.ID) | CreateUserPublicKey(ctx, form, ctx.User.ID) | ||||
} | } | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
if err := models.DeletePublicKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | if err := models.DeletePublicKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | ||||
if models.IsErrKeyNotExist(err) { | if models.IsErrKeyNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else if models.IsErrKeyAccessDenied(err) { | } else if models.IsErrKeyAccessDenied(err) { | ||||
ctx.Error(403, "", "You do not have access to this key") | |||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key") | |||||
} else { | } else { | ||||
ctx.Error(500, "DeletePublicKey", err) | |||||
ctx.Error(http.StatusInternalServerError, "DeletePublicKey", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
func listUserRepos(ctx *context.APIContext, u *models.User, private bool) { | func listUserRepos(ctx *context.APIContext, u *models.User, private bool) { | ||||
repos, err := models.GetUserRepositories(u.ID, private, 1, u.NumRepos, "") | repos, err := models.GetUserRepositories(u.ID, private, 1, u.NumRepos, "") | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserRepositories", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) | |||||
return | return | ||||
} | } | ||||
for i := range repos { | for i := range repos { | ||||
access, err := models.AccessLevel(ctx.User, repos[i]) | access, err := models.AccessLevel(ctx.User, repos[i]) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "AccessLevel", err) | |||||
ctx.Error(http.StatusInternalServerError, "AccessLevel", err) | |||||
return | return | ||||
} | } | ||||
if ctx.IsSigned && ctx.User.IsAdmin || access >= models.AccessModeRead { | if ctx.IsSigned && ctx.User.IsAdmin || access >= models.AccessModeRead { | ||||
apiRepos = append(apiRepos, repos[i].APIFormat(access)) | apiRepos = append(apiRepos, repos[i].APIFormat(access)) | ||||
} | } | ||||
} | } | ||||
ctx.JSON(200, &apiRepos) | |||||
ctx.JSON(http.StatusOK, &apiRepos) | |||||
} | } | ||||
// ListUserRepos - list the repos owned by the given user. | // ListUserRepos - list the repos owned by the given user. | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
user := GetUserByParams(ctx) | user := GetUserByParams(ctx) | ||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
ownRepos, err := models.GetUserRepositories(ctx.User.ID, true, 1, ctx.User.NumRepos, "") | ownRepos, err := models.GetUserRepositories(ctx.User.ID, true, 1, ctx.User.NumRepos, "") | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetUserRepositories", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) | |||||
return | return | ||||
} | } | ||||
accessibleReposMap, err := ctx.User.GetRepositoryAccesses() | accessibleReposMap, err := ctx.User.GetRepositoryAccesses() | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetRepositoryAccesses", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetRepositoryAccesses", err) | |||||
return | return | ||||
} | } | ||||
apiRepos[i] = repo.APIFormat(access) | apiRepos[i] = repo.APIFormat(access) | ||||
i++ | i++ | ||||
} | } | ||||
ctx.JSON(200, &apiRepos) | |||||
ctx.JSON(http.StatusOK, &apiRepos) | |||||
} | } | ||||
// ListOrgRepos - list the repositories of an organization. | // ListOrgRepos - list the repositories of an organization. | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
listUserRepos(ctx, ctx.Org.Organization, ctx.IsSigned) | listUserRepos(ctx, ctx.Org.Organization, ctx.IsSigned) | ||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
user := GetUserByParams(ctx) | user := GetUserByParams(ctx) | ||||
private := user.ID == ctx.User.ID | private := user.ID == ctx.User.ID | ||||
repos, err := getStarredRepos(user, private) | repos, err := getStarredRepos(user, private) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "getStarredRepos", err) | |||||
ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) | |||||
} | } | ||||
ctx.JSON(200, &repos) | |||||
ctx.JSON(http.StatusOK, &repos) | |||||
} | } | ||||
// GetMyStarredRepos returns the repos that the authenticated user has starred | // GetMyStarredRepos returns the repos that the authenticated user has starred | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
repos, err := getStarredRepos(ctx.User, true) | repos, err := getStarredRepos(ctx.User, true) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "getStarredRepos", err) | |||||
ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) | |||||
} | } | ||||
ctx.JSON(200, &repos) | |||||
ctx.JSON(http.StatusOK, &repos) | |||||
} | } | ||||
// IsStarring returns whether the authenticated is starring the repo | // IsStarring returns whether the authenticated is starring the repo | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
if models.IsStaring(ctx.User.ID, ctx.Repo.Repository.ID) { | if models.IsStaring(ctx.User.ID, ctx.Repo.Repository.ID) { | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} else { | } else { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} | } | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) | err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "StarRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "StarRepo", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// Unstar the repo specified in the APIContext, as the authenticated user | // Unstar the repo specified in the APIContext, as the authenticated user | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) | err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "StarRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "StarRepo", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } |
// type: array | // type: array | ||||
// items: | // items: | ||||
// "$ref": "#/definitions/User" | // "$ref": "#/definitions/User" | ||||
opts := &models.SearchUserOptions{ | opts := &models.SearchUserOptions{ | ||||
Keyword: strings.Trim(ctx.Query("q"), " "), | Keyword: strings.Trim(ctx.Query("q"), " "), | ||||
UID: com.StrTo(ctx.Query("uid")).MustInt64(), | UID: com.StrTo(ctx.Query("uid")).MustInt64(), | ||||
users, _, err := models.SearchUsers(opts) | users, _, err := models.SearchUsers(opts) | ||||
if err != nil { | if err != nil { | ||||
ctx.JSON(500, map[string]interface{}{ | |||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | |||||
"ok": false, | "ok": false, | ||||
"error": err.Error(), | "error": err.Error(), | ||||
}) | }) | ||||
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin) | ||||
} | } | ||||
ctx.JSON(200, map[string]interface{}{ | |||||
ctx.JSON(http.StatusOK, map[string]interface{}{ | |||||
"ok": true, | "ok": true, | ||||
"data": results, | "data": results, | ||||
}) | }) | ||||
// "$ref": "#/responses/User" | // "$ref": "#/responses/User" | ||||
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
u, err := models.GetUserByName(ctx.Params(":username")) | u, err := models.GetUserByName(ctx.Params(":username")) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetUserByName", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err) | |||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User != nil && (ctx.User.ID == u.ID || ctx.User.IsAdmin))) | |||||
ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.IsSigned, ctx.User != nil && (ctx.User.ID == u.ID || ctx.User.IsAdmin))) | |||||
} | } | ||||
// GetAuthenticatedUser get current user's information | // GetAuthenticatedUser get current user's information | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/User" | // "$ref": "#/responses/User" | ||||
ctx.JSON(200, convert.ToUser(ctx.User, ctx.IsSigned, ctx.User != nil)) | |||||
ctx.JSON(http.StatusOK, convert.ToUser(ctx.User, ctx.IsSigned, ctx.User != nil)) | |||||
} | } | ||||
// GetUserHeatmapData is the handler to get a users heatmap | // GetUserHeatmapData is the handler to get a users heatmap | ||||
ctx.Error(http.StatusInternalServerError, "GetUserHeatmapDataByUser", err) | ctx.Error(http.StatusInternalServerError, "GetUserHeatmapDataByUser", err) | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, heatmap) | |||||
ctx.JSON(http.StatusOK, heatmap) | |||||
} | } |
package user | package user | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
user := GetUserByParams(ctx) | user := GetUserByParams(ctx) | ||||
private := user.ID == ctx.User.ID | private := user.ID == ctx.User.ID | ||||
repos, err := getWatchedRepos(user, private) | repos, err := getWatchedRepos(user, private) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "getWatchedRepos", err) | |||||
ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) | |||||
} | } | ||||
ctx.JSON(200, &repos) | |||||
ctx.JSON(http.StatusOK, &repos) | |||||
} | } | ||||
// GetMyWatchedRepos returns the repos that the authenticated user is watching | // GetMyWatchedRepos returns the repos that the authenticated user is watching | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
repos, err := getWatchedRepos(ctx.User, true) | repos, err := getWatchedRepos(ctx.User, true) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "getWatchedRepos", err) | |||||
ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) | |||||
} | } | ||||
ctx.JSON(200, &repos) | |||||
ctx.JSON(http.StatusOK, &repos) | |||||
} | } | ||||
// IsWatching returns whether the authenticated user is watching the repo | // IsWatching returns whether the authenticated user is watching the repo | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/WatchInfo" | // "$ref": "#/responses/WatchInfo" | ||||
if models.IsWatching(ctx.User.ID, ctx.Repo.Repository.ID) { | if models.IsWatching(ctx.User.ID, ctx.Repo.Repository.ID) { | ||||
ctx.JSON(200, api.WatchInfo{ | |||||
ctx.JSON(http.StatusOK, api.WatchInfo{ | |||||
Subscribed: true, | Subscribed: true, | ||||
Ignored: false, | Ignored: false, | ||||
Reason: nil, | Reason: nil, | ||||
// responses: | // responses: | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/WatchInfo" | // "$ref": "#/responses/WatchInfo" | ||||
err := models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) | err := models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "WatchRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "WatchRepo", err) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, api.WatchInfo{ | |||||
ctx.JSON(http.StatusOK, api.WatchInfo{ | |||||
Subscribed: true, | Subscribed: true, | ||||
Ignored: false, | Ignored: false, | ||||
Reason: nil, | Reason: nil, | ||||
// responses: | // responses: | ||||
// "204": | // "204": | ||||
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
err := models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) | err := models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "UnwatchRepo", err) | |||||
ctx.Error(http.StatusInternalServerError, "UnwatchRepo", err) | |||||
return | return | ||||
} | } | ||||
ctx.Status(204) | |||||
ctx.Status(http.StatusNoContent) | |||||
} | } | ||||
// subscriptionURL returns the URL of the subscription API endpoint of a repo | // subscriptionURL returns the URL of the subscription API endpoint of a repo |
if models.IsErrWebhookNotExist(err) { | if models.IsErrWebhookNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetWebhookByOrgID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetWebhookByOrgID", err) | |||||
} | } | ||||
return nil, err | return nil, err | ||||
} | } | ||||
if models.IsErrWebhookNotExist(err) { | if models.IsErrWebhookNotExist(err) { | ||||
ctx.NotFound() | ctx.NotFound() | ||||
} else { | } else { | ||||
ctx.Error(500, "GetWebhookByID", err) | |||||
ctx.Error(http.StatusInternalServerError, "GetWebhookByID", err) | |||||
} | } | ||||
return nil, err | return nil, err | ||||
} | } | ||||
// write the appropriate error to `ctx`. Return whether the form is valid | // write the appropriate error to `ctx`. Return whether the form is valid | ||||
func CheckCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption) bool { | func CheckCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption) bool { | ||||
if !models.IsValidHookTaskType(form.Type) { | if !models.IsValidHookTaskType(form.Type) { | ||||
ctx.Error(422, "", "Invalid hook type") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid hook type") | |||||
return false | return false | ||||
} | } | ||||
for _, name := range []string{"url", "content_type"} { | for _, name := range []string{"url", "content_type"} { | ||||
if _, ok := form.Config[name]; !ok { | if _, ok := form.Config[name]; !ok { | ||||
ctx.Error(422, "", "Missing config option: "+name) | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Missing config option: "+name) | |||||
return false | return false | ||||
} | } | ||||
} | } | ||||
if !models.IsValidHookContentType(form.Config["content_type"]) { | if !models.IsValidHookContentType(form.Config["content_type"]) { | ||||
ctx.Error(422, "", "Invalid content type") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type") | |||||
return false | return false | ||||
} | } | ||||
return true | return true | ||||
if w.HookTaskType == models.SLACK { | if w.HookTaskType == models.SLACK { | ||||
channel, ok := form.Config["channel"] | channel, ok := form.Config["channel"] | ||||
if !ok { | if !ok { | ||||
ctx.Error(422, "", "Missing config option: channel") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Missing config option: channel") | |||||
return nil, false | return nil, false | ||||
} | } | ||||
if !utils.IsValidSlackChannel(channel) { | if !utils.IsValidSlackChannel(channel) { | ||||
ctx.Error(400, "", "Invalid slack channel name") | |||||
ctx.Error(http.StatusBadRequest, "", "Invalid slack channel name") | |||||
return nil, false | return nil, false | ||||
} | } | ||||
Color: form.Config["color"], | Color: form.Config["color"], | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "slack: JSON marshal failed", err) | |||||
ctx.Error(http.StatusInternalServerError, "slack: JSON marshal failed", err) | |||||
return nil, false | return nil, false | ||||
} | } | ||||
w.Meta = string(meta) | w.Meta = string(meta) | ||||
} | } | ||||
if err := w.UpdateEvent(); err != nil { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.Error(500, "UpdateEvent", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateEvent", err) | |||||
return nil, false | return nil, false | ||||
} else if err := models.CreateWebhook(w); err != nil { | } else if err := models.CreateWebhook(w); err != nil { | ||||
ctx.Error(500, "CreateWebhook", err) | |||||
ctx.Error(http.StatusInternalServerError, "CreateWebhook", err) | |||||
return nil, false | return nil, false | ||||
} | } | ||||
return w, true | return w, true | ||||
if err != nil { | if err != nil { | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToHook(org.HomeLink(), updated)) | |||||
ctx.JSON(http.StatusOK, convert.ToHook(org.HomeLink(), updated)) | |||||
} | } | ||||
// EditRepoHook edit webhook `w` according to `form`. Writes to `ctx` accordingly | // EditRepoHook edit webhook `w` according to `form`. Writes to `ctx` accordingly | ||||
if err != nil { | if err != nil { | ||||
return | return | ||||
} | } | ||||
ctx.JSON(200, convert.ToHook(repo.RepoLink, updated)) | |||||
ctx.JSON(http.StatusOK, convert.ToHook(repo.RepoLink, updated)) | |||||
} | } | ||||
// editHook edit the webhook `w` according to `form`. If an error occurs, write | // editHook edit the webhook `w` according to `form`. If an error occurs, write | ||||
} | } | ||||
if ct, ok := form.Config["content_type"]; ok { | if ct, ok := form.Config["content_type"]; ok { | ||||
if !models.IsValidHookContentType(ct) { | if !models.IsValidHookContentType(ct) { | ||||
ctx.Error(422, "", "Invalid content type") | |||||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type") | |||||
return false | return false | ||||
} | } | ||||
w.ContentType = models.ToHookContentType(ct) | w.ContentType = models.ToHookContentType(ct) | ||||
Color: form.Config["color"], | Color: form.Config["color"], | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "slack: JSON marshal failed", err) | |||||
ctx.Error(http.StatusInternalServerError, "slack: JSON marshal failed", err) | |||||
return false | return false | ||||
} | } | ||||
w.Meta = string(meta) | w.Meta = string(meta) | ||||
w.BranchFilter = form.BranchFilter | w.BranchFilter = form.BranchFilter | ||||
if err := w.UpdateEvent(); err != nil { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.Error(500, "UpdateEvent", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateEvent", err) | |||||
return false | return false | ||||
} | } | ||||
} | } | ||||
if err := models.UpdateWebhook(w); err != nil { | if err := models.UpdateWebhook(w); err != nil { | ||||
ctx.Error(500, "UpdateWebhook", err) | |||||
ctx.Error(http.StatusInternalServerError, "UpdateWebhook", err) | |||||
return false | return false | ||||
} | } | ||||
return true | return true |
"201": { | "201": { | ||||
"$ref": "#/responses/User" | "$ref": "#/responses/User" | ||||
}, | }, | ||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
}, | |||||
"403": { | "403": { | ||||
"$ref": "#/responses/forbidden" | "$ref": "#/responses/forbidden" | ||||
}, | }, | ||||
"403": { | "403": { | ||||
"$ref": "#/responses/forbidden" | "$ref": "#/responses/forbidden" | ||||
}, | }, | ||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
}, | |||||
"409": { | |||||
"$ref": "#/responses/error" | |||||
}, | |||||
"422": { | "422": { | ||||
"$ref": "#/responses/validationError" | "$ref": "#/responses/validationError" | ||||
} | } | ||||
"204": { | "204": { | ||||
"description": "user is a member" | "description": "user is a member" | ||||
}, | }, | ||||
"302": { | |||||
"description": "redirection to /orgs/{org}/public_members/{username}" | |||||
}, | |||||
"404": { | "404": { | ||||
"description": "user is not a member" | "description": "user is not a member" | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"description": "membership publicized" | "description": "membership publicized" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Team" | "$ref": "#/responses/Team" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Repository" | "$ref": "#/responses/Repository" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"description": "success" | "description": "success" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | }, | ||||
"404": { | "404": { | ||||
"$ref": "#/responses/empty" | |||||
"$ref": "#/responses/notFound" | |||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/Status" | "$ref": "#/responses/Status" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"description": "success" | "description": "success" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"202": { | "202": { | ||||
"$ref": "#/responses/Repository" | "$ref": "#/responses/Repository" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/GitBlobResponse" | "$ref": "#/responses/GitBlobResponse" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/AnnotatedTag" | "$ref": "#/responses/AnnotatedTag" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/GitTreeResponse" | "$ref": "#/responses/GitTreeResponse" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/Hook" | "$ref": "#/responses/Hook" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Issue" | "$ref": "#/responses/Issue" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
}, | |||||
"412": { | |||||
"$ref": "#/responses/error" | |||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/ReactionResponseList" | "$ref": "#/responses/ReactionResponseList" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/ReactionResponse" | "$ref": "#/responses/ReactionResponse" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/TrackedTimeList" | "$ref": "#/responses/TrackedTimeList" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"$ref": "#/responses/error" | "$ref": "#/responses/error" | ||||
}, | }, | ||||
"403": { | "403": { | ||||
"$ref": "#/responses/error" | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/Issue" | "$ref": "#/responses/Issue" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Issue" | "$ref": "#/responses/Issue" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
}, | |||||
"412": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Comment" | "$ref": "#/responses/Comment" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/Comment" | "$ref": "#/responses/Comment" | ||||
}, | |||||
"204": { | |||||
"$ref": "#/responses/empty" | |||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"$ref": "#/responses/IssueDeadline" | "$ref": "#/responses/IssueDeadline" | ||||
}, | }, | ||||
"403": { | "403": { | ||||
"description": "Not repo writer" | |||||
"$ref": "#/responses/forbidden" | |||||
}, | }, | ||||
"404": { | "404": { | ||||
"description": "Issue not found" | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/LabelList" | "$ref": "#/responses/LabelList" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/LabelList" | "$ref": "#/responses/LabelList" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/ReactionResponseList" | "$ref": "#/responses/ReactionResponseList" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/ReactionResponse" | "$ref": "#/responses/ReactionResponse" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"description": "Not repo writer, user does not have rights to toggle stopwatch" | "description": "Not repo writer, user does not have rights to toggle stopwatch" | ||||
}, | }, | ||||
"404": { | "404": { | ||||
"description": "Issue not found" | |||||
"$ref": "#/responses/notFound" | |||||
}, | }, | ||||
"409": { | "409": { | ||||
"description": "Cannot cancel a non existent stopwatch" | "description": "Cannot cancel a non existent stopwatch" | ||||
"description": "Not repo writer, user does not have rights to toggle stopwatch" | "description": "Not repo writer, user does not have rights to toggle stopwatch" | ||||
}, | }, | ||||
"404": { | "404": { | ||||
"description": "Issue not found" | |||||
"$ref": "#/responses/notFound" | |||||
}, | }, | ||||
"409": { | "409": { | ||||
"description": "Cannot start a stopwatch again if it already exists" | "description": "Cannot start a stopwatch again if it already exists" | ||||
"description": "Not repo writer, user does not have rights to toggle stopwatch" | "description": "Not repo writer, user does not have rights to toggle stopwatch" | ||||
}, | }, | ||||
"404": { | "404": { | ||||
"description": "Issue not found" | |||||
"$ref": "#/responses/notFound" | |||||
}, | }, | ||||
"409": { | "409": { | ||||
"description": "Cannot stop a non existent stopwatch" | "description": "Cannot stop a non existent stopwatch" | ||||
"$ref": "#/responses/UserList" | "$ref": "#/responses/UserList" | ||||
}, | }, | ||||
"404": { | "404": { | ||||
"description": "Issue not found" | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"description": "User can only subscribe itself if he is no admin" | "description": "User can only subscribe itself if he is no admin" | ||||
}, | }, | ||||
"404": { | "404": { | ||||
"description": "Issue not found" | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"description": "User can only subscribe itself if he is no admin" | "description": "User can only subscribe itself if he is no admin" | ||||
}, | }, | ||||
"404": { | "404": { | ||||
"description": "Issue not found" | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/DeployKey" | "$ref": "#/responses/DeployKey" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/PullRequest" | "$ref": "#/responses/PullRequest" | ||||
}, | |||||
"409": { | |||||
"$ref": "#/responses/error" | |||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/PullRequest" | "$ref": "#/responses/PullRequest" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
}, | |||||
"412": { | |||||
"$ref": "#/responses/error" | |||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"405": { | "405": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"409": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"description": "success" | "description": "success" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Release" | "$ref": "#/responses/Release" | ||||
}, | |||||
"409": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Attachment" | "$ref": "#/responses/Attachment" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/StatusList" | "$ref": "#/responses/StatusList" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/Status" | "$ref": "#/responses/Status" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/TrackedTimeList" | "$ref": "#/responses/TrackedTimeList" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/TrackedTimeList" | "$ref": "#/responses/TrackedTimeList" | ||||
}, | |||||
"400": { | |||||
"$ref": "#/responses/error" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/invalidTopicsError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/invalidTopicsError" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/invalidTopicsError" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/User" | "$ref": "#/responses/User" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"404": { | |||||
"$ref": "#/responses/notFound" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"responses": { | "responses": { | ||||
"204": { | "204": { | ||||
"$ref": "#/responses/empty" | "$ref": "#/responses/empty" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"200": { | "200": { | ||||
"$ref": "#/responses/TopicListResponse" | "$ref": "#/responses/TopicListResponse" | ||||
}, | |||||
"403": { | |||||
"$ref": "#/responses/forbidden" | |||||
} | } | ||||
} | } | ||||
} | } | ||||
"responses": { | "responses": { | ||||
"201": { | "201": { | ||||
"$ref": "#/responses/EmailList" | "$ref": "#/responses/EmailList" | ||||
}, | |||||
"422": { | |||||
"$ref": "#/responses/validationError" | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"invalidTopicsError": { | |||||
"description": "APIInvalidTopicsError is error format response to invalid topics", | |||||
"headers": { | |||||
"invalidTopics": { | |||||
"type": "array", | |||||
"items": { | |||||
"type": "string" | |||||
} | |||||
}, | |||||
"message": { | |||||
"type": "string" | |||||
} | |||||
} | |||||
}, | |||||
"notFound": { | "notFound": { | ||||
"description": "APINotFound is a not found empty response" | "description": "APINotFound is a not found empty response" | ||||
}, | }, |