Move keys to models/asymkey (#17917)
* Move keys to models/keys * Rename models/keys -> models/asymkey * change the missed package name * Fix package alias * Fix test * Fix docs * Fix test * Fix test * merge
This commit is contained in:
parent
0a9fcf63a4
commit
3ca5dc7e32
@ -14,6 +14,7 @@ import (
|
||||
"text/tabwriter"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/login"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -625,7 +626,7 @@ func runRegenerateKeys(_ *cli.Context) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return models.RewriteAllPublicKeys()
|
||||
return asymkey_model.RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
@ -129,9 +130,9 @@ func runServ(c *cli.Context) error {
|
||||
return fail("Internal error", "Failed to check provided key: %v", err)
|
||||
}
|
||||
switch key.Type {
|
||||
case models.KeyTypeDeploy:
|
||||
case asymkey_model.KeyTypeDeploy:
|
||||
println("Hi there! You've successfully authenticated with the deploy key named " + key.Name + ", but Gitea does not provide shell access.")
|
||||
case models.KeyTypePrincipal:
|
||||
case asymkey_model.KeyTypePrincipal:
|
||||
println("Hi there! You've successfully authenticated with the principal " + key.Content + ", but Gitea does not provide shell access.")
|
||||
default:
|
||||
println("Hi there, " + user.Name + "! You've successfully authenticated with the key named " + key.Name + ", but Gitea does not provide shell access.")
|
||||
|
@ -277,7 +277,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `SSH_AUTHORIZED_PRINCIPALS_ALLOW`: **off** or **username, email**: \[off, username, email, anything\]: Specify the principals values that users are allowed to use as principal. When set to `anything` no checks are done on the principal string. When set to `off` authorized principal are not allowed to be set.
|
||||
- `SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE`: **false/true**: Gitea will create a authorized_principals file by default when it is not using the internal ssh server and `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
|
||||
- `SSH_AUTHORIZED_PRINCIPALS_BACKUP`: **false/true**: Enable SSH Authorized Principals Backup when rewriting all keys, default is true if `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
|
||||
- `SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE`: **{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}**: Set the template for the command to passed on authorized keys. Possible keys are: AppPath, AppWorkPath, CustomConf, CustomPath, Key - where Key is a `models.PublicKey` and the others are strings which are shellquoted.
|
||||
- `SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE`: **{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}**: Set the template for the command to passed on authorized keys. Possible keys are: AppPath, AppWorkPath, CustomConf, CustomPath, Key - where Key is a `models/asymkey.PublicKey` and the others are strings which are shellquoted.
|
||||
- `SSH_SERVER_CIPHERS`: **aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, arcfour256, arcfour128**: For the built-in SSH server, choose the ciphers to support for SSH connections, for system SSH this setting has no effect.
|
||||
- `SSH_SERVER_KEY_EXCHANGES`: **diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, curve25519-sha256@libssh.org**: For the built-in SSH server, choose the key exchange algorithms to support for SSH connections, for system SSH this setting has no effect.
|
||||
- `SSH_SERVER_MACS`: **hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1, hmac-sha1-96**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
@ -34,7 +34,7 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||
|
||||
var newPublicKey api.PublicKey
|
||||
DecodeJSON(t, resp, &newPublicKey)
|
||||
unittest.AssertExistsAndLoadBean(t, &models.PublicKey{
|
||||
unittest.AssertExistsAndLoadBean(t, &asymkey_model.PublicKey{
|
||||
ID: newPublicKey.ID,
|
||||
Name: newPublicKey.Title,
|
||||
Content: newPublicKey.Key,
|
||||
@ -45,7 +45,7 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
|
||||
keyOwner.Name, newPublicKey.ID, token)
|
||||
session.MakeRequest(t, req, http.StatusNoContent)
|
||||
unittest.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID})
|
||||
unittest.AssertNotExistsBean(t, &asymkey_model.PublicKey{ID: newPublicKey.ID})
|
||||
}
|
||||
|
||||
func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -65,7 +65,7 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
|
||||
|
||||
var newDeployKey api.DeployKey
|
||||
DecodeJSON(t, resp, &newDeployKey)
|
||||
unittest.AssertExistsAndLoadBean(t, &models.DeployKey{
|
||||
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||
ID: newDeployKey.ID,
|
||||
Name: rawKeyBody.Title,
|
||||
Content: rawKeyBody.Key,
|
||||
@ -90,7 +90,7 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
|
||||
|
||||
var newDeployKey api.DeployKey
|
||||
DecodeJSON(t, resp, &newDeployKey)
|
||||
unittest.AssertExistsAndLoadBean(t, &models.DeployKey{
|
||||
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||
ID: newDeployKey.ID,
|
||||
Name: rawKeyBody.Title,
|
||||
Content: rawKeyBody.Key,
|
||||
@ -116,7 +116,7 @@ func TestCreateUserKey(t *testing.T) {
|
||||
|
||||
var newPublicKey api.PublicKey
|
||||
DecodeJSON(t, resp, &newPublicKey)
|
||||
unittest.AssertExistsAndLoadBean(t, &models.PublicKey{
|
||||
unittest.AssertExistsAndLoadBean(t, &asymkey_model.PublicKey{
|
||||
ID: newPublicKey.ID,
|
||||
OwnerID: user.ID,
|
||||
Name: rawKeyBody.Title,
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
|
||||
@ -27,7 +27,7 @@ func TestAPIPrivateNoServ(t *testing.T) {
|
||||
assert.Equal(t, int64(1), key.ID)
|
||||
assert.Equal(t, "user2@localhost", key.Name)
|
||||
|
||||
deployKey, err := models.AddDeployKey(1, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", false)
|
||||
deployKey, err := asymkey_model.AddDeployKey(1, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
key, user, err = private.ServNoCommand(ctx, deployKey.KeyID)
|
||||
@ -85,7 +85,7 @@ func TestAPIPrivateServ(t *testing.T) {
|
||||
assert.Empty(t, results)
|
||||
|
||||
// Add reading deploy key
|
||||
deployKey, err := models.AddDeployKey(19, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", true)
|
||||
deployKey, err := asymkey_model.AddDeployKey(19, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Can pull from repo we're a deploy key for
|
||||
@ -117,7 +117,7 @@ func TestAPIPrivateServ(t *testing.T) {
|
||||
assert.Empty(t, results)
|
||||
|
||||
// Add writing deploy key
|
||||
deployKey, err = models.AddDeployKey(20, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", false)
|
||||
deployKey, err = asymkey_model.AddDeployKey(20, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Cannot push to a private repo with reading key
|
||||
|
248
models/asymkey/error.go
Normal file
248
models/asymkey/error.go
Normal file
@ -0,0 +1,248 @@
|
||||
// Copyright 2021 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 asymkey
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ErrKeyUnableVerify represents a "KeyUnableVerify" kind of error.
|
||||
type ErrKeyUnableVerify struct {
|
||||
Result string
|
||||
}
|
||||
|
||||
// IsErrKeyUnableVerify checks if an error is a ErrKeyUnableVerify.
|
||||
func IsErrKeyUnableVerify(err error) bool {
|
||||
_, ok := err.(ErrKeyUnableVerify)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyUnableVerify) Error() string {
|
||||
return fmt.Sprintf("Unable to verify key content [result: %s]", err.Result)
|
||||
}
|
||||
|
||||
// ErrKeyNotExist represents a "KeyNotExist" kind of error.
|
||||
type ErrKeyNotExist struct {
|
||||
ID int64
|
||||
}
|
||||
|
||||
// IsErrKeyNotExist checks if an error is a ErrKeyNotExist.
|
||||
func IsErrKeyNotExist(err error) bool {
|
||||
_, ok := err.(ErrKeyNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyNotExist) Error() string {
|
||||
return fmt.Sprintf("public key does not exist [id: %d]", err.ID)
|
||||
}
|
||||
|
||||
// ErrKeyAlreadyExist represents a "KeyAlreadyExist" kind of error.
|
||||
type ErrKeyAlreadyExist struct {
|
||||
OwnerID int64
|
||||
Fingerprint string
|
||||
Content string
|
||||
}
|
||||
|
||||
// IsErrKeyAlreadyExist checks if an error is a ErrKeyAlreadyExist.
|
||||
func IsErrKeyAlreadyExist(err error) bool {
|
||||
_, ok := err.(ErrKeyAlreadyExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("public key already exists [owner_id: %d, finger_print: %s, content: %s]",
|
||||
err.OwnerID, err.Fingerprint, err.Content)
|
||||
}
|
||||
|
||||
// ErrKeyNameAlreadyUsed represents a "KeyNameAlreadyUsed" kind of error.
|
||||
type ErrKeyNameAlreadyUsed struct {
|
||||
OwnerID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsErrKeyNameAlreadyUsed checks if an error is a ErrKeyNameAlreadyUsed.
|
||||
func IsErrKeyNameAlreadyUsed(err error) bool {
|
||||
_, ok := err.(ErrKeyNameAlreadyUsed)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyNameAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
|
||||
}
|
||||
|
||||
// ErrGPGNoEmailFound represents a "ErrGPGNoEmailFound" kind of error.
|
||||
type ErrGPGNoEmailFound struct {
|
||||
FailedEmails []string
|
||||
ID string
|
||||
}
|
||||
|
||||
// IsErrGPGNoEmailFound checks if an error is a ErrGPGNoEmailFound.
|
||||
func IsErrGPGNoEmailFound(err error) bool {
|
||||
_, ok := err.(ErrGPGNoEmailFound)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGNoEmailFound) Error() string {
|
||||
return fmt.Sprintf("none of the emails attached to the GPG key could be found: %v", err.FailedEmails)
|
||||
}
|
||||
|
||||
// ErrGPGInvalidTokenSignature represents a "ErrGPGInvalidTokenSignature" kind of error.
|
||||
type ErrGPGInvalidTokenSignature struct {
|
||||
Wrapped error
|
||||
ID string
|
||||
}
|
||||
|
||||
// IsErrGPGInvalidTokenSignature checks if an error is a ErrGPGInvalidTokenSignature.
|
||||
func IsErrGPGInvalidTokenSignature(err error) bool {
|
||||
_, ok := err.(ErrGPGInvalidTokenSignature)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGInvalidTokenSignature) Error() string {
|
||||
return "the provided signature does not sign the token with the provided key"
|
||||
}
|
||||
|
||||
// ErrGPGKeyParsing represents a "ErrGPGKeyParsing" kind of error.
|
||||
type ErrGPGKeyParsing struct {
|
||||
ParseError error
|
||||
}
|
||||
|
||||
// IsErrGPGKeyParsing checks if an error is a ErrGPGKeyParsing.
|
||||
func IsErrGPGKeyParsing(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyParsing)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyParsing) Error() string {
|
||||
return fmt.Sprintf("failed to parse gpg key %s", err.ParseError.Error())
|
||||
}
|
||||
|
||||
// ErrGPGKeyNotExist represents a "GPGKeyNotExist" kind of error.
|
||||
type ErrGPGKeyNotExist struct {
|
||||
ID int64
|
||||
}
|
||||
|
||||
// IsErrGPGKeyNotExist checks if an error is a ErrGPGKeyNotExist.
|
||||
func IsErrGPGKeyNotExist(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyNotExist) Error() string {
|
||||
return fmt.Sprintf("public gpg key does not exist [id: %d]", err.ID)
|
||||
}
|
||||
|
||||
// ErrGPGKeyImportNotExist represents a "GPGKeyImportNotExist" kind of error.
|
||||
type ErrGPGKeyImportNotExist struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// IsErrGPGKeyImportNotExist checks if an error is a ErrGPGKeyImportNotExist.
|
||||
func IsErrGPGKeyImportNotExist(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyImportNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyImportNotExist) Error() string {
|
||||
return fmt.Sprintf("public gpg key import does not exist [id: %s]", err.ID)
|
||||
}
|
||||
|
||||
// ErrGPGKeyIDAlreadyUsed represents a "GPGKeyIDAlreadyUsed" kind of error.
|
||||
type ErrGPGKeyIDAlreadyUsed struct {
|
||||
KeyID string
|
||||
}
|
||||
|
||||
// IsErrGPGKeyIDAlreadyUsed checks if an error is a ErrKeyNameAlreadyUsed.
|
||||
func IsErrGPGKeyIDAlreadyUsed(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyIDAlreadyUsed)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyIDAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("public key already exists [key_id: %s]", err.KeyID)
|
||||
}
|
||||
|
||||
// ErrGPGKeyAccessDenied represents a "GPGKeyAccessDenied" kind of Error.
|
||||
type ErrGPGKeyAccessDenied struct {
|
||||
UserID int64
|
||||
KeyID int64
|
||||
}
|
||||
|
||||
// IsErrGPGKeyAccessDenied checks if an error is a ErrGPGKeyAccessDenied.
|
||||
func IsErrGPGKeyAccessDenied(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyAccessDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Error pretty-prints an error of type ErrGPGKeyAccessDenied.
|
||||
func (err ErrGPGKeyAccessDenied) Error() string {
|
||||
return fmt.Sprintf("user does not have access to the key [user_id: %d, key_id: %d]",
|
||||
err.UserID, err.KeyID)
|
||||
}
|
||||
|
||||
// ErrKeyAccessDenied represents a "KeyAccessDenied" kind of error.
|
||||
type ErrKeyAccessDenied struct {
|
||||
UserID int64
|
||||
KeyID int64
|
||||
Note string
|
||||
}
|
||||
|
||||
// IsErrKeyAccessDenied checks if an error is a ErrKeyAccessDenied.
|
||||
func IsErrKeyAccessDenied(err error) bool {
|
||||
_, ok := err.(ErrKeyAccessDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// ErrDeployKeyNotExist represents a "DeployKeyNotExist" kind of error.
|
||||
type ErrDeployKeyNotExist struct {
|
||||
ID int64
|
||||
KeyID int64
|
||||
RepoID int64
|
||||
}
|
||||
|
||||
// IsErrDeployKeyNotExist checks if an error is a ErrDeployKeyNotExist.
|
||||
func IsErrDeployKeyNotExist(err error) bool {
|
||||
_, ok := err.(ErrDeployKeyNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDeployKeyNotExist) Error() string {
|
||||
return fmt.Sprintf("Deploy key does not exist [id: %d, key_id: %d, repo_id: %d]", err.ID, err.KeyID, err.RepoID)
|
||||
}
|
||||
|
||||
// ErrDeployKeyAlreadyExist represents a "DeployKeyAlreadyExist" kind of error.
|
||||
type ErrDeployKeyAlreadyExist struct {
|
||||
KeyID int64
|
||||
RepoID int64
|
||||
}
|
||||
|
||||
// IsErrDeployKeyAlreadyExist checks if an error is a ErrDeployKeyAlreadyExist.
|
||||
func IsErrDeployKeyAlreadyExist(err error) bool {
|
||||
_, ok := err.(ErrDeployKeyAlreadyExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDeployKeyAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("public key already exists [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID)
|
||||
}
|
||||
|
||||
// ErrDeployKeyNameAlreadyUsed represents a "DeployKeyNameAlreadyUsed" kind of error.
|
||||
type ErrDeployKeyNameAlreadyUsed struct {
|
||||
RepoID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsErrDeployKeyNameAlreadyUsed checks if an error is a ErrDeployKeyNameAlreadyUsed.
|
||||
func IsErrDeployKeyNameAlreadyUsed(err error) bool {
|
||||
_, ok := err.(ErrDeployKeyNameAlreadyUsed)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDeployKeyNameAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("public key with name already exists [repo_id: %d, name: %s]", err.RepoID, err.Name)
|
||||
}
|
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -63,12 +64,8 @@ func (key *GPGKey) AfterLoad(session *xorm.Session) {
|
||||
}
|
||||
|
||||
// ListGPGKeys returns a list of public keys belongs to given user.
|
||||
func ListGPGKeys(uid int64, listOptions db.ListOptions) ([]*GPGKey, error) {
|
||||
return listGPGKeys(db.GetEngine(db.DefaultContext), uid, listOptions)
|
||||
}
|
||||
|
||||
func listGPGKeys(e db.Engine, uid int64, listOptions db.ListOptions) ([]*GPGKey, error) {
|
||||
sess := e.Table(&GPGKey{}).Where("owner_id=? AND primary_key_id=''", uid)
|
||||
func ListGPGKeys(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*GPGKey, error) {
|
||||
sess := db.GetEngine(ctx).Table(&GPGKey{}).Where("owner_id=? AND primary_key_id=''", uid)
|
||||
if listOptions.Page != 0 {
|
||||
sess = db.SetSessionPagination(sess, &listOptions)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"strings"
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -70,7 +70,7 @@ const (
|
||||
)
|
||||
|
||||
// ParseCommitsWithSignature checks if signaute of commits are corresponding to users gpg keys.
|
||||
func ParseCommitsWithSignature(oldCommits []*user_model.UserCommit, repository *repo_model.Repository) []*SignCommit {
|
||||
func ParseCommitsWithSignature(oldCommits []*user_model.UserCommit, repoTrustModel repo_model.TrustModelType, isCodeReader func(*user_model.User) (bool, error)) []*SignCommit {
|
||||
newCommits := make([]*SignCommit, 0, len(oldCommits))
|
||||
keyMap := map[string]bool{}
|
||||
|
||||
@ -80,7 +80,7 @@ func ParseCommitsWithSignature(oldCommits []*user_model.UserCommit, repository *
|
||||
Verification: ParseCommitWithSignature(c.Commit),
|
||||
}
|
||||
|
||||
_ = CalculateTrustStatus(signCommit.Verification, repository, &keyMap)
|
||||
_ = CalculateTrustStatus(signCommit.Verification, repoTrustModel, isCodeReader, &keyMap)
|
||||
|
||||
newCommits = append(newCommits, signCommit)
|
||||
}
|
||||
@ -159,7 +159,7 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
|
||||
|
||||
// Now try to associate the signature with the committer, if present
|
||||
if committer.ID != 0 {
|
||||
keys, err := ListGPGKeys(committer.ID, db.ListOptions{})
|
||||
keys, err := ListGPGKeys(db.DefaultContext, committer.ID, db.ListOptions{})
|
||||
if err != nil { // Skipping failed to get gpg keys of user
|
||||
log.Error("ListGPGKeys: %v", err)
|
||||
return &CommitVerification{
|
||||
@ -448,18 +448,16 @@ func hashAndVerifyForKeyID(sig *packet.Signature, payload string, committer *use
|
||||
}
|
||||
|
||||
// CalculateTrustStatus will calculate the TrustStatus for a commit verification within a repository
|
||||
func CalculateTrustStatus(verification *CommitVerification, repository *repo_model.Repository, keyMap *map[string]bool) (err error) {
|
||||
// There are several trust models in Gitea
|
||||
func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_model.TrustModelType, isCodeReader func(*user_model.User) (bool, error), keyMap *map[string]bool) (err error) {
|
||||
if !verification.Verified {
|
||||
return
|
||||
}
|
||||
|
||||
// There are several trust models in Gitea
|
||||
trustModel := repository.GetTrustModel()
|
||||
|
||||
// In the Committer trust model a signature is trusted if it matches the committer
|
||||
// - it doesn't matter if they're a collaborator, the owner, Gitea or Github
|
||||
// NB: This model is commit verification only
|
||||
if trustModel == repo_model.CommitterTrustModel {
|
||||
if repoTrustModel == repo_model.CommitterTrustModel {
|
||||
// default to "unmatched"
|
||||
verification.TrustStatus = "unmatched"
|
||||
|
||||
@ -482,7 +480,7 @@ func CalculateTrustStatus(verification *CommitVerification, repository *repo_mod
|
||||
|
||||
// However in the repo_model.CollaboratorCommitterTrustModel we cannot mark this as trusted
|
||||
// unless the default key matches the email of a non-user.
|
||||
if trustModel == repo_model.CollaboratorCommitterTrustModel && (verification.CommittingUser.ID != 0 ||
|
||||
if repoTrustModel == repo_model.CollaboratorCommitterTrustModel && (verification.CommittingUser.ID != 0 ||
|
||||
verification.SigningUser.Email != verification.CommittingUser.Email) {
|
||||
verification.TrustStatus = "untrusted"
|
||||
}
|
||||
@ -494,11 +492,11 @@ func CalculateTrustStatus(verification *CommitVerification, repository *repo_mod
|
||||
var has bool
|
||||
isMember, has = (*keyMap)[verification.SigningKey.KeyID]
|
||||
if !has {
|
||||
isMember, err = IsOwnerMemberCollaborator(repository, verification.SigningUser.ID)
|
||||
isMember, err = isCodeReader(verification.SigningUser)
|
||||
(*keyMap)[verification.SigningKey.KeyID] = isMember
|
||||
}
|
||||
} else {
|
||||
isMember, err = IsOwnerMemberCollaborator(repository, verification.SigningUser.ID)
|
||||
isMember, err = isCodeReader(verification.SigningUser)
|
||||
}
|
||||
|
||||
if !isMember {
|
||||
@ -508,7 +506,7 @@ func CalculateTrustStatus(verification *CommitVerification, repository *repo_mod
|
||||
// This should be marked as questionable unless the signing user is a collaborator/team member etc.
|
||||
verification.TrustStatus = "unmatched"
|
||||
}
|
||||
} else if trustModel == repo_model.CollaboratorCommitterTrustModel && verification.CommittingUser.ID != verification.SigningUser.ID {
|
||||
} else if repoTrustModel == repo_model.CollaboratorCommitterTrustModel && verification.CommittingUser.ID != verification.SigningUser.ID {
|
||||
// The committing user and the signing user are not the same and our trustmodel states that they must match
|
||||
verification.TrustStatus = "unmatched"
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import "code.gitea.io/gitea/models/db"
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"testing"
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"strconv"
|
29
models/asymkey/main_test.go
Normal file
29
models/asymkey/main_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2021 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 asymkey
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
func init() {
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
setting.LoadForTest()
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, filepath.Join("..", ".."),
|
||||
"gpg_key.yml",
|
||||
"public_key.yml",
|
||||
"deploy_key.yml",
|
||||
"gpg_key_import.yml",
|
||||
"user.yml",
|
||||
"email_address.yml",
|
||||
)
|
||||
}
|
@ -3,9 +3,10 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -247,13 +248,13 @@ func UpdatePublicKeyUpdated(id int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// deletePublicKeys does the actual key deletion but does not update authorized_keys file.
|
||||
func deletePublicKeys(e db.Engine, keyIDs ...int64) error {
|
||||
// DeletePublicKeys does the actual key deletion but does not update authorized_keys file.
|
||||
func DeletePublicKeys(ctx context.Context, keyIDs ...int64) error {
|
||||
if len(keyIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := e.In("id", keyIDs).Delete(new(PublicKey))
|
||||
_, err := db.GetEngine(ctx).In("id", keyIDs).Delete(new(PublicKey))
|
||||
return err
|
||||
}
|
||||
|
||||
@ -325,40 +326,6 @@ func PublicKeyIsExternallyManaged(id int64) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
|
||||
func DeletePublicKey(doer *user_model.User, id int64) (err error) {
|
||||
key, err := GetPublicKeyByID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if user has access to delete this key.
|
||||
if !doer.IsAdmin && doer.ID != key.OwnerID {
|
||||
return ErrKeyAccessDenied{doer.ID, key.ID, "public"}
|
||||
}
|
||||
|
||||
ctx, committer, err := db.TxContext()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if err = deletePublicKeys(db.GetEngine(ctx), id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = committer.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
committer.Close()
|
||||
|
||||
if key.Type == KeyTypePrincipal {
|
||||
return RewriteAllPrincipalKeys()
|
||||
}
|
||||
|
||||
return RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
// deleteKeysMarkedForDeletion returns true if ssh keys needs update
|
||||
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||
// Start session
|
||||
@ -377,7 +344,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||
log.Error("SearchPublicKeyByContent: %v", err)
|
||||
continue
|
||||
}
|
||||
if err = deletePublicKeys(sess, key.ID); err != nil {
|
||||
if err = DeletePublicKeys(ctx, key.ID); err != nil {
|
||||
log.Error("deletePublicKeys: %v", err)
|
||||
continue
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -118,10 +118,6 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
|
||||
// Note: db.GetEngine(db.DefaultContext).Iterate does not get latest data after insert/delete, so we have to call this function
|
||||
// outside any session scope independently.
|
||||
func RewriteAllPublicKeys() error {
|
||||
return rewriteAllPublicKeys(db.GetEngine(db.DefaultContext))
|
||||
}
|
||||
|
||||
func rewriteAllPublicKeys(e db.Engine) error {
|
||||
// Don't rewrite key if internal server
|
||||
if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
|
||||
return nil
|
||||
@ -169,7 +165,7 @@ func rewriteAllPublicKeys(e db.Engine) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := regeneratePublicKeys(e, t); err != nil {
|
||||
if err := RegeneratePublicKeys(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"bufio"
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -11,8 +11,6 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"xorm.io/builder"
|
||||
@ -169,13 +167,9 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey
|
||||
}
|
||||
|
||||
// GetDeployKeyByID returns deploy key by given ID.
|
||||
func GetDeployKeyByID(id int64) (*DeployKey, error) {
|
||||
return getDeployKeyByID(db.GetEngine(db.DefaultContext), id)
|
||||
}
|
||||
|
||||
func getDeployKeyByID(e db.Engine, id int64) (*DeployKey, error) {
|
||||
func GetDeployKeyByID(ctx context.Context, id int64) (*DeployKey, error) {
|
||||
key := new(DeployKey)
|
||||
has, err := e.ID(id).Get(key)
|
||||
has, err := db.GetEngine(ctx).ID(id).Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
@ -215,68 +209,6 @@ func UpdateDeployKey(key *DeployKey) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed.
|
||||
func DeleteDeployKey(doer *user_model.User, id int64) error {
|
||||
ctx, committer, err := db.TxContext()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if err := deleteDeployKey(ctx, doer, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
func deleteDeployKey(ctx context.Context, doer *user_model.User, id int64) error {
|
||||
sess := db.GetEngine(ctx)
|
||||
key, err := getDeployKeyByID(sess, id)
|
||||
if err != nil {
|
||||
if IsErrDeployKeyNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("GetDeployKeyByID: %v", err)
|
||||
}
|
||||
|
||||
// Check if user has access to delete this key.
|
||||
if !doer.IsAdmin {
|
||||
repo, err := repo_model.GetRepositoryByIDCtx(ctx, key.RepoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("repo_model.GetRepositoryByID: %v", err)
|
||||
}
|
||||
has, err := isUserRepoAdmin(sess, repo, doer)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetUserRepoPermission: %v", err)
|
||||
} else if !has {
|
||||
return ErrKeyAccessDenied{doer.ID, key.ID, "deploy"}
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = sess.ID(key.ID).Delete(new(DeployKey)); err != nil {
|
||||
return fmt.Errorf("delete deploy key [%d]: %v", key.ID, err)
|
||||
}
|
||||
|
||||
// Check if this is the last reference to same key content.
|
||||
has, err := sess.
|
||||
Where("key_id = ?", key.KeyID).
|
||||
Get(new(DeployKey))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
if err = deletePublicKeys(sess, key.KeyID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// after deleted the public keys, should rewrite the public keys file
|
||||
if err = rewriteAllPublicKeys(sess); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListDeployKeysOptions are options for ListDeployKeys
|
||||
type ListDeployKeysOptions struct {
|
||||
db.ListOptions
|
||||
@ -300,12 +232,8 @@ func (opt ListDeployKeysOptions) toCond() builder.Cond {
|
||||
}
|
||||
|
||||
// ListDeployKeys returns a list of deploy keys matching the provided arguments.
|
||||
func ListDeployKeys(opts *ListDeployKeysOptions) ([]*DeployKey, error) {
|
||||
return listDeployKeys(db.GetEngine(db.DefaultContext), opts)
|
||||
}
|
||||
|
||||
func listDeployKeys(e db.Engine, opts *ListDeployKeysOptions) ([]*DeployKey, error) {
|
||||
sess := e.Where(opts.toCond())
|
||||
func ListDeployKeys(ctx context.Context, opts *ListDeployKeysOptions) ([]*DeployKey, error) {
|
||||
sess := db.GetEngine(ctx).Where(opts.toCond())
|
||||
|
||||
if opts.Page != 0 {
|
||||
sess = db.SetSessionPagination(sess, opts)
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"errors"
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
@ -18,6 +18,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@ -157,7 +158,7 @@ func parseKeyString(content string) (string, error) {
|
||||
// It returns the actual public key line on success.
|
||||
func CheckPublicKeyString(content string) (_ string, err error) {
|
||||
if setting.SSH.Disabled {
|
||||
return "", ErrSSHDisabled{}
|
||||
return "", db.ErrSSHDisabled{}
|
||||
}
|
||||
|
||||
content, err = parseKeyString(content)
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -76,7 +76,7 @@ func addPrincipalKey(e db.Engine, key *PublicKey) (err error) {
|
||||
// CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines
|
||||
func CheckPrincipalKeyString(user *user_model.User, content string) (_ string, err error) {
|
||||
if setting.SSH.Disabled {
|
||||
return "", ErrSSHDisabled{}
|
||||
return "", db.ErrSSHDisabled{}
|
||||
}
|
||||
|
||||
content = strings.TrimSpace(content)
|
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@ -14,11 +14,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func init() {
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
setting.LoadForTest()
|
||||
}
|
||||
|
||||
func Test_SSHParsePublicKey(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
@ -5,6 +5,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
@ -13,9 +14,12 @@ import (
|
||||
// ConvertFromGitCommit converts git commits into SignCommitWithStatuses
|
||||
func ConvertFromGitCommit(commits []*git.Commit, repo *repo_model.Repository) []*SignCommitWithStatuses {
|
||||
return ParseCommitsWithStatus(
|
||||
ParseCommitsWithSignature(
|
||||
asymkey_model.ParseCommitsWithSignature(
|
||||
user_model.ValidateCommitsWithEmails(commits),
|
||||
repo,
|
||||
repo.GetTrustModel(),
|
||||
func(user *user_model.User) (bool, error) {
|
||||
return IsUserRepoAdmin(repo, user)
|
||||
},
|
||||
),
|
||||
repo,
|
||||
)
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -328,11 +329,11 @@ func NewCommitStatus(opts NewCommitStatusOptions) error {
|
||||
type SignCommitWithStatuses struct {
|
||||
Status *CommitStatus
|
||||
Statuses []*CommitStatus
|
||||
*SignCommit
|
||||
*asymkey_model.SignCommit
|
||||
}
|
||||
|
||||
// ParseCommitsWithStatus checks commits latest statuses and calculates its worst status state
|
||||
func ParseCommitsWithStatus(oldCommits []*SignCommit, repo *repo_model.Repository) []*SignCommitWithStatuses {
|
||||
func ParseCommitsWithStatus(oldCommits []*asymkey_model.SignCommit, repo *repo_model.Repository) []*SignCommitWithStatuses {
|
||||
newCommits := make([]*SignCommitWithStatuses, 0, len(oldCommits))
|
||||
|
||||
for _, c := range oldCommits {
|
||||
|
@ -29,3 +29,16 @@ func ErrCancelledf(format string, args ...interface{}) error {
|
||||
fmt.Sprintf(format, args...),
|
||||
}
|
||||
}
|
||||
|
||||
// ErrSSHDisabled represents an "SSH disabled" error.
|
||||
type ErrSSHDisabled struct{}
|
||||
|
||||
// IsErrSSHDisabled checks if an error is a ErrSSHDisabled.
|
||||
func IsErrSSHDisabled(err error) bool {
|
||||
_, ok := err.(ErrSSHDisabled)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrSSHDisabled) Error() string {
|
||||
return "SSH is disabled"
|
||||
}
|
||||
|
277
models/error.go
277
models/error.go
@ -28,19 +28,6 @@ func (err ErrNotExist) Error() string {
|
||||
return fmt.Sprintf("record does not exist [id: %d]", err.ID)
|
||||
}
|
||||
|
||||
// ErrSSHDisabled represents an "SSH disabled" error.
|
||||
type ErrSSHDisabled struct{}
|
||||
|
||||
// IsErrSSHDisabled checks if an error is a ErrSSHDisabled.
|
||||
func IsErrSSHDisabled(err error) bool {
|
||||
_, ok := err.(ErrSSHDisabled)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrSSHDisabled) Error() string {
|
||||
return "SSH is disabled"
|
||||
}
|
||||
|
||||
// ErrUserOwnRepos represents a "UserOwnRepos" kind of error.
|
||||
type ErrUserOwnRepos struct {
|
||||
UID int64
|
||||
@ -151,254 +138,6 @@ func (err ErrWikiInvalidFileName) Error() string {
|
||||
return fmt.Sprintf("Invalid wiki filename: %s", err.FileName)
|
||||
}
|
||||
|
||||
// __________ ___. .__ .__ ____ __.
|
||||
// \______ \__ _\_ |__ | | |__| ____ | |/ _|____ ___.__.
|
||||
// | ___/ | \ __ \| | | |/ ___\ | <_/ __ < | |
|
||||
// | | | | / \_\ \ |_| \ \___ | | \ ___/\___ |
|
||||
// |____| |____/|___ /____/__|\___ > |____|__ \___ > ____|
|
||||
// \/ \/ \/ \/\/
|
||||
|
||||
// ErrKeyUnableVerify represents a "KeyUnableVerify" kind of error.
|
||||
type ErrKeyUnableVerify struct {
|
||||
Result string
|
||||
}
|
||||
|
||||
// IsErrKeyUnableVerify checks if an error is a ErrKeyUnableVerify.
|
||||
func IsErrKeyUnableVerify(err error) bool {
|
||||
_, ok := err.(ErrKeyUnableVerify)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyUnableVerify) Error() string {
|
||||
return fmt.Sprintf("Unable to verify key content [result: %s]", err.Result)
|
||||
}
|
||||
|
||||
// ErrKeyNotExist represents a "KeyNotExist" kind of error.
|
||||
type ErrKeyNotExist struct {
|
||||
ID int64
|
||||
}
|
||||
|
||||
// IsErrKeyNotExist checks if an error is a ErrKeyNotExist.
|
||||
func IsErrKeyNotExist(err error) bool {
|
||||
_, ok := err.(ErrKeyNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyNotExist) Error() string {
|
||||
return fmt.Sprintf("public key does not exist [id: %d]", err.ID)
|
||||
}
|
||||
|
||||
// ErrKeyAlreadyExist represents a "KeyAlreadyExist" kind of error.
|
||||
type ErrKeyAlreadyExist struct {
|
||||
OwnerID int64
|
||||
Fingerprint string
|
||||
Content string
|
||||
}
|
||||
|
||||
// IsErrKeyAlreadyExist checks if an error is a ErrKeyAlreadyExist.
|
||||
func IsErrKeyAlreadyExist(err error) bool {
|
||||
_, ok := err.(ErrKeyAlreadyExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("public key already exists [owner_id: %d, finger_print: %s, content: %s]",
|
||||
err.OwnerID, err.Fingerprint, err.Content)
|
||||
}
|
||||
|
||||
// ErrKeyNameAlreadyUsed represents a "KeyNameAlreadyUsed" kind of error.
|
||||
type ErrKeyNameAlreadyUsed struct {
|
||||
OwnerID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsErrKeyNameAlreadyUsed checks if an error is a ErrKeyNameAlreadyUsed.
|
||||
func IsErrKeyNameAlreadyUsed(err error) bool {
|
||||
_, ok := err.(ErrKeyNameAlreadyUsed)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrKeyNameAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
|
||||
}
|
||||
|
||||
// ErrGPGNoEmailFound represents a "ErrGPGNoEmailFound" kind of error.
|
||||
type ErrGPGNoEmailFound struct {
|
||||
FailedEmails []string
|
||||
ID string
|
||||
}
|
||||
|
||||
// IsErrGPGNoEmailFound checks if an error is a ErrGPGNoEmailFound.
|
||||
func IsErrGPGNoEmailFound(err error) bool {
|
||||
_, ok := err.(ErrGPGNoEmailFound)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGNoEmailFound) Error() string {
|
||||
return fmt.Sprintf("none of the emails attached to the GPG key could be found: %v", err.FailedEmails)
|
||||
}
|
||||
|
||||
// ErrGPGInvalidTokenSignature represents a "ErrGPGInvalidTokenSignature" kind of error.
|
||||
type ErrGPGInvalidTokenSignature struct {
|
||||
Wrapped error
|
||||
ID string
|
||||
}
|
||||
|
||||
// IsErrGPGInvalidTokenSignature checks if an error is a ErrGPGInvalidTokenSignature.
|
||||
func IsErrGPGInvalidTokenSignature(err error) bool {
|
||||
_, ok := err.(ErrGPGInvalidTokenSignature)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGInvalidTokenSignature) Error() string {
|
||||
return "the provided signature does not sign the token with the provided key"
|
||||
}
|
||||
|
||||
// ErrGPGKeyParsing represents a "ErrGPGKeyParsing" kind of error.
|
||||
type ErrGPGKeyParsing struct {
|
||||
ParseError error
|
||||
}
|
||||
|
||||
// IsErrGPGKeyParsing checks if an error is a ErrGPGKeyParsing.
|
||||
func IsErrGPGKeyParsing(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyParsing)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyParsing) Error() string {
|
||||
return fmt.Sprintf("failed to parse gpg key %s", err.ParseError.Error())
|
||||
}
|
||||
|
||||
// ErrGPGKeyNotExist represents a "GPGKeyNotExist" kind of error.
|
||||
type ErrGPGKeyNotExist struct {
|
||||
ID int64
|
||||
}
|
||||
|
||||
// IsErrGPGKeyNotExist checks if an error is a ErrGPGKeyNotExist.
|
||||
func IsErrGPGKeyNotExist(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyNotExist) Error() string {
|
||||
return fmt.Sprintf("public gpg key does not exist [id: %d]", err.ID)
|
||||
}
|
||||
|
||||
// ErrGPGKeyImportNotExist represents a "GPGKeyImportNotExist" kind of error.
|
||||
type ErrGPGKeyImportNotExist struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// IsErrGPGKeyImportNotExist checks if an error is a ErrGPGKeyImportNotExist.
|
||||
func IsErrGPGKeyImportNotExist(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyImportNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyImportNotExist) Error() string {
|
||||
return fmt.Sprintf("public gpg key import does not exist [id: %s]", err.ID)
|
||||
}
|
||||
|
||||
// ErrGPGKeyIDAlreadyUsed represents a "GPGKeyIDAlreadyUsed" kind of error.
|
||||
type ErrGPGKeyIDAlreadyUsed struct {
|
||||
KeyID string
|
||||
}
|
||||
|
||||
// IsErrGPGKeyIDAlreadyUsed checks if an error is a ErrKeyNameAlreadyUsed.
|
||||
func IsErrGPGKeyIDAlreadyUsed(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyIDAlreadyUsed)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyIDAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("public key already exists [key_id: %s]", err.KeyID)
|
||||
}
|
||||
|
||||
// ErrGPGKeyAccessDenied represents a "GPGKeyAccessDenied" kind of Error.
|
||||
type ErrGPGKeyAccessDenied struct {
|
||||
UserID int64
|
||||
KeyID int64
|
||||
}
|
||||
|
||||
// IsErrGPGKeyAccessDenied checks if an error is a ErrGPGKeyAccessDenied.
|
||||
func IsErrGPGKeyAccessDenied(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyAccessDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Error pretty-prints an error of type ErrGPGKeyAccessDenied.
|
||||
func (err ErrGPGKeyAccessDenied) Error() string {
|
||||
return fmt.Sprintf("user does not have access to the key [user_id: %d, key_id: %d]",
|
||||
err.UserID, err.KeyID)
|
||||
}
|
||||
|
||||
// ErrKeyAccessDenied represents a "KeyAccessDenied" kind of error.
|
||||
type ErrKeyAccessDenied struct {
|
||||
UserID int64
|
||||
KeyID int64
|
||||
Note string
|
||||
}
|
||||
|
||||
// IsErrKeyAccessDenied checks if an error is a ErrKeyAccessDenied.
|
||||
func IsErrKeyAccessDenied(err error) bool {
|
||||
_, ok := err.(ErrKeyAccessDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// ErrDeployKeyNotExist represents a "DeployKeyNotExist" kind of error.
|
||||
type ErrDeployKeyNotExist struct {
|
||||
ID int64
|
||||
KeyID int64
|
||||
RepoID int64
|
||||
}
|
||||
|
||||
// IsErrDeployKeyNotExist checks if an error is a ErrDeployKeyNotExist.
|
||||
func IsErrDeployKeyNotExist(err error) bool {
|
||||
_, ok := err.(ErrDeployKeyNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDeployKeyNotExist) Error() string {
|
||||
return fmt.Sprintf("Deploy key does not exist [id: %d, key_id: %d, repo_id: %d]", err.ID, err.KeyID, err.RepoID)
|
||||
}
|
||||
|
||||
// ErrDeployKeyAlreadyExist represents a "DeployKeyAlreadyExist" kind of error.
|
||||
type ErrDeployKeyAlreadyExist struct {
|
||||
KeyID int64
|
||||
RepoID int64
|
||||
}
|
||||
|
||||
// IsErrDeployKeyAlreadyExist checks if an error is a ErrDeployKeyAlreadyExist.
|
||||
func IsErrDeployKeyAlreadyExist(err error) bool {
|
||||
_, ok := err.(ErrDeployKeyAlreadyExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDeployKeyAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("public key already exists [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID)
|
||||
}
|
||||
|
||||
// ErrDeployKeyNameAlreadyUsed represents a "DeployKeyNameAlreadyUsed" kind of error.
|
||||
type ErrDeployKeyNameAlreadyUsed struct {
|
||||
RepoID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsErrDeployKeyNameAlreadyUsed checks if an error is a ErrDeployKeyNameAlreadyUsed.
|
||||
func IsErrDeployKeyNameAlreadyUsed(err error) bool {
|
||||
_, ok := err.(ErrDeployKeyNameAlreadyUsed)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDeployKeyNameAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("public key with name already exists [repo_id: %d, name: %s]", err.RepoID, err.Name)
|
||||
}
|
||||
|
||||
// _____ ___________ __
|
||||
// / _ \ ____ ____ ____ ______ _____\__ ___/___ | | __ ____ ____
|
||||
// / /_\ \_/ ___\/ ___\/ __ \ / ___// ___/ | | / _ \| |/ // __ \ / \
|
||||
@ -878,22 +617,6 @@ func (err ErrUserDoesNotHaveAccessToRepo) Error() string {
|
||||
return fmt.Sprintf("user doesn't have access to repo [user_id: %d, repo_name: %s]", err.UserID, err.RepoName)
|
||||
}
|
||||
|
||||
// ErrWontSign explains the first reason why a commit would not be signed
|
||||
// There may be other reasons - this is just the first reason found
|
||||
type ErrWontSign struct {
|
||||
Reason signingMode
|
||||
}
|
||||
|
||||
func (e *ErrWontSign) Error() string {
|
||||
return fmt.Sprintf("wont sign: %s", e.Reason)
|
||||
}
|
||||
|
||||
// IsErrWontSign checks if an error is a ErrWontSign
|
||||
func IsErrWontSign(err error) bool {
|
||||
_, ok := err.(*ErrWontSign)
|
||||
return ok
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \____________ ____ ____ | |__
|
||||
// | | _/\_ __ \__ \ / \_/ ___\| | \
|
||||
|
@ -10,10 +10,16 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func init() {
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
setting.LoadForTest()
|
||||
}
|
||||
|
||||
// TestFixturesAreConsistent assert that test fixtures are consistent
|
||||
func TestFixturesAreConsistent(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
@ -1,133 +0,0 @@
|
||||
// Copyright 2019 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 models
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/login"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
// SignMerge determines if we should sign a PR merge commit to the base repository
|
||||
func (pr *PullRequest) SignMerge(u *user_model.User, tmpBasePath, baseCommit, headCommit string) (bool, string, *git.Signature, error) {
|
||||
if err := pr.LoadBaseRepo(); err != nil {
|
||||
log.Error("Unable to get Base Repo for pull request")
|
||||
return false, "", nil, err
|
||||
}
|
||||
repo := pr.BaseRepo
|
||||
|
||||
signingKey, signer := SigningKey(repo.RepoPath())
|
||||
if signingKey == "" {
|
||||
return false, "", nil, &ErrWontSign{noKey}
|
||||
}
|
||||
rules := signingModeFromStrings(setting.Repository.Signing.Merges)
|
||||
|
||||
var gitRepo *git.Repository
|
||||
var err error
|
||||
|
||||
Loop:
|
||||
for _, rule := range rules {
|
||||
switch rule {
|
||||
case never:
|
||||
return false, "", nil, &ErrWontSign{never}
|
||||
case always:
|
||||
break Loop
|
||||
case pubkey:
|
||||
keys, err := ListGPGKeys(u.ID, db.ListOptions{})
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return false, "", nil, &ErrWontSign{pubkey}
|
||||
}
|
||||
case twofa:
|
||||
twofaModel, err := login.GetTwoFactorByUID(u.ID)
|
||||
if err != nil && !login.IsErrTwoFactorNotEnrolled(err) {
|
||||
return false, "", nil, err
|
||||
}
|
||||
if twofaModel == nil {
|
||||
return false, "", nil, &ErrWontSign{twofa}
|
||||
}
|
||||
case approved:
|
||||
protectedBranch, err := GetProtectedBranchBy(repo.ID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
if protectedBranch == nil {
|
||||
return false, "", nil, &ErrWontSign{approved}
|
||||
}
|
||||
if protectedBranch.GetGrantedApprovalsCount(pr) < 1 {
|
||||
return false, "", nil, &ErrWontSign{approved}
|
||||
}
|
||||
case baseSigned:
|
||||
if gitRepo == nil {
|
||||
gitRepo, err = git.OpenRepository(tmpBasePath)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
}
|
||||
commit, err := gitRepo.GetCommit(baseCommit)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
verification := ParseCommitWithSignature(commit)
|
||||
if !verification.Verified {
|
||||
return false, "", nil, &ErrWontSign{baseSigned}
|
||||
}
|
||||
case headSigned:
|
||||
if gitRepo == nil {
|
||||
gitRepo, err = git.OpenRepository(tmpBasePath)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
}
|
||||
commit, err := gitRepo.GetCommit(headCommit)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
verification := ParseCommitWithSignature(commit)
|
||||
if !verification.Verified {
|
||||
return false, "", nil, &ErrWontSign{headSigned}
|
||||
}
|
||||
case commitsSigned:
|
||||
if gitRepo == nil {
|
||||
gitRepo, err = git.OpenRepository(tmpBasePath)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
}
|
||||
commit, err := gitRepo.GetCommit(headCommit)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
verification := ParseCommitWithSignature(commit)
|
||||
if !verification.Verified {
|
||||
return false, "", nil, &ErrWontSign{commitsSigned}
|
||||
}
|
||||
// need to work out merge-base
|
||||
mergeBaseCommit, _, err := gitRepo.GetMergeBase("", baseCommit, headCommit)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
commitList, err := commit.CommitsBeforeUntil(mergeBaseCommit)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
for _, commit := range commitList {
|
||||
verification := ParseCommitWithSignature(commit)
|
||||
if !verification.Verified {
|
||||
return false, "", nil, &ErrWontSign{commitsSigned}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, signingKey, signer, nil
|
||||
}
|
@ -20,6 +20,7 @@ import (
|
||||
_ "image/jpeg" // Needed for jpeg support
|
||||
|
||||
admin_model "code.gitea.io/gitea/models/admin"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -856,12 +857,13 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
||||
}
|
||||
|
||||
// Delete Deploy Keys
|
||||
deployKeys, err := listDeployKeys(sess, &ListDeployKeysOptions{RepoID: repoID})
|
||||
deployKeys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: repoID})
|
||||
if err != nil {
|
||||
return fmt.Errorf("listDeployKeys: %v", err)
|
||||
}
|
||||
var needRewriteKeysFile = len(deployKeys) > 0
|
||||
for _, dKey := range deployKeys {
|
||||
if err := deleteDeployKey(ctx, doer, dKey.ID); err != nil {
|
||||
if err := DeleteDeployKey(ctx, doer, dKey.ID); err != nil {
|
||||
return fmt.Errorf("deleteDeployKeys: %v", err)
|
||||
}
|
||||
}
|
||||
@ -1049,6 +1051,12 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
||||
|
||||
committer.Close()
|
||||
|
||||
if needRewriteKeysFile {
|
||||
if err := asymkey_model.RewriteAllPublicKeys(); err != nil {
|
||||
log.Error("RewriteAllPublicKeys failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// We should always delete the files after the database transaction succeed. If
|
||||
// we delete the file but the database rollback, the repository will be broken.
|
||||
|
||||
@ -1407,3 +1415,52 @@ func LinkedRepository(a *repo_model.Attachment) (*repo_model.Repository, unit.Ty
|
||||
}
|
||||
return nil, -1, nil
|
||||
}
|
||||
|
||||
// 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: %v", err)
|
||||
}
|
||||
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
// Check if user has access to delete this key.
|
||||
if !doer.IsAdmin {
|
||||
repo, err := repo_model.GetRepositoryByIDCtx(ctx, key.RepoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetRepositoryByID: %v", err)
|
||||
}
|
||||
has, err := isUserRepoAdmin(sess, repo, doer)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetUserRepoPermission: %v", err)
|
||||
} else if !has {
|
||||
return asymkey_model.ErrKeyAccessDenied{
|
||||
UserID: doer.ID,
|
||||
KeyID: key.ID,
|
||||
Note: "deploy",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = sess.ID(key.ID).Delete(new(asymkey_model.DeployKey)); err != nil {
|
||||
return fmt.Errorf("delete deploy key [%d]: %v", key.ID, err)
|
||||
}
|
||||
|
||||
// Check if this is the last reference to same key content.
|
||||
has, err := sess.
|
||||
Where("key_id = ?", key.KeyID).
|
||||
Get(new(asymkey_model.DeployKey))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
if err = asymkey_model.DeletePublicKeys(ctx, key.KeyID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user