code.gitea.io/gitea@v1.21.7/routers/api/v1/user/key.go (about) 1 // Copyright 2015 The Gogs Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package user 5 6 import ( 7 std_ctx "context" 8 "net/http" 9 10 asymkey_model "code.gitea.io/gitea/models/asymkey" 11 "code.gitea.io/gitea/models/perm" 12 user_model "code.gitea.io/gitea/models/user" 13 "code.gitea.io/gitea/modules/context" 14 "code.gitea.io/gitea/modules/setting" 15 api "code.gitea.io/gitea/modules/structs" 16 "code.gitea.io/gitea/modules/web" 17 "code.gitea.io/gitea/routers/api/v1/repo" 18 "code.gitea.io/gitea/routers/api/v1/utils" 19 asymkey_service "code.gitea.io/gitea/services/asymkey" 20 "code.gitea.io/gitea/services/convert" 21 ) 22 23 // appendPrivateInformation appends the owner and key type information to api.PublicKey 24 func appendPrivateInformation(ctx std_ctx.Context, apiKey *api.PublicKey, key *asymkey_model.PublicKey, defaultUser *user_model.User) (*api.PublicKey, error) { 25 if key.Type == asymkey_model.KeyTypeDeploy { 26 apiKey.KeyType = "deploy" 27 } else if key.Type == asymkey_model.KeyTypeUser { 28 apiKey.KeyType = "user" 29 30 if defaultUser.ID == key.OwnerID { 31 apiKey.Owner = convert.ToUser(ctx, defaultUser, defaultUser) 32 } else { 33 user, err := user_model.GetUserByID(ctx, key.OwnerID) 34 if err != nil { 35 return apiKey, err 36 } 37 apiKey.Owner = convert.ToUser(ctx, user, user) 38 } 39 } else { 40 apiKey.KeyType = "unknown" 41 } 42 apiKey.ReadOnly = key.Mode == perm.AccessModeRead 43 return apiKey, nil 44 } 45 46 func composePublicKeysAPILink() string { 47 return setting.AppURL + "api/v1/user/keys/" 48 } 49 50 func listPublicKeys(ctx *context.APIContext, user *user_model.User) { 51 var keys []*asymkey_model.PublicKey 52 var err error 53 var count int 54 55 fingerprint := ctx.FormString("fingerprint") 56 username := ctx.Params("username") 57 58 if fingerprint != "" { 59 // Querying not just listing 60 if username != "" { 61 // Restrict to provided uid 62 keys, err = asymkey_model.SearchPublicKey(user.ID, fingerprint) 63 } else { 64 // Unrestricted 65 keys, err = asymkey_model.SearchPublicKey(0, fingerprint) 66 } 67 count = len(keys) 68 } else { 69 total, err2 := asymkey_model.CountPublicKeys(user.ID) 70 if err2 != nil { 71 ctx.InternalServerError(err) 72 return 73 } 74 count = int(total) 75 76 // Use ListPublicKeys 77 keys, err = asymkey_model.ListPublicKeys(user.ID, utils.GetListOptions(ctx)) 78 } 79 80 if err != nil { 81 ctx.Error(http.StatusInternalServerError, "ListPublicKeys", err) 82 return 83 } 84 85 apiLink := composePublicKeysAPILink() 86 apiKeys := make([]*api.PublicKey, len(keys)) 87 for i := range keys { 88 apiKeys[i] = convert.ToPublicKey(apiLink, keys[i]) 89 if ctx.Doer.IsAdmin || ctx.Doer.ID == keys[i].OwnerID { 90 apiKeys[i], _ = appendPrivateInformation(ctx, apiKeys[i], keys[i], user) 91 } 92 } 93 94 ctx.SetTotalCountHeader(int64(count)) 95 ctx.JSON(http.StatusOK, &apiKeys) 96 } 97 98 // ListMyPublicKeys list all of the authenticated user's public keys 99 func ListMyPublicKeys(ctx *context.APIContext) { 100 // swagger:operation GET /user/keys user userCurrentListKeys 101 // --- 102 // summary: List the authenticated user's public keys 103 // parameters: 104 // - name: fingerprint 105 // in: query 106 // description: fingerprint of the key 107 // type: string 108 // - name: page 109 // in: query 110 // description: page number of results to return (1-based) 111 // type: integer 112 // - name: limit 113 // in: query 114 // description: page size of results 115 // type: integer 116 // produces: 117 // - application/json 118 // responses: 119 // "200": 120 // "$ref": "#/responses/PublicKeyList" 121 122 listPublicKeys(ctx, ctx.Doer) 123 } 124 125 // ListPublicKeys list the given user's public keys 126 func ListPublicKeys(ctx *context.APIContext) { 127 // swagger:operation GET /users/{username}/keys user userListKeys 128 // --- 129 // summary: List the given user's public keys 130 // produces: 131 // - application/json 132 // parameters: 133 // - name: username 134 // in: path 135 // description: username of user 136 // type: string 137 // required: true 138 // - name: fingerprint 139 // in: query 140 // description: fingerprint of the key 141 // type: string 142 // - name: page 143 // in: query 144 // description: page number of results to return (1-based) 145 // type: integer 146 // - name: limit 147 // in: query 148 // description: page size of results 149 // type: integer 150 // responses: 151 // "200": 152 // "$ref": "#/responses/PublicKeyList" 153 // "404": 154 // "$ref": "#/responses/notFound" 155 156 listPublicKeys(ctx, ctx.ContextUser) 157 } 158 159 // GetPublicKey get a public key 160 func GetPublicKey(ctx *context.APIContext) { 161 // swagger:operation GET /user/keys/{id} user userCurrentGetKey 162 // --- 163 // summary: Get a public key 164 // produces: 165 // - application/json 166 // parameters: 167 // - name: id 168 // in: path 169 // description: id of key to get 170 // type: integer 171 // format: int64 172 // required: true 173 // responses: 174 // "200": 175 // "$ref": "#/responses/PublicKey" 176 // "404": 177 // "$ref": "#/responses/notFound" 178 179 key, err := asymkey_model.GetPublicKeyByID(ctx.ParamsInt64(":id")) 180 if err != nil { 181 if asymkey_model.IsErrKeyNotExist(err) { 182 ctx.NotFound() 183 } else { 184 ctx.Error(http.StatusInternalServerError, "GetPublicKeyByID", err) 185 } 186 return 187 } 188 189 apiLink := composePublicKeysAPILink() 190 apiKey := convert.ToPublicKey(apiLink, key) 191 if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID { 192 apiKey, _ = appendPrivateInformation(ctx, apiKey, key, ctx.Doer) 193 } 194 ctx.JSON(http.StatusOK, apiKey) 195 } 196 197 // CreateUserPublicKey creates new public key to given user by ID. 198 func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) { 199 content, err := asymkey_model.CheckPublicKeyString(form.Key) 200 if err != nil { 201 repo.HandleCheckKeyStringError(ctx, err) 202 return 203 } 204 205 key, err := asymkey_model.AddPublicKey(uid, form.Title, content, 0) 206 if err != nil { 207 repo.HandleAddKeyError(ctx, err) 208 return 209 } 210 apiLink := composePublicKeysAPILink() 211 apiKey := convert.ToPublicKey(apiLink, key) 212 if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID { 213 apiKey, _ = appendPrivateInformation(ctx, apiKey, key, ctx.Doer) 214 } 215 ctx.JSON(http.StatusCreated, apiKey) 216 } 217 218 // CreatePublicKey create one public key for me 219 func CreatePublicKey(ctx *context.APIContext) { 220 // swagger:operation POST /user/keys user userCurrentPostKey 221 // --- 222 // summary: Create a public key 223 // consumes: 224 // - application/json 225 // produces: 226 // - application/json 227 // parameters: 228 // - name: body 229 // in: body 230 // schema: 231 // "$ref": "#/definitions/CreateKeyOption" 232 // responses: 233 // "201": 234 // "$ref": "#/responses/PublicKey" 235 // "422": 236 // "$ref": "#/responses/validationError" 237 238 form := web.GetForm(ctx).(*api.CreateKeyOption) 239 CreateUserPublicKey(ctx, *form, ctx.Doer.ID) 240 } 241 242 // DeletePublicKey delete one public key 243 func DeletePublicKey(ctx *context.APIContext) { 244 // swagger:operation DELETE /user/keys/{id} user userCurrentDeleteKey 245 // --- 246 // summary: Delete a public key 247 // produces: 248 // - application/json 249 // parameters: 250 // - name: id 251 // in: path 252 // description: id of key to delete 253 // type: integer 254 // format: int64 255 // required: true 256 // responses: 257 // "204": 258 // "$ref": "#/responses/empty" 259 // "403": 260 // "$ref": "#/responses/forbidden" 261 // "404": 262 // "$ref": "#/responses/notFound" 263 264 id := ctx.ParamsInt64(":id") 265 externallyManaged, err := asymkey_model.PublicKeyIsExternallyManaged(id) 266 if err != nil { 267 if asymkey_model.IsErrKeyNotExist(err) { 268 ctx.NotFound() 269 } else { 270 ctx.Error(http.StatusInternalServerError, "PublicKeyIsExternallyManaged", err) 271 } 272 return 273 } 274 275 if externallyManaged { 276 ctx.Error(http.StatusForbidden, "", "SSH Key is externally managed for this user") 277 return 278 } 279 280 if err := asymkey_service.DeletePublicKey(ctx, ctx.Doer, id); err != nil { 281 if asymkey_model.IsErrKeyAccessDenied(err) { 282 ctx.Error(http.StatusForbidden, "", "You do not have access to this key") 283 } else { 284 ctx.Error(http.StatusInternalServerError, "DeletePublicKey", err) 285 } 286 return 287 } 288 289 ctx.Status(http.StatusNoContent) 290 }