2015-11-18 21:21:47 -05:00
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2015-12-04 17:16:42 -05:00
package repo
2015-11-18 21:21:47 -05:00
import (
"fmt"
2016-11-10 17:24:48 +01:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers/api/v1/convert"
2018-03-29 21:32:40 +08:00
api "code.gitea.io/sdk/gitea"
2015-11-18 21:21:47 -05:00
)
2018-11-01 03:40:49 +00:00
// appendPrivateInformation appends the owner and key type information to api.PublicKey
func appendPrivateInformation ( apiKey * api . DeployKey , key * models . DeployKey , repository * models . Repository ) ( * api . DeployKey , error ) {
apiKey . ReadOnly = key . Mode == models . AccessModeRead
if repository . ID == key . RepoID {
apiKey . Repository = repository . APIFormat ( key . Mode )
} else {
repo , err := models . GetRepositoryByID ( key . RepoID )
if err != nil {
return apiKey , err
}
apiKey . Repository = repo . APIFormat ( key . Mode )
}
return apiKey , nil
}
2015-11-18 21:21:47 -05:00
func composeDeployKeysAPILink ( repoPath string ) string {
2016-11-27 18:14:25 +08:00
return setting . AppURL + "api/v1/repos/" + repoPath + "/keys/"
2015-11-18 21:21:47 -05:00
}
2016-11-24 15:04:31 +08:00
// ListDeployKeys list all the deploy keys of a repository
2016-03-13 18:49:16 -04:00
func ListDeployKeys ( ctx * context . APIContext ) {
2017-11-12 23:02:25 -08:00
// swagger:operation GET /repos/{owner}/{repo}/keys repository repoListKeys
// ---
// summary: List a repository's keys
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
2018-11-01 03:40:49 +00:00
// - name: key_id
// in: query
// description: the key_id to search for
// type: integer
// - name: fingerprint
// in: query
// description: fingerprint of the key
// type: string
2017-11-12 23:02:25 -08:00
// responses:
// "200":
// "$ref": "#/responses/DeployKeyList"
2018-11-01 03:40:49 +00:00
var keys [ ] * models . DeployKey
var err error
fingerprint := ctx . Query ( "fingerprint" )
keyID := ctx . QueryInt64 ( "key_id" )
if fingerprint != "" || keyID != 0 {
keys , err = models . SearchDeployKeys ( ctx . Repo . Repository . ID , keyID , fingerprint )
} else {
keys , err = models . ListDeployKeys ( ctx . Repo . Repository . ID )
}
2015-11-18 21:21:47 -05:00
if err != nil {
2016-03-13 18:49:16 -04:00
ctx . Error ( 500 , "ListDeployKeys" , err )
2015-11-18 21:21:47 -05:00
return
}
apiLink := composeDeployKeysAPILink ( ctx . Repo . Owner . Name + "/" + ctx . Repo . Repository . Name )
apiKeys := make ( [ ] * api . DeployKey , len ( keys ) )
for i := range keys {
if err = keys [ i ] . GetContent ( ) ; err != nil {
2016-03-13 18:49:16 -04:00
ctx . Error ( 500 , "GetContent" , err )
2015-11-18 21:21:47 -05:00
return
}
2016-03-13 23:20:22 -04:00
apiKeys [ i ] = convert . ToDeployKey ( apiLink , keys [ i ] )
2018-11-01 03:40:49 +00:00
if ctx . User . IsAdmin || ( ( ctx . Repo . Repository . ID == keys [ i ] . RepoID ) && ( ctx . User . ID == ctx . Repo . Owner . ID ) ) {
apiKeys [ i ] , _ = appendPrivateInformation ( apiKeys [ i ] , keys [ i ] , ctx . Repo . Repository )
}
2015-11-18 21:21:47 -05:00
}
ctx . JSON ( 200 , & apiKeys )
}
2016-11-24 15:04:31 +08:00
// GetDeployKey get a deploy key by id
2016-03-13 18:49:16 -04:00
func GetDeployKey ( ctx * context . APIContext ) {
2017-11-12 23:02:25 -08:00
// swagger:operation GET /repos/{owner}/{repo}/keys/{id} repository repoGetKey
// ---
// summary: Get a repository's key by id
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: id
// in: path
// description: id of the key to get
// type: integer
2018-10-21 04:40:42 +01:00
// format: int64
2017-11-12 23:02:25 -08:00
// required: true
// responses:
// "200":
// "$ref": "#/responses/DeployKey"
2015-11-18 21:21:47 -05:00
key , err := models . GetDeployKeyByID ( ctx . ParamsInt64 ( ":id" ) )
if err != nil {
if models . IsErrDeployKeyNotExist ( err ) {
2016-03-13 18:49:16 -04:00
ctx . Status ( 404 )
2015-11-18 21:21:47 -05:00
} else {
2016-03-13 18:49:16 -04:00
ctx . Error ( 500 , "GetDeployKeyByID" , err )
2015-11-18 21:21:47 -05:00
}
return
}
if err = key . GetContent ( ) ; err != nil {
2016-03-13 18:49:16 -04:00
ctx . Error ( 500 , "GetContent" , err )
2015-11-18 21:21:47 -05:00
return
}
apiLink := composeDeployKeysAPILink ( ctx . Repo . Owner . Name + "/" + ctx . Repo . Repository . Name )
2018-11-01 03:40:49 +00:00
apiKey := convert . ToDeployKey ( apiLink , key )
if ctx . User . IsAdmin || ( ( ctx . Repo . Repository . ID == key . RepoID ) && ( ctx . User . ID == ctx . Repo . Owner . ID ) ) {
apiKey , _ = appendPrivateInformation ( apiKey , key , ctx . Repo . Repository )
}
ctx . JSON ( 200 , apiKey )
2015-11-18 21:21:47 -05:00
}
2016-11-24 15:04:31 +08:00
// HandleCheckKeyStringError handle check key error
2016-03-13 18:49:16 -04:00
func HandleCheckKeyStringError ( ctx * context . APIContext , err error ) {
2017-11-21 04:49:33 +01:00
if models . IsErrSSHDisabled ( err ) {
ctx . Error ( 422 , "" , "SSH is disabled" )
} else if models . IsErrKeyUnableVerify ( err ) {
2016-03-13 18:49:16 -04:00
ctx . Error ( 422 , "" , "Unable to verify key content" )
2015-12-03 00:24:37 -05:00
} else {
2016-03-13 18:49:16 -04:00
ctx . Error ( 422 , "" , fmt . Errorf ( "Invalid key content: %v" , err ) )
2015-12-03 00:24:37 -05:00
}
}
2016-11-24 15:04:31 +08:00
// HandleAddKeyError handle add key error
2016-03-13 18:49:16 -04:00
func HandleAddKeyError ( ctx * context . APIContext , err error ) {
2015-12-03 00:24:37 -05:00
switch {
2019-02-03 23:56:53 +00:00
case models . IsErrDeployKeyAlreadyExist ( err ) :
ctx . Error ( 422 , "" , "This key has already been added to this repository" )
2015-12-03 00:24:37 -05:00
case models . IsErrKeyAlreadyExist ( err ) :
2016-03-13 18:49:16 -04:00
ctx . Error ( 422 , "" , "Key content has been used as non-deploy key" )
2015-12-03 00:24:37 -05:00
case models . IsErrKeyNameAlreadyUsed ( err ) :
2016-03-13 18:49:16 -04:00
ctx . Error ( 422 , "" , "Key title has been used" )
2015-12-03 00:24:37 -05:00
default :
2016-03-13 18:49:16 -04:00
ctx . Error ( 500 , "AddKey" , err )
2015-12-03 00:24:37 -05:00
}
}
2016-11-24 15:04:31 +08:00
// CreateDeployKey create deploy key for a repository
2016-03-13 18:49:16 -04:00
func CreateDeployKey ( ctx * context . APIContext , form api . CreateKeyOption ) {
2017-11-12 23:02:25 -08:00
// swagger:operation POST /repos/{owner}/{repo}/keys repository repoCreateKey
// ---
// summary: Add a key to a repository
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/CreateKeyOption"
// responses:
// "201":
// "$ref": "#/responses/DeployKey"
2015-11-18 21:21:47 -05:00
content , err := models . CheckPublicKeyString ( form . Key )
if err != nil {
2015-12-04 17:16:42 -05:00
HandleCheckKeyStringError ( ctx , err )
2015-11-18 21:21:47 -05:00
return
}
2018-01-07 00:55:53 +02:00
key , err := models . AddDeployKey ( ctx . Repo . Repository . ID , form . Title , content , form . ReadOnly )
2015-11-18 21:21:47 -05:00
if err != nil {
2015-12-04 17:16:42 -05:00
HandleAddKeyError ( ctx , err )
2015-11-18 21:21:47 -05:00
return
}
key . Content = content
apiLink := composeDeployKeysAPILink ( ctx . Repo . Owner . Name + "/" + ctx . Repo . Repository . Name )
2016-03-13 23:20:22 -04:00
ctx . JSON ( 201 , convert . ToDeployKey ( apiLink , key ) )
2015-11-18 21:21:47 -05:00
}
2016-11-24 15:04:31 +08:00
// DeleteDeploykey delete deploy key for a repository
2016-03-13 18:49:16 -04:00
func DeleteDeploykey ( ctx * context . APIContext ) {
2017-11-12 23:02:25 -08:00
// swagger:operation DELETE /repos/{owner}/{repo}/keys/{id} repository repoDeleteKey
// ---
// summary: Delete a key from a repository
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: id
// in: path
// description: id of the key to delete
// type: integer
2018-10-21 04:40:42 +01:00
// format: int64
2017-11-12 23:02:25 -08:00
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
2015-12-03 00:24:37 -05:00
if err := models . DeleteDeployKey ( ctx . User , ctx . ParamsInt64 ( ":id" ) ) ; err != nil {
if models . IsErrKeyAccessDenied ( err ) {
2016-03-13 18:49:16 -04:00
ctx . Error ( 403 , "" , "You do not have access to this key" )
2015-12-03 00:24:37 -05:00
} else {
2016-03-13 18:49:16 -04:00
ctx . Error ( 500 , "DeleteDeployKey" , err )
2015-12-03 00:24:37 -05:00
}
2015-11-18 21:21:47 -05:00
return
}
ctx . Status ( 204 )
}