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

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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. }