summaryrefslogtreecommitdiffstats
path: root/routers/api/v1/user/key.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--routers/api/v1/user/key.go317
1 files changed, 317 insertions, 0 deletions
diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go
new file mode 100644
index 0000000..1b4ba0a
--- /dev/null
+++ b/routers/api/v1/user/key.go
@@ -0,0 +1,317 @@
+// Copyright 2015 The Gogs Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package user
+
+import (
+ std_ctx "context"
+ "fmt"
+ "net/http"
+
+ asymkey_model "code.gitea.io/gitea/models/asymkey"
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/perm"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/setting"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/routers/api/v1/repo"
+ "code.gitea.io/gitea/routers/api/v1/utils"
+ asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/convert"
+)
+
+// appendPrivateInformation appends the owner and key type information to api.PublicKey
+func appendPrivateInformation(ctx std_ctx.Context, apiKey *api.PublicKey, key *asymkey_model.PublicKey, defaultUser *user_model.User) (*api.PublicKey, error) {
+ if key.Type == asymkey_model.KeyTypeDeploy {
+ apiKey.KeyType = "deploy"
+ } else if key.Type == asymkey_model.KeyTypeUser {
+ apiKey.KeyType = "user"
+
+ if defaultUser.ID == key.OwnerID {
+ apiKey.Owner = convert.ToUser(ctx, defaultUser, defaultUser)
+ } else {
+ user, err := user_model.GetUserByID(ctx, key.OwnerID)
+ if err != nil {
+ return apiKey, err
+ }
+ apiKey.Owner = convert.ToUser(ctx, user, user)
+ }
+ } else {
+ apiKey.KeyType = "unknown"
+ }
+ apiKey.ReadOnly = key.Mode == perm.AccessModeRead
+ return apiKey, nil
+}
+
+func composePublicKeysAPILink() string {
+ return setting.AppURL + "api/v1/user/keys/"
+}
+
+func listPublicKeys(ctx *context.APIContext, user *user_model.User) {
+ var keys []*asymkey_model.PublicKey
+ var err error
+ var count int
+
+ fingerprint := ctx.FormString("fingerprint")
+ username := ctx.Params("username")
+
+ if fingerprint != "" {
+ var userID int64 // Unrestricted
+ // Querying not just listing
+ if username != "" {
+ // Restrict to provided uid
+ userID = user.ID
+ }
+ keys, err = db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{
+ OwnerID: userID,
+ Fingerprint: fingerprint,
+ })
+ count = len(keys)
+ } else {
+ var total int64
+ // Use ListPublicKeys
+ keys, total, err = db.FindAndCount[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{
+ ListOptions: utils.GetListOptions(ctx),
+ OwnerID: user.ID,
+ NotKeytype: asymkey_model.KeyTypePrincipal,
+ })
+ count = int(total)
+ }
+
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "ListPublicKeys", err)
+ return
+ }
+
+ apiLink := composePublicKeysAPILink()
+ apiKeys := make([]*api.PublicKey, len(keys))
+ for i := range keys {
+ apiKeys[i] = convert.ToPublicKey(apiLink, keys[i])
+ if ctx.Doer.IsAdmin || ctx.Doer.ID == keys[i].OwnerID {
+ apiKeys[i], _ = appendPrivateInformation(ctx, apiKeys[i], keys[i], user)
+ }
+ }
+
+ ctx.SetTotalCountHeader(int64(count))
+ ctx.JSON(http.StatusOK, &apiKeys)
+}
+
+// ListMyPublicKeys list all of the authenticated user's public keys
+func ListMyPublicKeys(ctx *context.APIContext) {
+ // swagger:operation GET /user/keys user userCurrentListKeys
+ // ---
+ // summary: List the authenticated user's public keys
+ // parameters:
+ // - name: fingerprint
+ // in: query
+ // description: fingerprint of the key
+ // type: string
+ // - name: page
+ // in: query
+ // description: page number of results to return (1-based)
+ // type: integer
+ // - name: limit
+ // in: query
+ // description: page size of results
+ // type: integer
+ // produces:
+ // - application/json
+ // responses:
+ // "200":
+ // "$ref": "#/responses/PublicKeyList"
+ // "401":
+ // "$ref": "#/responses/unauthorized"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+
+ listPublicKeys(ctx, ctx.Doer)
+}
+
+// ListPublicKeys list the given user's public keys
+func ListPublicKeys(ctx *context.APIContext) {
+ // swagger:operation GET /users/{username}/keys user userListKeys
+ // ---
+ // summary: List the given user's public keys
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: username
+ // in: path
+ // description: username of user
+ // type: string
+ // required: true
+ // - name: fingerprint
+ // in: query
+ // description: fingerprint of the key
+ // type: string
+ // - name: page
+ // in: query
+ // description: page number of results to return (1-based)
+ // type: integer
+ // - name: limit
+ // in: query
+ // description: page size of results
+ // type: integer
+ // responses:
+ // "200":
+ // "$ref": "#/responses/PublicKeyList"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ listPublicKeys(ctx, ctx.ContextUser)
+}
+
+// GetPublicKey get a public key
+func GetPublicKey(ctx *context.APIContext) {
+ // swagger:operation GET /user/keys/{id} user userCurrentGetKey
+ // ---
+ // summary: Get a public key
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of key to get
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "200":
+ // "$ref": "#/responses/PublicKey"
+ // "401":
+ // "$ref": "#/responses/unauthorized"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ key, err := asymkey_model.GetPublicKeyByID(ctx, ctx.ParamsInt64(":id"))
+ if err != nil {
+ if asymkey_model.IsErrKeyNotExist(err) {
+ ctx.NotFound()
+ } else {
+ ctx.Error(http.StatusInternalServerError, "GetPublicKeyByID", err)
+ }
+ return
+ }
+
+ apiLink := composePublicKeysAPILink()
+ apiKey := convert.ToPublicKey(apiLink, key)
+ if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID {
+ apiKey, _ = appendPrivateInformation(ctx, apiKey, key, ctx.Doer)
+ }
+ ctx.JSON(http.StatusOK, apiKey)
+}
+
+// CreateUserPublicKey creates new public key to given user by ID.
+func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) {
+ if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
+ ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
+ return
+ }
+
+ content, err := asymkey_model.CheckPublicKeyString(form.Key)
+ if err != nil {
+ repo.HandleCheckKeyStringError(ctx, err)
+ return
+ }
+
+ key, err := asymkey_model.AddPublicKey(ctx, uid, form.Title, content, 0)
+ if err != nil {
+ repo.HandleAddKeyError(ctx, err)
+ return
+ }
+ apiLink := composePublicKeysAPILink()
+ apiKey := convert.ToPublicKey(apiLink, key)
+ if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID {
+ apiKey, _ = appendPrivateInformation(ctx, apiKey, key, ctx.Doer)
+ }
+ ctx.JSON(http.StatusCreated, apiKey)
+}
+
+// CreatePublicKey create one public key for me
+func CreatePublicKey(ctx *context.APIContext) {
+ // swagger:operation POST /user/keys user userCurrentPostKey
+ // ---
+ // summary: Create a public key
+ // consumes:
+ // - application/json
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: body
+ // in: body
+ // schema:
+ // "$ref": "#/definitions/CreateKeyOption"
+ // responses:
+ // "201":
+ // "$ref": "#/responses/PublicKey"
+ // "401":
+ // "$ref": "#/responses/unauthorized"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "422":
+ // "$ref": "#/responses/validationError"
+
+ form := web.GetForm(ctx).(*api.CreateKeyOption)
+ CreateUserPublicKey(ctx, *form, ctx.Doer.ID)
+}
+
+// DeletePublicKey delete one public key
+func DeletePublicKey(ctx *context.APIContext) {
+ // swagger:operation DELETE /user/keys/{id} user userCurrentDeleteKey
+ // ---
+ // summary: Delete a public key
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of key to delete
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "204":
+ // "$ref": "#/responses/empty"
+ // "401":
+ // "$ref": "#/responses/unauthorized"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
+ ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
+ return
+ }
+
+ id := ctx.ParamsInt64(":id")
+ externallyManaged, err := asymkey_model.PublicKeyIsExternallyManaged(ctx, id)
+ if err != nil {
+ if asymkey_model.IsErrKeyNotExist(err) {
+ ctx.NotFound()
+ } else {
+ ctx.Error(http.StatusInternalServerError, "PublicKeyIsExternallyManaged", err)
+ }
+ return
+ }
+
+ if externallyManaged {
+ ctx.Error(http.StatusForbidden, "", "SSH Key is externally managed for this user")
+ return
+ }
+
+ if err := asymkey_service.DeletePublicKey(ctx, ctx.Doer, id); err != nil {
+ if asymkey_model.IsErrKeyAccessDenied(err) {
+ ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
+ } else {
+ ctx.Error(http.StatusInternalServerError, "DeletePublicKey", err)
+ }
+ return
+ }
+
+ ctx.Status(http.StatusNoContent)
+}