Skip to content

Move delete deploy keys into service layer #32201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions models/asymkey/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ func (err ErrGPGKeyAccessDenied) Unwrap() error {
// ErrKeyAccessDenied represents a "KeyAccessDenied" kind of error.
type ErrKeyAccessDenied struct {
UserID int64
RepoID int64
KeyID int64
Note string
}
Expand All @@ -228,8 +229,8 @@ func IsErrKeyAccessDenied(err error) bool {
}

func (err ErrKeyAccessDenied) Error() string {
return fmt.Sprintf("user does not have access to the key [user_id: %d, key_id: %d, note: %s]",
err.UserID, err.KeyID, err.Note)
return fmt.Sprintf("user does not have access to the key [user_id: %d, repo_id: %d, key_id: %d, note: %s]",
err.UserID, err.RepoID, err.KeyID, err.Note)
}

func (err ErrKeyAccessDenied) Unwrap() error {
Expand Down
48 changes: 0 additions & 48 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ package models

import (
"context"
"fmt"
"strconv"

_ "image/jpeg" // Needed for jpeg support

asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
Expand Down Expand Up @@ -315,48 +312,3 @@ func DoctorUserStarNum(ctx context.Context) (err error) {

return err
}

// DeleteDeployKey delete deploy keys
func DeleteDeployKey(ctx context.Context, doer *user_model.User, id int64) error {
key, err := asymkey_model.GetDeployKeyByID(ctx, id)
if err != nil {
if asymkey_model.IsErrDeployKeyNotExist(err) {
return nil
}
return fmt.Errorf("GetDeployKeyByID: %w", err)
}

// Check if user has access to delete this key.
if !doer.IsAdmin {
repo, err := repo_model.GetRepositoryByID(ctx, key.RepoID)
if err != nil {
return fmt.Errorf("GetRepositoryByID: %w", err)
}
has, err := access_model.IsUserRepoAdmin(ctx, repo, doer)
if err != nil {
return fmt.Errorf("GetUserRepoPermission: %w", err)
} else if !has {
return asymkey_model.ErrKeyAccessDenied{
UserID: doer.ID,
KeyID: key.ID,
Note: "deploy",
}
}
}

if _, err := db.DeleteByID[asymkey_model.DeployKey](ctx, key.ID); err != nil {
return fmt.Errorf("delete deploy key [%d]: %w", key.ID, err)
}

// Check if this is the last reference to same key content.
has, err := asymkey_model.IsDeployKeyExistByKeyID(ctx, key.KeyID)
if err != nil {
return err
} else if !has {
if _, err = db.DeleteByID[asymkey_model.PublicKey](ctx, key.KeyID); err != nil {
return err
}
}

return nil
}
2 changes: 1 addition & 1 deletion routers/api/v1/repo/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func DeleteDeploykey(ctx *context.APIContext) {
// "404":
// "$ref": "#/responses/notFound"

if err := asymkey_service.DeleteDeployKey(ctx, ctx.Doer, ctx.PathParamInt64(":id")); err != nil {
if err := asymkey_service.DeleteDeployKey(ctx, ctx.Repo.Repository, ctx.PathParamInt64(":id")); err != nil {
if asymkey_model.IsErrKeyAccessDenied(err) {
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
} else {
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/setting/deploy_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func DeployKeysPost(ctx *context.Context) {

// DeleteDeployKey response for deleting a deploy key
func DeleteDeployKey(ctx *context.Context) {
if err := asymkey_service.DeleteDeployKey(ctx, ctx.Doer, ctx.FormInt64("id")); err != nil {
if err := asymkey_service.DeleteDeployKey(ctx, ctx.Repo.Repository, ctx.FormInt64("id")); err != nil {
ctx.Flash.Error("DeleteDeployKey: " + err.Error())
} else {
ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success"))
Expand Down
56 changes: 52 additions & 4 deletions services/asymkey/deploy_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,69 @@ package asymkey

import (
"context"
"fmt"

"code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
repo_model "code.gitea.io/gitea/models/repo"
)

// DeleteRepoDeployKeys deletes all deploy keys of a repository. permissions check should be done outside
func DeleteRepoDeployKeys(ctx context.Context, repoID int64) (int, error) {
deployKeys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: repoID})
if err != nil {
return 0, fmt.Errorf("listDeployKeys: %w", err)
}

for _, dKey := range deployKeys {
if err := deleteDeployKeyFromDB(ctx, dKey); err != nil {
return 0, fmt.Errorf("deleteDeployKeys: %w", err)
}
}
return len(deployKeys), nil
}

// deleteDeployKeyFromDB delete deploy keys from database
func deleteDeployKeyFromDB(ctx context.Context, key *asymkey_model.DeployKey) error {
if _, err := db.DeleteByID[asymkey_model.DeployKey](ctx, key.ID); err != nil {
return fmt.Errorf("delete deploy key [%d]: %w", key.ID, err)
}

// Check if this is the last reference to same key content.
has, err := asymkey_model.IsDeployKeyExistByKeyID(ctx, key.KeyID)
if err != nil {
return err
} else if !has {
if _, err = db.DeleteByID[asymkey_model.PublicKey](ctx, key.KeyID); err != nil {
return err
}
}

return nil
}

// DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed.
func DeleteDeployKey(ctx context.Context, doer *user_model.User, id int64) error {
// Permissions check should be done outside.
func DeleteDeployKey(ctx context.Context, repo *repo_model.Repository, id int64) error {
dbCtx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()

if err := models.DeleteDeployKey(dbCtx, doer, id); err != nil {
key, err := asymkey_model.GetDeployKeyByID(ctx, id)
if err != nil {
if asymkey_model.IsErrDeployKeyNotExist(err) {
return nil
}
return fmt.Errorf("GetDeployKeyByID: %w", err)
}

if key.RepoID != repo.ID {
return fmt.Errorf("deploy key %d does not belong to repository %d", id, repo.ID)
}

if err := deleteDeployKeyFromDB(dbCtx, key); err != nil {
return err
}
if err := committer.Commit(); err != nil {
Expand Down
1 change: 1 addition & 0 deletions services/asymkey/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"code.gitea.io/gitea/models/unittest"

_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
)
Expand Down
13 changes: 3 additions & 10 deletions services/repository/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ import (
"context"
"fmt"

"code.gitea.io/gitea/models"
actions_model "code.gitea.io/gitea/models/actions"
activities_model "code.gitea.io/gitea/models/activities"
admin_model "code.gitea.io/gitea/models/admin"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
Expand Down Expand Up @@ -76,16 +74,11 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
}

// Delete Deploy Keys
deployKeys, err := db.Find[asymkey_model.DeployKey](ctx, asymkey_model.ListDeployKeysOptions{RepoID: repoID})
deleted, err := asymkey_service.DeleteRepoDeployKeys(ctx, repoID)
if err != nil {
return fmt.Errorf("listDeployKeys: %w", err)
}
needRewriteKeysFile := len(deployKeys) > 0
for _, dKey := range deployKeys {
if err := models.DeleteDeployKey(ctx, doer, dKey.ID); err != nil {
return fmt.Errorf("deleteDeployKeys: %w", err)
}
return err
}
needRewriteKeysFile := deleted > 0

if cnt, err := sess.ID(repoID).Delete(&repo_model.Repository{}); err != nil {
return err
Expand Down
Loading