- Generate swagger.json into public/ - Add swagger-ui auto-installation - Add footer link to local swagger-ui - Add /swagger url for using app url. - Fix Swagger-UI version via git tagtags/v1.2.0-rc1
| @@ -54,6 +54,9 @@ generate: | |||
| @hash go-bindata > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ | |||
| go get -u github.com/jteeuwen/go-bindata/...; \ | |||
| fi | |||
| @hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ | |||
| go get -u github.com/go-swagger/go-swagger/cmd/swagger; \ | |||
| fi | |||
| go generate $(PACKAGES) | |||
| .PHONY: errcheck | |||
| @@ -184,5 +187,13 @@ stylesheets: public/css/index.css | |||
| public/css/index.css: $(STYLESHEETS) | |||
| lessc $< $@ | |||
| .PHONY: swagger-ui | |||
| swagger-ui: | |||
| rm -Rf public/assets/swagger-ui | |||
| git clone --depth=10 -b v3.0.7 --single-branch https://github.com/swagger-api/swagger-ui.git /tmp/swagger-ui | |||
| mv /tmp/swagger-ui/dist public/assets/swagger-ui | |||
| rm -Rf /tmp/swagger-ui | |||
| sed -i "s;http://petstore.swagger.io/v2/swagger.json;../../swagger.v1.json;g" public/assets/swagger-ui/index.html | |||
| .PHONY: assets | |||
| assets: javascripts stylesheets | |||
| @@ -84,16 +84,27 @@ func (repos MirrorRepositoryList) LoadAttributes() error { | |||
| } | |||
| // SearchRepoOptions holds the search options | |||
| // swagger:parameters repoSearch | |||
| type SearchRepoOptions struct { | |||
| Keyword string | |||
| OwnerID int64 | |||
| Searcher *User //ID of the person who's seeking | |||
| OrderBy string | |||
| Private bool // Include private repositories in results | |||
| Starred bool | |||
| Page int | |||
| IsProfile bool | |||
| PageSize int // Can be smaller than or equal to setting.ExplorePagingNum | |||
| // Keyword to search | |||
| // | |||
| // in: query | |||
| Keyword string `json:"q"` | |||
| // Owner in we search search | |||
| // | |||
| // in: query | |||
| OwnerID int64 `json:"uid"` | |||
| Searcher *User `json:"-"` //ID of the person who's seeking | |||
| OrderBy string `json:"-"` | |||
| Private bool `json:"-"` // Include private repositories in results | |||
| Starred bool `json:"-"` | |||
| Page int `json:"-"` | |||
| IsProfile bool `json:"-"` | |||
| // Limit of result | |||
| // | |||
| // maximum: setting.ExplorePagingNum | |||
| // in: query | |||
| PageSize int `json:"limit"` // Can be smaller than or equal to setting.ExplorePagingNum | |||
| } | |||
| // SearchRepositoryByName takes keyword and part of repository name to search, | |||
| @@ -23,6 +23,34 @@ type APIContext struct { | |||
| Org *APIOrganization | |||
| } | |||
| // APIError is error format response | |||
| // swagger:response error | |||
| type APIError struct { | |||
| Message string `json:"message"` | |||
| URL string `json:"url"` | |||
| } | |||
| // APIValidationError is error format response related to input validation | |||
| // swagger:response validationError | |||
| type APIValidationError struct { | |||
| Message string `json:"message"` | |||
| URL string `json:"url"` | |||
| } | |||
| //APIEmpty is a empty response | |||
| // swagger:response empty | |||
| type APIEmpty struct{} | |||
| //APIForbiddenError is a forbidden error response | |||
| // swagger:response forbidden | |||
| type APIForbiddenError struct { | |||
| APIError | |||
| } | |||
| //APINotFound is a not found empty response | |||
| // swagger:response notFound | |||
| type APINotFound struct{} | |||
| // Error responses error message to client with given message. | |||
| // If status is 500, also it prints error to log. | |||
| func (ctx *APIContext) Error(status int, title string, obj interface{}) { | |||
| @@ -37,9 +65,9 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) { | |||
| log.Error(4, "%s: %s", title, message) | |||
| } | |||
| ctx.JSON(status, map[string]string{ | |||
| "message": message, | |||
| "url": base.DocURL, | |||
| ctx.JSON(status, APIError{ | |||
| Message: message, | |||
| URL: base.DocURL, | |||
| }) | |||
| } | |||
| @@ -0,0 +1,93 @@ | |||
| <!-- HTML for static distribution bundle build --> | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Swagger UI</title> | |||
| <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet"> | |||
| <link rel="stylesheet" type="text/css" href="./swagger-ui.css" > | |||
| <link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" /> | |||
| <link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" /> | |||
| <style> | |||
| html | |||
| { | |||
| box-sizing: border-box; | |||
| overflow: -moz-scrollbars-vertical; | |||
| overflow-y: scroll; | |||
| } | |||
| *, | |||
| *:before, | |||
| *:after | |||
| { | |||
| box-sizing: inherit; | |||
| } | |||
| body { | |||
| margin:0; | |||
| background: #fafafa; | |||
| } | |||
| </style> | |||
| </head> | |||
| <body> | |||
| <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0"> | |||
| <defs> | |||
| <symbol viewBox="0 0 20 20" id="unlocked"> | |||
| <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="locked"> | |||
| <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="close"> | |||
| <path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="large-arrow"> | |||
| <path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="large-arrow-down"> | |||
| <path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 24 24" id="jump-to"> | |||
| <path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 24 24" id="expand"> | |||
| <path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/> | |||
| </symbol> | |||
| </defs> | |||
| </svg> | |||
| <div id="swagger-ui"></div> | |||
| <script src="./swagger-ui-bundle.js"> </script> | |||
| <script src="./swagger-ui-standalone-preset.js"> </script> | |||
| <script> | |||
| window.onload = function() { | |||
| // Build a system | |||
| const ui = SwaggerUIBundle({ | |||
| url: "../../swagger.v1.json", | |||
| dom_id: '#swagger-ui', | |||
| presets: [ | |||
| SwaggerUIBundle.presets.apis, | |||
| SwaggerUIStandalonePreset | |||
| ], | |||
| plugins: [ | |||
| SwaggerUIBundle.plugins.DownloadUrl | |||
| ], | |||
| layout: "StandaloneLayout" | |||
| }) | |||
| window.ui = ui | |||
| } | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,83 @@ | |||
| <!doctype html> | |||
| <html lang="en-US"> | |||
| <body onload="run()"> | |||
| </body> | |||
| </html> | |||
| <script> | |||
| 'use strict'; | |||
| function run () { | |||
| var oauth2 = window.opener.swaggerUIRedirectOauth2; | |||
| var sentState = oauth2.state; | |||
| var isValid, qp; | |||
| qp = (window.location.hash || location.search).substring(1); | |||
| qp = qp ? JSON.parse('{"' + qp.replace(/&/g, '","').replace(/=/g, '":"') + '"}', | |||
| function (key, value) { | |||
| return key === "" ? value : decodeURIComponent(value) | |||
| } | |||
| ) : {} | |||
| isValid = qp.state === sentState | |||
| if (oauth2.auth.schema.get("flow") === "accessCode" && !oauth2.auth.code) { | |||
| if (!isValid) { | |||
| oauth2.errCb({ | |||
| authId: oauth2.auth.name, | |||
| source: "auth", | |||
| level: "warning", | |||
| message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server" | |||
| }); | |||
| } | |||
| if (qp.code) { | |||
| delete oauth2.state; | |||
| oauth2.auth.code = qp.code; | |||
| createForm(oauth2.auth, qp).submit(); | |||
| } else { | |||
| oauth2.errCb({ | |||
| authId: oauth2.auth.name, | |||
| source: "auth", | |||
| level: "error", | |||
| message: "Authorization failed: no accessCode came from the server" | |||
| }); | |||
| window.close(); | |||
| } | |||
| } else { | |||
| oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid}); | |||
| window.close(); | |||
| } | |||
| } | |||
| function createForm(auth, qp) { | |||
| var form = document.createElement("form"); | |||
| var schema = auth.schema; | |||
| var action = schema.get("tokenUrl"); | |||
| var name, input; | |||
| var fields = { | |||
| code: qp.code, | |||
| "redirect_uri": location.protocol + "//" + location.host + location.pathname, | |||
| "grant_type": "authorization_code", | |||
| "client_secret": auth.clientSecret, | |||
| "client_id": auth.clientId | |||
| } | |||
| for ( name in fields ) { | |||
| input = document.createElement("input"); | |||
| input.name = name; | |||
| input.value = fields[name]; | |||
| input.type = "hidden"; | |||
| form.appendChild(input); | |||
| } | |||
| form.method = "POST"; | |||
| form.action = action; | |||
| document.body.appendChild(form); | |||
| return form; | |||
| } | |||
| </script> | |||
| @@ -0,0 +1 @@ | |||
| {"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0dA;;;;;;AAoIA;AAk7FA;AAmtCA;;;;;AA0uIA;AA+4IA;AAm9FA;AA2rGA;AA8lFA;AA2nFA;AAu9CA;AAyhDA;AAqrCA;AAy4EA;AA8/GA;;;;;;;;;;;;;;AA+mJA;AA4mIA;AAquJA;AAwsHA;AAinGA;AAmiEA;AAy4DA;AAm2DA;AA0nBA;;;;;;AA4iFA;AAk0FA;;;;;AA23CA;AA2qFA;AAw2CA;AAglCA;AA0/CA;AAykFA;AA+1FA;;;;;;;;;AAk4CA;AA2zIA;AAk4DA;AAolDA","sourceRoot":""} | |||
| @@ -0,0 +1 @@ | |||
| {"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA4QA;AAitGA","sourceRoot":""} | |||
| @@ -0,0 +1 @@ | |||
| {"version":3,"file":"swagger-ui.css","sources":[],"mappings":"","sourceRoot":""} | |||
| @@ -0,0 +1 @@ | |||
| {"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA4wCA;AAoyHA;AAuxHA;AAy4FA;AA8rCA;AAugCA;AA+hCA;AA24BA","sourceRoot":""} | |||
| @@ -2,6 +2,31 @@ | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| //go:generate swagger generate spec -o ../../../public/swagger.v1.json | |||
| //go:generate sed -i "s;\".ref\": \"#/definitions/GPGKey\";\"type\": \"object\";g" ../../../public/swagger.v1.json | |||
| // Package v1 Gitea API. | |||
| // | |||
| // This provide API interface to communicate with this Gitea instance. | |||
| // | |||
| // Terms Of Service: | |||
| // | |||
| // there are no TOS at this moment, use at your own risk we take no responsibility | |||
| // | |||
| // Schemes: http, https | |||
| // BasePath: /api/v1 | |||
| // Version: 1.1.1 | |||
| // License: MIT http://opensource.org/licenses/MIT | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // - text/plain | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // - text/html | |||
| // | |||
| // swagger:meta | |||
| package v1 | |||
| import ( | |||
| @@ -13,8 +13,19 @@ import ( | |||
| ) | |||
| // Markdown render markdown document to HTML | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Miscellaneous#render-an-arbitrary-markdown-document | |||
| func Markdown(ctx *context.APIContext, form api.MarkdownOption) { | |||
| // swagger:route POST /markdown renderMarkdown | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // | |||
| // Produces: | |||
| // - text/html | |||
| // | |||
| // Responses: | |||
| // 200: MarkdownRender | |||
| // 422: validationError | |||
| if ctx.HasAPIError() { | |||
| ctx.Error(422, "", ctx.GetErrMsg()) | |||
| return | |||
| @@ -40,8 +51,18 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) { | |||
| } | |||
| // MarkdownRaw render raw markdown HTML | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Miscellaneous#render-a-markdown-document-in-raw-mode | |||
| func MarkdownRaw(ctx *context.APIContext) { | |||
| // swagger:route POST /markdown/raw renderMarkdownRaw | |||
| // | |||
| // Consumes: | |||
| // - text/plain | |||
| // | |||
| // Produces: | |||
| // - text/html | |||
| // | |||
| // Responses: | |||
| // 200: MarkdownRender | |||
| // 422: validationError | |||
| body, err := ctx.Req.Body().Bytes() | |||
| if err != nil { | |||
| ctx.Error(422, "", err) | |||
| @@ -12,5 +12,17 @@ import ( | |||
| // Version shows the version of the Gitea server | |||
| func Version(ctx *context.APIContext) { | |||
| // swagger:route GET /version getVersion | |||
| // | |||
| // Return Gitea running version. | |||
| // | |||
| // This show current running Gitea application version. | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: ServerVersion | |||
| ctx.JSON(200, &gitea.ServerVersion{Version: setting.AppVer}) | |||
| } | |||
| @@ -14,8 +14,16 @@ import ( | |||
| ) | |||
| // ListHooks list all hooks of a repository | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#list-hooks | |||
| func ListHooks(ctx *context.APIContext) { | |||
| // swagger:route GET /repos/{username}/{reponame}/hooks | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: apiHooks | |||
| // 500: error | |||
| hooks, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID) | |||
| if err != nil { | |||
| ctx.Error(500, "GetWebhooksByRepoID", err) | |||
| @@ -41,8 +49,20 @@ func GetHook(ctx *context.APIContext) { | |||
| } | |||
| // CreateHook create a hook for a repository | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#create-a-hook | |||
| func CreateHook(ctx *context.APIContext, form api.CreateHookOption) { | |||
| // swagger:route POST /repos/{username}/{reponame}/hooks | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: apiHook | |||
| // 422: validationError | |||
| // 500: error | |||
| if !utils.CheckCreateHookOption(ctx, &form) { | |||
| return | |||
| } | |||
| @@ -50,14 +70,33 @@ func CreateHook(ctx *context.APIContext, form api.CreateHookOption) { | |||
| } | |||
| // EditHook modify a hook of a repository | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#edit-a-hook | |||
| func EditHook(ctx *context.APIContext, form api.EditHookOption) { | |||
| // swagger:route PATCH /repos/{username}/{reponame}/hooks/{id} | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: apiHook //TODO | |||
| // 422: validationError | |||
| // 500: error | |||
| hookID := ctx.ParamsInt64(":id") | |||
| utils.EditRepoHook(ctx, &form, hookID) | |||
| } | |||
| // DeleteHook delete a hook of a repository | |||
| func DeleteHook(ctx *context.APIContext) { | |||
| // swagger:route DELETE /repos/{username}/{reponame}/hooks/{id} | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 404: notFound | |||
| // 500: error | |||
| if err := models.DeleteWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { | |||
| if models.IsErrWebhookNotExist(err) { | |||
| ctx.Status(404) | |||
| @@ -18,8 +18,16 @@ import ( | |||
| ) | |||
| // Search repositories via options | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#search-repositories | |||
| func Search(ctx *context.APIContext) { | |||
| // swagger:route GET /repos/search repoSearch | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: SearchResults | |||
| // 500: SearchError | |||
| opts := &models.SearchRepoOptions{ | |||
| Keyword: strings.Trim(ctx.Query("q"), " "), | |||
| OwnerID: ctx.QueryInt64("uid"), | |||
| @@ -33,9 +41,9 @@ func Search(ctx *context.APIContext) { | |||
| } else { | |||
| u, err := models.GetUserByID(opts.OwnerID) | |||
| if err != nil { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "ok": false, | |||
| "error": err.Error(), | |||
| ctx.JSON(500, api.SearchError{ | |||
| OK: false, | |||
| Error: err.Error(), | |||
| }) | |||
| return | |||
| } | |||
| @@ -48,9 +56,9 @@ func Search(ctx *context.APIContext) { | |||
| repos, count, err := models.SearchRepositoryByName(opts) | |||
| if err != nil { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "ok": false, | |||
| "error": err.Error(), | |||
| ctx.JSON(500, api.SearchError{ | |||
| OK: false, | |||
| Error: err.Error(), | |||
| }) | |||
| return | |||
| } | |||
| @@ -63,26 +71,26 @@ func Search(ctx *context.APIContext) { | |||
| results := make([]*api.Repository, len(repos)) | |||
| for i, repo := range repos { | |||
| if err = repo.GetOwner(); err != nil { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "ok": false, | |||
| "error": err.Error(), | |||
| ctx.JSON(500, api.SearchError{ | |||
| OK: false, | |||
| Error: err.Error(), | |||
| }) | |||
| return | |||
| } | |||
| accessMode, err := models.AccessLevel(userID, repo) | |||
| if err != nil { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "ok": false, | |||
| "error": err.Error(), | |||
| ctx.JSON(500, api.SearchError{ | |||
| OK: false, | |||
| Error: err.Error(), | |||
| }) | |||
| } | |||
| results[i] = repo.APIFormat(accessMode) | |||
| } | |||
| ctx.SetLinkHeader(int(count), setting.API.MaxResponseItems) | |||
| ctx.JSON(200, map[string]interface{}{ | |||
| "ok": true, | |||
| "data": results, | |||
| ctx.JSON(200, api.SearchResults{ | |||
| OK: true, | |||
| Data: results, | |||
| }) | |||
| } | |||
| @@ -129,6 +137,20 @@ func Create(ctx *context.APIContext, opt api.CreateRepoOption) { | |||
| // CreateOrgRepo create one repository of the organization | |||
| func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) { | |||
| // swagger:route POST /org/{org}/repos createOrgRepo | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 201: Repository | |||
| // 422: validationError | |||
| // 403: forbidden | |||
| // 500: error | |||
| org, err := models.GetOrgByName(ctx.Params(":org")) | |||
| if err != nil { | |||
| if models.IsErrUserNotExist(err) { | |||
| @@ -147,8 +169,20 @@ func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) { | |||
| } | |||
| // Migrate migrate remote git repository to gitea | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#migrate | |||
| func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) { | |||
| // swagger:route POST /repos/migrate | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 201: Repository | |||
| // 422: validationError | |||
| // 500: error | |||
| ctxUser := ctx.User | |||
| // Not equal means context user is an organization, | |||
| // or is another user/organization if current user is admin. | |||
| @@ -220,8 +254,16 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) { | |||
| } | |||
| // Get one repository | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#get | |||
| func Get(ctx *context.APIContext) { | |||
| // swagger:route GET /repos/{username}/{reponame} | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: Repository | |||
| // 500: error | |||
| repo := ctx.Repo.Repository | |||
| access, err := models.AccessLevel(ctx.User.ID, repo) | |||
| if err != nil { | |||
| @@ -233,6 +275,15 @@ func Get(ctx *context.APIContext) { | |||
| // GetByID returns a single Repository | |||
| func GetByID(ctx *context.APIContext) { | |||
| // swagger:route GET /repositories/{id} | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: Repository | |||
| // 500: error | |||
| repo, err := models.GetRepositoryByID(ctx.ParamsInt64(":id")) | |||
| if err != nil { | |||
| if models.IsErrRepoNotExist(err) { | |||
| @@ -252,8 +303,17 @@ func GetByID(ctx *context.APIContext) { | |||
| } | |||
| // Delete one repository | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#delete | |||
| func Delete(ctx *context.APIContext) { | |||
| // swagger:route DELETE /repos/{username}/{reponame} | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 403: forbidden | |||
| // 500: error | |||
| if !ctx.Repo.IsAdmin() { | |||
| ctx.Error(403, "", "Must have admin rights") | |||
| return | |||
| @@ -12,8 +12,16 @@ import ( | |||
| ) | |||
| // ListAccessTokens list all the access tokens | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users#list-access-tokens-for-a-user | |||
| func ListAccessTokens(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/tokens userGetTokens | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: AccessTokenList | |||
| // 500: error | |||
| tokens, err := models.ListAccessTokens(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.Error(500, "ListAccessTokens", err) | |||
| @@ -31,8 +39,19 @@ func ListAccessTokens(ctx *context.APIContext) { | |||
| } | |||
| // CreateAccessToken create access tokens | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users#create-a-access-token | |||
| func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption) { | |||
| // swagger:route POST /users/{username} /tokens userCreateToken | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: AccessToken | |||
| // 500: error | |||
| t := &models.AccessToken{ | |||
| UID: ctx.User.ID, | |||
| Name: form.Name, | |||
| @@ -30,12 +30,29 @@ func listUserFollowers(ctx *context.APIContext, u *models.User) { | |||
| // ListMyFollowers list all my followers | |||
| func ListMyFollowers(ctx *context.APIContext) { | |||
| // swagger:route GET /user/followers userCurrentListFollowers | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: UserList | |||
| // 500: error | |||
| listUserFollowers(ctx, ctx.User) | |||
| } | |||
| // ListFollowers list user's followers | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Followers#list-followers-of-a-user | |||
| func ListFollowers(ctx *context.APIContext) { | |||
| // swagger:route GET /users/:username/followers userListFollowers | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: UserList | |||
| // 500: error | |||
| u := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -54,12 +71,29 @@ func listUserFollowing(ctx *context.APIContext, u *models.User) { | |||
| // ListMyFollowing list all my followings | |||
| func ListMyFollowing(ctx *context.APIContext) { | |||
| // swagger:route GET /user/following userCurrentListFollowing | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: UserList | |||
| // 500: error | |||
| listUserFollowing(ctx, ctx.User) | |||
| } | |||
| // ListFollowing list user's followings | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Followers#list-users-followed-by-another-user | |||
| func ListFollowing(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/following userListFollowing | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: UserList | |||
| // 500: error | |||
| u := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -76,8 +110,13 @@ func checkUserFollowing(ctx *context.APIContext, u *models.User, followID int64) | |||
| } | |||
| // CheckMyFollowing check if the repo is followed by me | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Followers#check-if-you-are-following-a-user | |||
| func CheckMyFollowing(ctx *context.APIContext) { | |||
| // swagger:route GET /user/following/{username} userCurrentCheckFollowing | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 404: notFound | |||
| target := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -86,8 +125,13 @@ func CheckMyFollowing(ctx *context.APIContext) { | |||
| } | |||
| // CheckFollowing check if the repo is followed by user | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Followers#check-if-one-user-follows-another | |||
| func CheckFollowing(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/following/:target userCheckFollowing | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 404: notFound | |||
| u := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -100,8 +144,13 @@ func CheckFollowing(ctx *context.APIContext) { | |||
| } | |||
| // Follow follow one repository | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Followers#follow-a-user | |||
| func Follow(ctx *context.APIContext) { | |||
| // swagger:route PUT /user/following/{username} userCurrentPutFollow | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 500: error | |||
| target := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -114,8 +163,13 @@ func Follow(ctx *context.APIContext) { | |||
| } | |||
| // Unfollow unfollow one repository | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Followers#unfollow-a-user | |||
| func Unfollow(ctx *context.APIContext) { | |||
| // swagger:route DELETE /user/following/{username} userCurrentDeleteFollow | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 500: error | |||
| target := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -34,6 +34,15 @@ func listGPGKeys(ctx *context.APIContext, uid int64) { | |||
| //ListGPGKeys get the GPG key list of a user | |||
| func ListGPGKeys(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/gpg_keys userListGPGKeys | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: GPGKeyList | |||
| // 500: error | |||
| user := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -43,11 +52,30 @@ func ListGPGKeys(ctx *context.APIContext) { | |||
| //ListMyGPGKeys get the GPG key list of the logged user | |||
| func ListMyGPGKeys(ctx *context.APIContext) { | |||
| // swagger:route GET /user/gpg_keys userCurrentListGPGKeys | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: GPGKeyList | |||
| // 500: error | |||
| listGPGKeys(ctx, ctx.User.ID) | |||
| } | |||
| //GetGPGKey get the GPG key based on a id | |||
| func GetGPGKey(ctx *context.APIContext) { | |||
| // swagger:route GET /user/gpg_keys/{id} userCurrentGetGPGKey | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: GPGKey | |||
| // 404: notFound | |||
| // 500: error | |||
| key, err := models.GetGPGKeyByID(ctx.ParamsInt64(":id")) | |||
| if err != nil { | |||
| if models.IsErrGPGKeyNotExist(err) { | |||
| @@ -72,11 +100,34 @@ func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid | |||
| //CreateGPGKey associate a GPG key to the current user | |||
| func CreateGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption) { | |||
| // swagger:route POST /user/gpg_keys userCurrentPostGPGKey | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 201: GPGKey | |||
| // 422: validationError | |||
| // 500: error | |||
| CreateUserGPGKey(ctx, form, ctx.User.ID) | |||
| } | |||
| //DeleteGPGKey remove a GPG key associated to the current user | |||
| func DeleteGPGKey(ctx *context.APIContext) { | |||
| // swagger:route DELETE /user/gpg_keys/{id} userCurrentDeleteGPGKey | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 403: forbidden | |||
| // 500: error | |||
| if err := models.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | |||
| if models.IsErrGPGKeyAccessDenied(err) { | |||
| ctx.Error(403, "", "You do not have access to this key") | |||
| @@ -54,14 +54,30 @@ func listPublicKeys(ctx *context.APIContext, uid int64) { | |||
| } | |||
| // ListMyPublicKeys list all my public keys | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#list-your-public-keys | |||
| func ListMyPublicKeys(ctx *context.APIContext) { | |||
| // swagger:route GET /user/keys userCurrentListKeys | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: PublicKeyList | |||
| // 500: error | |||
| listPublicKeys(ctx, ctx.User.ID) | |||
| } | |||
| // ListPublicKeys list all user's public keys | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#list-public-keys-for-a-user | |||
| func ListPublicKeys(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/keys userListKeys | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: PublicKeyList | |||
| // 500: error | |||
| user := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -70,8 +86,17 @@ func ListPublicKeys(ctx *context.APIContext) { | |||
| } | |||
| // GetPublicKey get one public key | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#get-a-single-public-key | |||
| func GetPublicKey(ctx *context.APIContext) { | |||
| // swagger:route GET /user/keys/{id} userCurrentGetKey | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: PublicKey | |||
| // 404: notFound | |||
| // 500: error | |||
| key, err := models.GetPublicKeyByID(ctx.ParamsInt64(":id")) | |||
| if err != nil { | |||
| if models.IsErrKeyNotExist(err) { | |||
| @@ -104,14 +129,35 @@ func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid | |||
| } | |||
| // CreatePublicKey create one public key for me | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#create-a-public-key | |||
| func CreatePublicKey(ctx *context.APIContext, form api.CreateKeyOption) { | |||
| // swagger:route POST /user/keys userCurrentPostKey | |||
| // | |||
| // Consumes: | |||
| // - application/json | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 201: PublicKey | |||
| // 422: validationError | |||
| // 500: error | |||
| CreateUserPublicKey(ctx, form, ctx.User.ID) | |||
| } | |||
| // DeletePublicKey delete one public key of mine | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#delete-a-public-key | |||
| func DeletePublicKey(ctx *context.APIContext) { | |||
| // swagger:route DELETE /user/keys/{id} userCurrentDeleteKey | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 403: forbidden | |||
| // 500: error | |||
| if err := models.DeletePublicKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | |||
| if models.IsErrKeyAccessDenied(err) { | |||
| ctx.Error(403, "", "You do not have access to this key") | |||
| @@ -36,6 +36,15 @@ func listUserRepos(ctx *context.APIContext, u *models.User) { | |||
| // ListUserRepos - list the repos owned and accessible by the given user. | |||
| func ListUserRepos(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/repos userListRepos | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: RepositoryList | |||
| // 500: error | |||
| user := GetUserByParams(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| @@ -44,8 +53,16 @@ func ListUserRepos(ctx *context.APIContext) { | |||
| } | |||
| // ListMyRepos - list the repositories owned by you. | |||
| // see https://github.com/gogits/go-gogs-client/wiki/Repositories#list-your-repositories | |||
| func ListMyRepos(ctx *context.APIContext) { | |||
| // swagger:route GET /user/repos userCurrentListRepos | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: RepositoryList | |||
| // 500: error | |||
| listUserRepos(ctx, ctx.User) | |||
| } | |||
| @@ -33,6 +33,15 @@ func getStarredRepos(userID int64, private bool) ([]*api.Repository, error) { | |||
| // GetStarredRepos returns the repos that the user specified by the APIContext | |||
| // has starred | |||
| func GetStarredRepos(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/starred userListStarred | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: RepositoryList | |||
| // 500: error | |||
| user := GetUserByParams(ctx) | |||
| private := user.ID == ctx.User.ID | |||
| repos, err := getStarredRepos(user.ID, private) | |||
| @@ -44,6 +53,15 @@ func GetStarredRepos(ctx *context.APIContext) { | |||
| // GetMyStarredRepos returns the repos that the authenticated user has starred | |||
| func GetMyStarredRepos(ctx *context.APIContext) { | |||
| // swagger:route GET /user/starred userCurrentListStarred | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: RepositoryList | |||
| // 500: error | |||
| repos, err := getStarredRepos(ctx.User.ID, true) | |||
| if err != nil { | |||
| ctx.Error(500, "getStarredRepos", err) | |||
| @@ -53,6 +71,12 @@ func GetMyStarredRepos(ctx *context.APIContext) { | |||
| // IsStarring returns whether the authenticated is starring the repo | |||
| func IsStarring(ctx *context.APIContext) { | |||
| // swagger:route GET /user/starred/{username}/{reponame} userCurrentCheckStarring | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 404: notFound | |||
| if models.IsStaring(ctx.User.ID, ctx.Repo.Repository.ID) { | |||
| ctx.Status(204) | |||
| } else { | |||
| @@ -62,6 +86,12 @@ func IsStarring(ctx *context.APIContext) { | |||
| // Star the repo specified in the APIContext, as the authenticated user | |||
| func Star(ctx *context.APIContext) { | |||
| // swagger:route PUT /user/starred/{username}/{reponame} userCurrentPutStar | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 500: error | |||
| err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) | |||
| if err != nil { | |||
| ctx.Error(500, "StarRepo", err) | |||
| @@ -72,6 +102,12 @@ func Star(ctx *context.APIContext) { | |||
| // Unstar the repo specified in the APIContext, as the authenticated user | |||
| func Unstar(ctx *context.APIContext) { | |||
| // swagger:route DELETE /user/starred/{username}/{reponame} userCurrentDeleteStar | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 500: error | |||
| err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) | |||
| if err != nil { | |||
| ctx.Error(500, "StarRepo", err) | |||
| @@ -17,6 +17,15 @@ import ( | |||
| // Search search users | |||
| func Search(ctx *context.APIContext) { | |||
| // swagger:route GET /users/search userSearch | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: UserList | |||
| // 500: error | |||
| opts := &models.SearchUserOptions{ | |||
| Keyword: strings.Trim(ctx.Query("q"), " "), | |||
| Type: models.UserTypeIndividual, | |||
| @@ -56,6 +65,16 @@ func Search(ctx *context.APIContext) { | |||
| // GetInfo get user's information | |||
| func GetInfo(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username} userGet | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: User | |||
| // 404: notFound | |||
| // 500: error | |||
| u, err := models.GetUserByName(ctx.Params(":username")) | |||
| if err != nil { | |||
| if models.IsErrUserNotExist(err) { | |||
| @@ -75,5 +94,13 @@ func GetInfo(ctx *context.APIContext) { | |||
| // GetAuthenticatedUser get curent user's information | |||
| func GetAuthenticatedUser(ctx *context.APIContext) { | |||
| // swagger:route GET /user userGetCurrent | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: User | |||
| ctx.JSON(200, ctx.User.APIFormat()) | |||
| } | |||
| @@ -33,6 +33,15 @@ func getWatchedRepos(userID int64, private bool) ([]*api.Repository, error) { | |||
| // GetWatchedRepos returns the repos that the user specified in ctx is watching | |||
| func GetWatchedRepos(ctx *context.APIContext) { | |||
| // swagger:route GET /users/{username}/subscriptions userListSubscriptions | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: RepositoryList | |||
| // 500: error | |||
| user := GetUserByParams(ctx) | |||
| private := user.ID == ctx.User.ID | |||
| repos, err := getWatchedRepos(user.ID, private) | |||
| @@ -44,6 +53,15 @@ func GetWatchedRepos(ctx *context.APIContext) { | |||
| // GetMyWatchedRepos returns the repos that the authenticated user is watching | |||
| func GetMyWatchedRepos(ctx *context.APIContext) { | |||
| // swagger:route GET /user/subscriptions userCurrentListSubscriptions | |||
| // | |||
| // Produces: | |||
| // - application/json | |||
| // | |||
| // Responses: | |||
| // 200: RepositoryList | |||
| // 500: error | |||
| repos, err := getWatchedRepos(ctx.User.ID, true) | |||
| if err != nil { | |||
| ctx.Error(500, "getWatchedRepos", err) | |||
| @@ -54,6 +72,12 @@ func GetMyWatchedRepos(ctx *context.APIContext) { | |||
| // IsWatching returns whether the authenticated user is watching the repo | |||
| // specified in ctx | |||
| func IsWatching(ctx *context.APIContext) { | |||
| // swagger:route GET /repos/{username}/{reponame}/subscription userCurrentCheckSubscription | |||
| // | |||
| // Responses: | |||
| // 200: WatchInfo | |||
| // 404: notFound | |||
| if models.IsWatching(ctx.User.ID, ctx.Repo.Repository.ID) { | |||
| ctx.JSON(200, api.WatchInfo{ | |||
| Subscribed: true, | |||
| @@ -70,6 +94,12 @@ func IsWatching(ctx *context.APIContext) { | |||
| // Watch the repo specified in ctx, as the authenticated user | |||
| func Watch(ctx *context.APIContext) { | |||
| // swagger:route PUT /repos/{username}/{reponame}/subscription userCurrentPutSubscription | |||
| // | |||
| // Responses: | |||
| // 200: WatchInfo | |||
| // 500: error | |||
| err := models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) | |||
| if err != nil { | |||
| ctx.Error(500, "WatchRepo", err) | |||
| @@ -88,6 +118,12 @@ func Watch(ctx *context.APIContext) { | |||
| // Unwatch the repo specified in ctx, as the authenticated user | |||
| func Unwatch(ctx *context.APIContext) { | |||
| // swagger:route DELETE /repos/{username}/{reponame}/subscription userCurrentDeleteSubscription | |||
| // | |||
| // Responses: | |||
| // 204: empty | |||
| // 500: error | |||
| err := models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) | |||
| if err != nil { | |||
| ctx.Error(500, "UnwatchRepo", err) | |||
| @@ -20,6 +20,8 @@ import ( | |||
| const ( | |||
| // tplHome home page template | |||
| tplHome base.TplName = "home" | |||
| // tplSwagger swagger page template | |||
| tplSwagger base.TplName = "swagger" | |||
| // tplExploreRepos explore repositories page template | |||
| tplExploreRepos base.TplName = "explore/repos" | |||
| // tplExploreUsers explore users page template | |||
| @@ -51,6 +53,11 @@ func Home(ctx *context.Context) { | |||
| ctx.HTML(200, tplHome) | |||
| } | |||
| // Swagger render swagger-ui page | |||
| func Swagger(ctx *context.Context) { | |||
| ctx.HTML(200, tplSwagger) | |||
| } | |||
| // RepoSearchOptions when calling search repositories | |||
| type RepoSearchOptions struct { | |||
| Ranger func(*models.SearchRepoOptions) (models.RepositoryList, int64, error) | |||
| @@ -146,6 +146,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| return "" | |||
| }) | |||
| m.Get("/", ignSignIn, routers.Home) | |||
| m.Get("/swagger", ignSignIn, routers.Swagger) | |||
| m.Group("/explore", func() { | |||
| m.Get("", func(ctx *context.Context) { | |||
| ctx.Redirect(setting.AppSubURL + "/explore/repos") | |||
| @@ -23,6 +23,7 @@ | |||
| </div> | |||
| </div> | |||
| <a href="{{AppSubUrl}}/assets/librejs/librejs.html" data-jslicense="1">Javascript licenses</a> | |||
| <a href="{{AppSubUrl}}/swagger">API</a> | |||
| <a target="_blank" rel="noopener" href="https://gitea.io">{{.i18n.Tr "website"}}</a> | |||
| {{if (or .ShowFooterVersion .PageIsAdmin)}}<span class="version">{{GoVer}}</span>{{end}} | |||
| </div> | |||
| @@ -0,0 +1,93 @@ | |||
| <!-- HTML for static distribution bundle build --> | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Swagger UI</title> | |||
| <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet"> | |||
| <link rel="stylesheet" type="text/css" href="{{AppSubUrl}}/assets/swagger-ui/swagger-ui.css" > | |||
| <link rel="icon" type="image/png" href="{{AppSubUrl}}/assets/swagger-ui/favicon-32x32.png" sizes="32x32" /> | |||
| <link rel="icon" type="image/png" href="{{AppSubUrl}}/assets/swagger-ui/favicon-16x16.png" sizes="16x16" /> | |||
| <style> | |||
| html | |||
| { | |||
| box-sizing: border-box; | |||
| overflow: -moz-scrollbars-vertical; | |||
| overflow-y: scroll; | |||
| } | |||
| *, | |||
| *:before, | |||
| *:after | |||
| { | |||
| box-sizing: inherit; | |||
| } | |||
| body { | |||
| margin:0; | |||
| background: #fafafa; | |||
| } | |||
| </style> | |||
| </head> | |||
| <body> | |||
| <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0"> | |||
| <defs> | |||
| <symbol viewBox="0 0 20 20" id="unlocked"> | |||
| <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="locked"> | |||
| <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="close"> | |||
| <path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="large-arrow"> | |||
| <path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 20 20" id="large-arrow-down"> | |||
| <path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 24 24" id="jump-to"> | |||
| <path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/> | |||
| </symbol> | |||
| <symbol viewBox="0 0 24 24" id="expand"> | |||
| <path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/> | |||
| </symbol> | |||
| </defs> | |||
| </svg> | |||
| <div id="swagger-ui"></div> | |||
| <script src="{{AppSubUrl}}/assets/swagger-ui/swagger-ui-bundle.js"> </script> | |||
| <script src="{{AppSubUrl}}/assets/swagger-ui/swagger-ui-standalone-preset.js"> </script> | |||
| <script> | |||
| window.onload = function() { | |||
| // Build a system | |||
| const ui = SwaggerUIBundle({ | |||
| url: "{{AppUrl}}swagger.v1.json", | |||
| dom_id: '#swagger-ui', | |||
| presets: [ | |||
| SwaggerUIBundle.presets.apis, | |||
| SwaggerUIStandalonePreset | |||
| ], | |||
| plugins: [ | |||
| SwaggerUIBundle.plugins.DownloadUrl | |||
| ], | |||
| layout: "StandaloneLayout" | |||
| }) | |||
| window.ui = ui | |||
| } | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @@ -4,15 +4,47 @@ | |||
| package gitea | |||
| // SearchResults results of search | |||
| // swagger:response SearchResults | |||
| type SearchResults struct { | |||
| OK bool `json:"ok"` | |||
| Data []*Repository `json:"data"` | |||
| } | |||
| // SearchError error of failing search | |||
| // swagger:response SearchError | |||
| type SearchError struct { | |||
| OK bool `json:"ok"` | |||
| Error string `json:"error"` | |||
| } | |||
| // MarkdownOption markdown options | |||
| // swagger:parameters renderMarkdown | |||
| type MarkdownOption struct { | |||
| Text string | |||
| Mode string | |||
| // Text markdown to render | |||
| // | |||
| // in: body | |||
| Text string | |||
| // Mode to render | |||
| // | |||
| // in: body | |||
| Mode string | |||
| // Context to render | |||
| // | |||
| // in: body | |||
| Context string | |||
| Wiki bool | |||
| // Is it a wiki page ? | |||
| // | |||
| // in: body | |||
| Wiki bool | |||
| } | |||
| // MarkdownRender is a rendered markdown document | |||
| // swagger:response MarkdownRender | |||
| type MarkdownRender string | |||
| // ServerVersion wraps the version of the server | |||
| // swagger:response ServerVersion | |||
| type ServerVersion struct { | |||
| Version string | |||
| } | |||
| @@ -19,6 +19,7 @@ type Permission struct { | |||
| } | |||
| // Repository represents a API repository. | |||
| // swagger:response Repository | |||
| type Repository struct { | |||
| ID int64 `json:"id"` | |||
| Owner *User `json:"owner"` | |||
| @@ -42,6 +43,10 @@ type Repository struct { | |||
| Permissions *Permission `json:"permissions,omitempty"` | |||
| } | |||
| // RepositoryList represents a list of API repository. | |||
| // swagger:response RepositoryList | |||
| type RepositoryList []*Repository | |||
| // ListMyRepos lists all repositories for the authenticated user that has access to. | |||
| func (c *Client) ListMyRepos() ([]*Repository, error) { | |||
| repos := make([]*Repository, 0, 10) | |||
| @@ -61,14 +66,37 @@ func (c *Client) ListOrgRepos(org string) ([]*Repository, error) { | |||
| } | |||
| // CreateRepoOption options when creating repository | |||
| //swagger:parameters createOrgRepo | |||
| type CreateRepoOption struct { | |||
| Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"` | |||
| // Name of the repository to create | |||
| // | |||
| // in: body | |||
| // unique: true | |||
| Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"` | |||
| // Description of the repository to create | |||
| // | |||
| // in: body | |||
| Description string `json:"description" binding:"MaxSize(255)"` | |||
| Private bool `json:"private"` | |||
| AutoInit bool `json:"auto_init"` | |||
| Gitignores string `json:"gitignores"` | |||
| License string `json:"license"` | |||
| Readme string `json:"readme"` | |||
| // Is the repository to create private ? | |||
| // | |||
| // in: body | |||
| Private bool `json:"private"` | |||
| // Init the repository to create ? | |||
| // | |||
| // in: body | |||
| AutoInit bool `json:"auto_init"` | |||
| // Gitignores to use | |||
| // | |||
| // in: body | |||
| Gitignores string `json:"gitignores"` | |||
| // License to use | |||
| // | |||
| // in: body | |||
| License string `json:"license"` | |||
| // Readme of the repository to create | |||
| // | |||
| // in: body | |||
| Readme string `json:"readme"` | |||
| } | |||
| // CreateRepo creates a repository for authenticated user. | |||
| @@ -34,9 +34,20 @@ func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, error | |||
| } | |||
| // CreateKeyOption options when create deploy key | |||
| // swagger:parameters userCurrentPostKey | |||
| type CreateKeyOption struct { | |||
| // Title of the key to add | |||
| // | |||
| // in: body | |||
| // required: true | |||
| // unique: true | |||
| Title string `json:"title" binding:"Required"` | |||
| Key string `json:"key" binding:"Required"` | |||
| // An armored SSH key to add | |||
| // | |||
| // in: body | |||
| // required: true | |||
| // unique: true | |||
| Key string `json:"key" binding:"Required"` | |||
| } | |||
| // CreateDeployKey options when create one deploy key | |||
| @@ -11,6 +11,7 @@ import ( | |||
| ) | |||
| // WatchInfo represents a API watch status of one repository | |||
| // swagger:response WatchInfo | |||
| type WatchInfo struct { | |||
| Subscribed bool `json:"subscribed"` | |||
| Ignored bool `json:"ignored"` | |||
| @@ -10,6 +10,7 @@ import ( | |||
| ) | |||
| // User represents a API user. | |||
| // swagger:response User | |||
| type User struct { | |||
| ID int64 `json:"id"` | |||
| UserName string `json:"login"` | |||
| @@ -18,6 +19,10 @@ type User struct { | |||
| AvatarURL string `json:"avatar_url"` | |||
| } | |||
| // UserList represents a list of API user. | |||
| // swagger:response UserList | |||
| type UserList []*User | |||
| // MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility | |||
| func (u User) MarshalJSON() ([]byte, error) { | |||
| // Re-declaring User to avoid recursion | |||
| @@ -18,11 +18,16 @@ func BasicAuthEncode(user, pass string) string { | |||
| } | |||
| // AccessToken represents a API access token. | |||
| // swagger:response AccessToken | |||
| type AccessToken struct { | |||
| Name string `json:"name"` | |||
| Sha1 string `json:"sha1"` | |||
| } | |||
| // AccessTokenList represents a list of API access token. | |||
| // swagger:response AccessTokenList | |||
| type AccessTokenList []*AccessToken | |||
| // ListAccessTokens lista all the access tokens of user | |||
| func (c *Client) ListAccessTokens(user, pass string) ([]*AccessToken, error) { | |||
| tokens := make([]*AccessToken, 0, 10) | |||
| @@ -31,6 +36,7 @@ func (c *Client) ListAccessTokens(user, pass string) ([]*AccessToken, error) { | |||
| } | |||
| // CreateAccessTokenOption options when create access token | |||
| // swagger:parameters userCreateToken | |||
| type CreateAccessTokenOption struct { | |||
| Name string `json:"name" binding:"Required"` | |||
| } | |||
| @@ -11,7 +11,12 @@ import ( | |||
| "time" | |||
| ) | |||
| // GPGKeyList represents a list of GPGKey | |||
| // swagger:response GPGKeyList | |||
| type GPGKeyList []*GPGKey | |||
| // GPGKey a user GPG key to sign commit and tag in repository | |||
| // swagger:response GPGKey | |||
| type GPGKey struct { | |||
| ID int64 `json:"id"` | |||
| PrimaryKeyID string `json:"primary_key_id"` | |||
| @@ -28,13 +33,20 @@ type GPGKey struct { | |||
| } | |||
| // GPGKeyEmail a email attache to a GPGKey | |||
| // swagger:model GPGKeyEmail | |||
| type GPGKeyEmail struct { | |||
| Email string `json:"email"` | |||
| Verified bool `json:"verified"` | |||
| } | |||
| // CreateGPGKeyOption options create user GPG key | |||
| // swagger:parameters userCurrentPostGPGKey | |||
| type CreateGPGKeyOption struct { | |||
| // An armored GPG key to add | |||
| // | |||
| // in: body | |||
| // required: true | |||
| // unique: true | |||
| ArmoredKey string `json:"armored_public_key" binding:"Required"` | |||
| } | |||
| @@ -11,7 +11,12 @@ import ( | |||
| "time" | |||
| ) | |||
| // PublicKeyList represents a list of PublicKey | |||
| // swagger:response PublicKeyList | |||
| type PublicKeyList []*PublicKey | |||
| // PublicKey publickey is a user key to push code to repository | |||
| // swagger:response PublicKey | |||
| type PublicKey struct { | |||
| ID int64 `json:"id"` | |||
| Key string `json:"key"` | |||
| @@ -9,10 +9,10 @@ | |||
| "revisionTime": "2017-04-26T13:12:33Z" | |||
| }, | |||
| { | |||
| "checksumSHA1": "xACJysFK1sK/D5655EpU48mw2vo=", | |||
| "checksumSHA1": "vdziKobpPIkU/dLvSI8n7eWrIIE=", | |||
| "path": "code.gitea.io/sdk/gitea", | |||
| "revision": "0c3a0b0b5ea6edfb5bf3a4c81ebda6d207ecdfad", | |||
| "revisionTime": "2017-04-27T00:40:26Z" | |||
| "revision": "d2f87fd3f9f2887b9f15112cec8d7f53b2825147", | |||
| "revisionTime": "2017-04-30T15:33:16Z" | |||
| }, | |||
| { | |||
| "checksumSHA1": "IyfS7Rbl6OgR83QR7TOfKdDCq+M=", | |||