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

key.go 6.8KB

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