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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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/convert"
  10. "code.gitea.io/gitea/modules/setting"
  11. api "code.gitea.io/gitea/modules/structs"
  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.NotFound()
  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.IsErrDeployKeyAlreadyExist(err):
  147. ctx.Error(422, "", "This key has already been added to this repository")
  148. case models.IsErrKeyAlreadyExist(err):
  149. ctx.Error(422, "", "Key content has been used as non-deploy key")
  150. case models.IsErrKeyNameAlreadyUsed(err):
  151. ctx.Error(422, "", "Key title has been used")
  152. default:
  153. ctx.Error(500, "AddKey", err)
  154. }
  155. }
  156. // CreateDeployKey create deploy key for a repository
  157. func CreateDeployKey(ctx *context.APIContext, form api.CreateKeyOption) {
  158. // swagger:operation POST /repos/{owner}/{repo}/keys repository repoCreateKey
  159. // ---
  160. // summary: Add a key to a repository
  161. // consumes:
  162. // - application/json
  163. // produces:
  164. // - application/json
  165. // parameters:
  166. // - name: owner
  167. // in: path
  168. // description: owner of the repo
  169. // type: string
  170. // required: true
  171. // - name: repo
  172. // in: path
  173. // description: name of the repo
  174. // type: string
  175. // required: true
  176. // - name: body
  177. // in: body
  178. // schema:
  179. // "$ref": "#/definitions/CreateKeyOption"
  180. // responses:
  181. // "201":
  182. // "$ref": "#/responses/DeployKey"
  183. content, err := models.CheckPublicKeyString(form.Key)
  184. if err != nil {
  185. HandleCheckKeyStringError(ctx, err)
  186. return
  187. }
  188. key, err := models.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, form.ReadOnly)
  189. if err != nil {
  190. HandleAddKeyError(ctx, err)
  191. return
  192. }
  193. key.Content = content
  194. apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
  195. ctx.JSON(201, convert.ToDeployKey(apiLink, key))
  196. }
  197. // DeleteDeploykey delete deploy key for a repository
  198. func DeleteDeploykey(ctx *context.APIContext) {
  199. // swagger:operation DELETE /repos/{owner}/{repo}/keys/{id} repository repoDeleteKey
  200. // ---
  201. // summary: Delete a key from a repository
  202. // parameters:
  203. // - name: owner
  204. // in: path
  205. // description: owner of the repo
  206. // type: string
  207. // required: true
  208. // - name: repo
  209. // in: path
  210. // description: name of the repo
  211. // type: string
  212. // required: true
  213. // - name: id
  214. // in: path
  215. // description: id of the key to delete
  216. // type: integer
  217. // format: int64
  218. // required: true
  219. // responses:
  220. // "204":
  221. // "$ref": "#/responses/empty"
  222. if err := models.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
  223. if models.IsErrKeyAccessDenied(err) {
  224. ctx.Error(403, "", "You do not have access to this key")
  225. } else {
  226. ctx.Error(500, "DeleteDeployKey", err)
  227. }
  228. return
  229. }
  230. ctx.Status(204)
  231. }