You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

key.go 7.6 kB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "fmt"
  7. "net/http"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/context"
  10. "code.gitea.io/gitea/modules/convert"
  11. "code.gitea.io/gitea/modules/setting"
  12. api "code.gitea.io/gitea/modules/structs"
  13. )
  14. // appendPrivateInformation appends the owner and key type information to api.PublicKey
  15. func appendPrivateInformation(apiKey *api.DeployKey, key *models.DeployKey, repository *models.Repository) (*api.DeployKey, error) {
  16. apiKey.ReadOnly = key.Mode == models.AccessModeRead
  17. if repository.ID == key.RepoID {
  18. apiKey.Repository = repository.APIFormat(key.Mode)
  19. } else {
  20. repo, err := models.GetRepositoryByID(key.RepoID)
  21. if err != nil {
  22. return apiKey, err
  23. }
  24. apiKey.Repository = repo.APIFormat(key.Mode)
  25. }
  26. return apiKey, nil
  27. }
  28. func composeDeployKeysAPILink(repoPath string) string {
  29. return setting.AppURL + "api/v1/repos/" + repoPath + "/keys/"
  30. }
  31. // ListDeployKeys list all the deploy keys of a repository
  32. func ListDeployKeys(ctx *context.APIContext) {
  33. // swagger:operation GET /repos/{owner}/{repo}/keys repository repoListKeys
  34. // ---
  35. // summary: List a repository's keys
  36. // produces:
  37. // - application/json
  38. // parameters:
  39. // - name: owner
  40. // in: path
  41. // description: owner of the repo
  42. // type: string
  43. // required: true
  44. // - name: repo
  45. // in: path
  46. // description: name of the repo
  47. // type: string
  48. // required: true
  49. // - name: key_id
  50. // in: query
  51. // description: the key_id to search for
  52. // type: integer
  53. // - name: fingerprint
  54. // in: query
  55. // description: fingerprint of the key
  56. // type: string
  57. // responses:
  58. // "200":
  59. // "$ref": "#/responses/DeployKeyList"
  60. var keys []*models.DeployKey
  61. var err error
  62. fingerprint := ctx.Query("fingerprint")
  63. keyID := ctx.QueryInt64("key_id")
  64. if fingerprint != "" || keyID != 0 {
  65. keys, err = models.SearchDeployKeys(ctx.Repo.Repository.ID, keyID, fingerprint)
  66. } else {
  67. keys, err = models.ListDeployKeys(ctx.Repo.Repository.ID)
  68. }
  69. if err != nil {
  70. ctx.Error(http.StatusInternalServerError, "ListDeployKeys", err)
  71. return
  72. }
  73. apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
  74. apiKeys := make([]*api.DeployKey, len(keys))
  75. for i := range keys {
  76. if err = keys[i].GetContent(); err != nil {
  77. ctx.Error(http.StatusInternalServerError, "GetContent", err)
  78. return
  79. }
  80. apiKeys[i] = convert.ToDeployKey(apiLink, keys[i])
  81. if ctx.User.IsAdmin || ((ctx.Repo.Repository.ID == keys[i].RepoID) && (ctx.User.ID == ctx.Repo.Owner.ID)) {
  82. apiKeys[i], _ = appendPrivateInformation(apiKeys[i], keys[i], ctx.Repo.Repository)
  83. }
  84. }
  85. ctx.JSON(http.StatusOK, &apiKeys)
  86. }
  87. // GetDeployKey get a deploy key by id
  88. func GetDeployKey(ctx *context.APIContext) {
  89. // swagger:operation GET /repos/{owner}/{repo}/keys/{id} repository repoGetKey
  90. // ---
  91. // summary: Get a repository's key by id
  92. // produces:
  93. // - application/json
  94. // parameters:
  95. // - name: owner
  96. // in: path
  97. // description: owner of the repo
  98. // type: string
  99. // required: true
  100. // - name: repo
  101. // in: path
  102. // description: name of the repo
  103. // type: string
  104. // required: true
  105. // - name: id
  106. // in: path
  107. // description: id of the key to get
  108. // type: integer
  109. // format: int64
  110. // required: true
  111. // responses:
  112. // "200":
  113. // "$ref": "#/responses/DeployKey"
  114. key, err := models.GetDeployKeyByID(ctx.ParamsInt64(":id"))
  115. if err != nil {
  116. if models.IsErrDeployKeyNotExist(err) {
  117. ctx.NotFound()
  118. } else {
  119. ctx.Error(http.StatusInternalServerError, "GetDeployKeyByID", err)
  120. }
  121. return
  122. }
  123. if err = key.GetContent(); err != nil {
  124. ctx.Error(http.StatusInternalServerError, "GetContent", err)
  125. return
  126. }
  127. apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
  128. apiKey := convert.ToDeployKey(apiLink, key)
  129. if ctx.User.IsAdmin || ((ctx.Repo.Repository.ID == key.RepoID) && (ctx.User.ID == ctx.Repo.Owner.ID)) {
  130. apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Repo.Repository)
  131. }
  132. ctx.JSON(http.StatusOK, apiKey)
  133. }
  134. // HandleCheckKeyStringError handle check key error
  135. func HandleCheckKeyStringError(ctx *context.APIContext, err error) {
  136. if models.IsErrSSHDisabled(err) {
  137. ctx.Error(http.StatusUnprocessableEntity, "", "SSH is disabled")
  138. } else if models.IsErrKeyUnableVerify(err) {
  139. ctx.Error(http.StatusUnprocessableEntity, "", "Unable to verify key content")
  140. } else {
  141. ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("Invalid key content: %v", err))
  142. }
  143. }
  144. // HandleAddKeyError handle add key error
  145. func HandleAddKeyError(ctx *context.APIContext, err error) {
  146. switch {
  147. case models.IsErrDeployKeyAlreadyExist(err):
  148. ctx.Error(http.StatusUnprocessableEntity, "", "This key has already been added to this repository")
  149. case models.IsErrKeyAlreadyExist(err):
  150. ctx.Error(http.StatusUnprocessableEntity, "", "Key content has been used as non-deploy key")
  151. case models.IsErrKeyNameAlreadyUsed(err):
  152. ctx.Error(http.StatusUnprocessableEntity, "", "Key title has been used")
  153. default:
  154. ctx.Error(http.StatusInternalServerError, "AddKey", err)
  155. }
  156. }
  157. // CreateDeployKey create deploy key for a repository
  158. func CreateDeployKey(ctx *context.APIContext, form api.CreateKeyOption) {
  159. // swagger:operation POST /repos/{owner}/{repo}/keys repository repoCreateKey
  160. // ---
  161. // summary: Add a key to a repository
  162. // consumes:
  163. // - application/json
  164. // produces:
  165. // - application/json
  166. // parameters:
  167. // - name: owner
  168. // in: path
  169. // description: owner of the repo
  170. // type: string
  171. // required: true
  172. // - name: repo
  173. // in: path
  174. // description: name of the repo
  175. // type: string
  176. // required: true
  177. // - name: body
  178. // in: body
  179. // schema:
  180. // "$ref": "#/definitions/CreateKeyOption"
  181. // responses:
  182. // "201":
  183. // "$ref": "#/responses/DeployKey"
  184. // "422":
  185. // "$ref": "#/responses/validationError"
  186. content, err := models.CheckPublicKeyString(form.Key)
  187. if err != nil {
  188. HandleCheckKeyStringError(ctx, err)
  189. return
  190. }
  191. key, err := models.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, form.ReadOnly)
  192. if err != nil {
  193. HandleAddKeyError(ctx, err)
  194. return
  195. }
  196. key.Content = content
  197. apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
  198. ctx.JSON(http.StatusCreated, convert.ToDeployKey(apiLink, key))
  199. }
  200. // DeleteDeploykey delete deploy key for a repository
  201. func DeleteDeploykey(ctx *context.APIContext) {
  202. // swagger:operation DELETE /repos/{owner}/{repo}/keys/{id} repository repoDeleteKey
  203. // ---
  204. // summary: Delete a key from a repository
  205. // parameters:
  206. // - name: owner
  207. // in: path
  208. // description: owner of the repo
  209. // type: string
  210. // required: true
  211. // - name: repo
  212. // in: path
  213. // description: name of the repo
  214. // type: string
  215. // required: true
  216. // - name: id
  217. // in: path
  218. // description: id of the key to delete
  219. // type: integer
  220. // format: int64
  221. // required: true
  222. // responses:
  223. // "204":
  224. // "$ref": "#/responses/empty"
  225. // "403":
  226. // "$ref": "#/responses/forbidden"
  227. if err := models.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
  228. if models.IsErrKeyAccessDenied(err) {
  229. ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
  230. } else {
  231. ctx.Error(http.StatusInternalServerError, "DeleteDeployKey", err)
  232. }
  233. return
  234. }
  235. ctx.Status(http.StatusNoContent)
  236. }