* Delete a user's public key via admin api * Test admin ssh endpoint for creating a new ssh key * Adapt public ssh key test to also test the delete operation * Test that deleting a missing key will result in a 404 * Test that a normal user can't delete another user's ssh key * Make DeletePublicKey return err * Update swagger doctags/v1.4.0-rc1
// Copyright 2017 The Gitea Authors. All rights reserved. | |||||
// Use of this source code is governed by a MIT-style | |||||
// license that can be found in the LICENSE file. | |||||
package integrations | |||||
import ( | |||||
"fmt" | |||||
"net/http" | |||||
"testing" | |||||
"code.gitea.io/gitea/models" | |||||
api "code.gitea.io/sdk/gitea" | |||||
) | |||||
func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) { | |||||
prepareTestEnv(t) | |||||
// user1 is an admin user | |||||
session := loginUser(t, "user1") | |||||
keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User) | |||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", keyOwner.Name) | |||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ | |||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n", | |||||
"title": "test-key", | |||||
}) | |||||
resp := session.MakeRequest(t, req, http.StatusCreated) | |||||
var newPublicKey api.PublicKey | |||||
DecodeJSON(t, resp, &newPublicKey) | |||||
models.AssertExistsAndLoadBean(t, &models.PublicKey{ | |||||
ID: newPublicKey.ID, | |||||
Name: newPublicKey.Title, | |||||
Content: newPublicKey.Key, | |||||
Fingerprint: newPublicKey.Fingerprint, | |||||
OwnerID: keyOwner.ID, | |||||
}) | |||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d", | |||||
keyOwner.Name, newPublicKey.ID) | |||||
session.MakeRequest(t, req, http.StatusNoContent) | |||||
models.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID}) | |||||
} | |||||
func TestAPIAdminDeleteMissingSSHKey(t *testing.T) { | |||||
prepareTestEnv(t) | |||||
// user1 is an admin user | |||||
session := loginUser(t, "user1") | |||||
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d", models.NonexistentID) | |||||
session.MakeRequest(t, req, http.StatusNotFound) | |||||
} | |||||
func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) { | |||||
prepareTestEnv(t) | |||||
adminUsername := "user1" | |||||
normalUsername := "user2" | |||||
session := loginUser(t, adminUsername) | |||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", adminUsername) | |||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ | |||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n", | |||||
"title": "test-key", | |||||
}) | |||||
resp := session.MakeRequest(t, req, http.StatusCreated) | |||||
var newPublicKey api.PublicKey | |||||
DecodeJSON(t, resp, &newPublicKey) | |||||
session = loginUser(t, normalUsername) | |||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d", | |||||
adminUsername, newPublicKey.ID) | |||||
session.MakeRequest(t, req, http.StatusForbidden) | |||||
} |
func DeletePublicKey(doer *User, id int64) (err error) { | func DeletePublicKey(doer *User, id int64) (err error) { | ||||
key, err := GetPublicKeyByID(id) | key, err := GetPublicKeyByID(id) | ||||
if err != nil { | if err != nil { | ||||
if IsErrKeyNotExist(err) { | |||||
return nil | |||||
} | |||||
return fmt.Errorf("GetPublicKeyByID: %v", err) | |||||
return err | |||||
} | } | ||||
// Check if user has access to delete this key. | // Check if user has access to delete this key. |
} | } | ||||
user.CreateUserPublicKey(ctx, form, u.ID) | user.CreateUserPublicKey(ctx, form, u.ID) | ||||
} | } | ||||
// DeleteUserPublicKey api for deleting a user's public key | |||||
func DeleteUserPublicKey(ctx *context.APIContext) { | |||||
// swagger:operation DELETE /admin/users/{username}/keys/{id} admin adminDeleteUserPublicKey | |||||
// --- | |||||
// summary: Delete a user's public key | |||||
// produces: | |||||
// - application/json | |||||
// parameters: | |||||
// - name: username | |||||
// in: path | |||||
// description: username of user | |||||
// type: string | |||||
// required: true | |||||
// - name: id | |||||
// in: path | |||||
// description: id of the key to delete | |||||
// type: integer | |||||
// required: true | |||||
// responses: | |||||
// "204": | |||||
// "$ref": "#/responses/empty" | |||||
// "403": | |||||
// "$ref": "#/responses/forbidden" | |||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
u := user.GetUserByParams(ctx) | |||||
if ctx.Written() { | |||||
return | |||||
} | |||||
if err := models.DeletePublicKey(u, ctx.ParamsInt64(":id")); err != nil { | |||||
if models.IsErrKeyNotExist(err) { | |||||
ctx.Status(404) | |||||
} else if models.IsErrKeyAccessDenied(err) { | |||||
ctx.Error(403, "", "You do not have access to this key") | |||||
} else { | |||||
ctx.Error(500, "DeleteUserPublicKey", err) | |||||
} | |||||
return | |||||
} | |||||
log.Trace("Key deleted by admin(%s): %s", ctx.User.Name, u.Name) | |||||
ctx.Status(204) | |||||
} |
m.Group("/:username", func() { | m.Group("/:username", func() { | ||||
m.Combo("").Patch(bind(api.EditUserOption{}), admin.EditUser). | m.Combo("").Patch(bind(api.EditUserOption{}), admin.EditUser). | ||||
Delete(admin.DeleteUser) | Delete(admin.DeleteUser) | ||||
m.Post("/keys", bind(api.CreateKeyOption{}), admin.CreatePublicKey) | |||||
m.Group("/keys", func() { | |||||
m.Post("", bind(api.CreateKeyOption{}), admin.CreatePublicKey) | |||||
m.Delete("/:id", admin.DeleteUserPublicKey) | |||||
}) | |||||
m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg) | m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg) | ||||
m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) | m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) | ||||
}) | }) |
// "$ref": "#/responses/empty" | // "$ref": "#/responses/empty" | ||||
// "403": | // "403": | ||||
// "$ref": "#/responses/forbidden" | // "$ref": "#/responses/forbidden" | ||||
// "404": | |||||
// "$ref": "#/responses/notFound" | |||||
if err := models.DeletePublicKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | if err := models.DeletePublicKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { | ||||
if models.IsErrKeyAccessDenied(err) { | |||||
if models.IsErrKeyNotExist(err) { | |||||
ctx.Status(404) | |||||
} else if models.IsErrKeyAccessDenied(err) { | |||||
ctx.Error(403, "", "You do not have access to this key") | ctx.Error(403, "", "You do not have access to this key") | ||||
} else { | } else { | ||||
ctx.Error(500, "DeletePublicKey", err) | ctx.Error(500, "DeletePublicKey", err) |