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
75 changed files with 1001 additions and 887 deletions
|
@ -14,6 +14,7 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -625,7 +626,7 @@ func runRegenerateKeys(_ *cli.Context) error {
|
||||||
if err := initDB(ctx); err != nil {
|
if err := initDB(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return models.RewriteAllPublicKeys()
|
return asymkey_model.RewriteAllPublicKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"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)
|
return fail("Internal error", "Failed to check provided key: %v", err)
|
||||||
}
|
}
|
||||||
switch key.Type {
|
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.")
|
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.")
|
println("Hi there! You've successfully authenticated with the principal " + key.Content + ", but Gitea does not provide shell access.")
|
||||||
default:
|
default:
|
||||||
println("Hi there, " + user.Name + "! You've successfully authenticated with the key named " + key.Name + ", but Gitea does not provide shell access.")
|
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_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_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_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_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_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
|
- `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"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
@ -34,7 +34,7 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||||
|
|
||||||
var newPublicKey api.PublicKey
|
var newPublicKey api.PublicKey
|
||||||
DecodeJSON(t, resp, &newPublicKey)
|
DecodeJSON(t, resp, &newPublicKey)
|
||||||
unittest.AssertExistsAndLoadBean(t, &models.PublicKey{
|
unittest.AssertExistsAndLoadBean(t, &asymkey_model.PublicKey{
|
||||||
ID: newPublicKey.ID,
|
ID: newPublicKey.ID,
|
||||||
Name: newPublicKey.Title,
|
Name: newPublicKey.Title,
|
||||||
Content: newPublicKey.Key,
|
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",
|
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
|
||||||
keyOwner.Name, newPublicKey.ID, token)
|
keyOwner.Name, newPublicKey.ID, token)
|
||||||
session.MakeRequest(t, req, http.StatusNoContent)
|
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) {
|
func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -65,7 +65,7 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
|
||||||
|
|
||||||
var newDeployKey api.DeployKey
|
var newDeployKey api.DeployKey
|
||||||
DecodeJSON(t, resp, &newDeployKey)
|
DecodeJSON(t, resp, &newDeployKey)
|
||||||
unittest.AssertExistsAndLoadBean(t, &models.DeployKey{
|
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||||
ID: newDeployKey.ID,
|
ID: newDeployKey.ID,
|
||||||
Name: rawKeyBody.Title,
|
Name: rawKeyBody.Title,
|
||||||
Content: rawKeyBody.Key,
|
Content: rawKeyBody.Key,
|
||||||
|
@ -90,7 +90,7 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
|
||||||
|
|
||||||
var newDeployKey api.DeployKey
|
var newDeployKey api.DeployKey
|
||||||
DecodeJSON(t, resp, &newDeployKey)
|
DecodeJSON(t, resp, &newDeployKey)
|
||||||
unittest.AssertExistsAndLoadBean(t, &models.DeployKey{
|
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||||
ID: newDeployKey.ID,
|
ID: newDeployKey.ID,
|
||||||
Name: rawKeyBody.Title,
|
Name: rawKeyBody.Title,
|
||||||
Content: rawKeyBody.Key,
|
Content: rawKeyBody.Key,
|
||||||
|
@ -116,7 +116,7 @@ func TestCreateUserKey(t *testing.T) {
|
||||||
|
|
||||||
var newPublicKey api.PublicKey
|
var newPublicKey api.PublicKey
|
||||||
DecodeJSON(t, resp, &newPublicKey)
|
DecodeJSON(t, resp, &newPublicKey)
|
||||||
unittest.AssertExistsAndLoadBean(t, &models.PublicKey{
|
unittest.AssertExistsAndLoadBean(t, &asymkey_model.PublicKey{
|
||||||
ID: newPublicKey.ID,
|
ID: newPublicKey.ID,
|
||||||
OwnerID: user.ID,
|
OwnerID: user.ID,
|
||||||
Name: rawKeyBody.Title,
|
Name: rawKeyBody.Title,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/modules/private"
|
"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, int64(1), key.ID)
|
||||||
assert.Equal(t, "user2@localhost", key.Name)
|
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)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
key, user, err = private.ServNoCommand(ctx, deployKey.KeyID)
|
key, user, err = private.ServNoCommand(ctx, deployKey.KeyID)
|
||||||
|
@ -85,7 +85,7 @@ func TestAPIPrivateServ(t *testing.T) {
|
||||||
assert.Empty(t, results)
|
assert.Empty(t, results)
|
||||||
|
|
||||||
// Add reading deploy key
|
// 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)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Can pull from repo we're a deploy key for
|
// Can pull from repo we're a deploy key for
|
||||||
|
@ -117,7 +117,7 @@ func TestAPIPrivateServ(t *testing.T) {
|
||||||
assert.Empty(t, results)
|
assert.Empty(t, results)
|
||||||
|
|
||||||
// Add writing deploy key
|
// 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)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Cannot push to a private repo with reading key
|
// 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
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -63,12 +64,8 @@ func (key *GPGKey) AfterLoad(session *xorm.Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListGPGKeys returns a list of public keys belongs to given user.
|
// ListGPGKeys returns a list of public keys belongs to given user.
|
||||||
func ListGPGKeys(uid int64, listOptions db.ListOptions) ([]*GPGKey, error) {
|
func ListGPGKeys(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*GPGKey, error) {
|
||||||
return listGPGKeys(db.GetEngine(db.DefaultContext), uid, listOptions)
|
sess := db.GetEngine(ctx).Table(&GPGKey{}).Where("owner_id=? AND primary_key_id=''", uid)
|
||||||
}
|
|
||||||
|
|
||||||
func listGPGKeys(e db.Engine, uid int64, listOptions db.ListOptions) ([]*GPGKey, error) {
|
|
||||||
sess := e.Table(&GPGKey{}).Where("owner_id=? AND primary_key_id=''", uid)
|
|
||||||
if listOptions.Page != 0 {
|
if listOptions.Page != 0 {
|
||||||
sess = db.SetSessionPagination(sess, &listOptions)
|
sess = db.SetSessionPagination(sess, &listOptions)
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -70,7 +70,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseCommitsWithSignature checks if signaute of commits are corresponding to users gpg keys.
|
// 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))
|
newCommits := make([]*SignCommit, 0, len(oldCommits))
|
||||||
keyMap := map[string]bool{}
|
keyMap := map[string]bool{}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ func ParseCommitsWithSignature(oldCommits []*user_model.UserCommit, repository *
|
||||||
Verification: ParseCommitWithSignature(c.Commit),
|
Verification: ParseCommitWithSignature(c.Commit),
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = CalculateTrustStatus(signCommit.Verification, repository, &keyMap)
|
_ = CalculateTrustStatus(signCommit.Verification, repoTrustModel, isCodeReader, &keyMap)
|
||||||
|
|
||||||
newCommits = append(newCommits, signCommit)
|
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
|
// Now try to associate the signature with the committer, if present
|
||||||
if committer.ID != 0 {
|
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
|
if err != nil { // Skipping failed to get gpg keys of user
|
||||||
log.Error("ListGPGKeys: %v", err)
|
log.Error("ListGPGKeys: %v", err)
|
||||||
return &CommitVerification{
|
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
|
// 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 {
|
if !verification.Verified {
|
||||||
return
|
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
|
// 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
|
// - it doesn't matter if they're a collaborator, the owner, Gitea or Github
|
||||||
// NB: This model is commit verification only
|
// NB: This model is commit verification only
|
||||||
if trustModel == repo_model.CommitterTrustModel {
|
if repoTrustModel == repo_model.CommitterTrustModel {
|
||||||
// default to "unmatched"
|
// default to "unmatched"
|
||||||
verification.TrustStatus = "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
|
// However in the repo_model.CollaboratorCommitterTrustModel we cannot mark this as trusted
|
||||||
// unless the default key matches the email of a non-user.
|
// 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.SigningUser.Email != verification.CommittingUser.Email) {
|
||||||
verification.TrustStatus = "untrusted"
|
verification.TrustStatus = "untrusted"
|
||||||
}
|
}
|
||||||
|
@ -494,11 +492,11 @@ func CalculateTrustStatus(verification *CommitVerification, repository *repo_mod
|
||||||
var has bool
|
var has bool
|
||||||
isMember, has = (*keyMap)[verification.SigningKey.KeyID]
|
isMember, has = (*keyMap)[verification.SigningKey.KeyID]
|
||||||
if !has {
|
if !has {
|
||||||
isMember, err = IsOwnerMemberCollaborator(repository, verification.SigningUser.ID)
|
isMember, err = isCodeReader(verification.SigningUser)
|
||||||
(*keyMap)[verification.SigningKey.KeyID] = isMember
|
(*keyMap)[verification.SigningKey.KeyID] = isMember
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
isMember, err = IsOwnerMemberCollaborator(repository, verification.SigningUser.ID)
|
isMember, err = isCodeReader(verification.SigningUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isMember {
|
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.
|
// This should be marked as questionable unless the signing user is a collaborator/team member etc.
|
||||||
verification.TrustStatus = "unmatched"
|
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
|
// The committing user and the signing user are not the same and our trustmodel states that they must match
|
||||||
verification.TrustStatus = "unmatched"
|
verification.TrustStatus = "unmatched"
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import "code.gitea.io/gitea/models/db"
|
import "code.gitea.io/gitea/models/db"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"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
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -247,13 +248,13 @@ func UpdatePublicKeyUpdated(id int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// deletePublicKeys does the actual key deletion but does not update authorized_keys file.
|
// DeletePublicKeys does the actual key deletion but does not update authorized_keys file.
|
||||||
func deletePublicKeys(e db.Engine, keyIDs ...int64) error {
|
func DeletePublicKeys(ctx context.Context, keyIDs ...int64) error {
|
||||||
if len(keyIDs) == 0 {
|
if len(keyIDs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := e.In("id", keyIDs).Delete(new(PublicKey))
|
_, err := db.GetEngine(ctx).In("id", keyIDs).Delete(new(PublicKey))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,40 +326,6 @@ func PublicKeyIsExternallyManaged(id int64) (bool, error) {
|
||||||
return false, nil
|
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
|
// deleteKeysMarkedForDeletion returns true if ssh keys needs update
|
||||||
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||||
// Start session
|
// Start session
|
||||||
|
@ -377,7 +344,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||||
log.Error("SearchPublicKeyByContent: %v", err)
|
log.Error("SearchPublicKeyByContent: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err = deletePublicKeys(sess, key.ID); err != nil {
|
if err = DeletePublicKeys(ctx, key.ID); err != nil {
|
||||||
log.Error("deletePublicKeys: %v", err)
|
log.Error("deletePublicKeys: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"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
|
// 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.
|
// outside any session scope independently.
|
||||||
func RewriteAllPublicKeys() error {
|
func RewriteAllPublicKeys() error {
|
||||||
return rewriteAllPublicKeys(db.GetEngine(db.DefaultContext))
|
|
||||||
}
|
|
||||||
|
|
||||||
func rewriteAllPublicKeys(e db.Engine) error {
|
|
||||||
// Don't rewrite key if internal server
|
// Don't rewrite key if internal server
|
||||||
if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
|
if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
|
||||||
return nil
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -11,8 +11,6 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"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"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
|
@ -169,13 +167,9 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDeployKeyByID returns deploy key by given ID.
|
// GetDeployKeyByID returns deploy key by given ID.
|
||||||
func GetDeployKeyByID(id int64) (*DeployKey, error) {
|
func GetDeployKeyByID(ctx context.Context, id int64) (*DeployKey, error) {
|
||||||
return getDeployKeyByID(db.GetEngine(db.DefaultContext), id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDeployKeyByID(e db.Engine, id int64) (*DeployKey, error) {
|
|
||||||
key := new(DeployKey)
|
key := new(DeployKey)
|
||||||
has, err := e.ID(id).Get(key)
|
has, err := db.GetEngine(ctx).ID(id).Get(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
|
@ -215,68 +209,6 @@ func UpdateDeployKey(key *DeployKey) error {
|
||||||
return err
|
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
|
// ListDeployKeysOptions are options for ListDeployKeys
|
||||||
type ListDeployKeysOptions struct {
|
type ListDeployKeysOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
|
@ -300,12 +232,8 @@ func (opt ListDeployKeysOptions) toCond() builder.Cond {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListDeployKeys returns a list of deploy keys matching the provided arguments.
|
// ListDeployKeys returns a list of deploy keys matching the provided arguments.
|
||||||
func ListDeployKeys(opts *ListDeployKeysOptions) ([]*DeployKey, error) {
|
func ListDeployKeys(ctx context.Context, opts *ListDeployKeysOptions) ([]*DeployKey, error) {
|
||||||
return listDeployKeys(db.GetEngine(db.DefaultContext), opts)
|
sess := db.GetEngine(ctx).Where(opts.toCond())
|
||||||
}
|
|
||||||
|
|
||||||
func listDeployKeys(e db.Engine, opts *ListDeployKeysOptions) ([]*DeployKey, error) {
|
|
||||||
sess := e.Where(opts.toCond())
|
|
||||||
|
|
||||||
if opts.Page != 0 {
|
if opts.Page != 0 {
|
||||||
sess = db.SetSessionPagination(sess, opts)
|
sess = db.SetSessionPagination(sess, opts)
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
@ -18,6 +18,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/process"
|
"code.gitea.io/gitea/modules/process"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"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.
|
// It returns the actual public key line on success.
|
||||||
func CheckPublicKeyString(content string) (_ string, err error) {
|
func CheckPublicKeyString(content string) (_ string, err error) {
|
||||||
if setting.SSH.Disabled {
|
if setting.SSH.Disabled {
|
||||||
return "", ErrSSHDisabled{}
|
return "", db.ErrSSHDisabled{}
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err = parseKeyString(content)
|
content, err = parseKeyString(content)
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"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
|
// CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines
|
||||||
func CheckPrincipalKeyString(user *user_model.User, content string) (_ string, err error) {
|
func CheckPrincipalKeyString(user *user_model.User, content string) (_ string, err error) {
|
||||||
if setting.SSH.Disabled {
|
if setting.SSH.Disabled {
|
||||||
return "", ErrSSHDisabled{}
|
return "", db.ErrSSHDisabled{}
|
||||||
}
|
}
|
||||||
|
|
||||||
content = strings.TrimSpace(content)
|
content = strings.TrimSpace(content)
|
|
@ -3,7 +3,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -14,11 +14,6 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
setting.SetCustomPathAndConf("", "", "")
|
|
||||||
setting.LoadForTest()
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_SSHParsePublicKey(t *testing.T) {
|
func Test_SSHParsePublicKey(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
|
@ -5,6 +5,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -13,9 +14,12 @@ import (
|
||||||
// ConvertFromGitCommit converts git commits into SignCommitWithStatuses
|
// ConvertFromGitCommit converts git commits into SignCommitWithStatuses
|
||||||
func ConvertFromGitCommit(commits []*git.Commit, repo *repo_model.Repository) []*SignCommitWithStatuses {
|
func ConvertFromGitCommit(commits []*git.Commit, repo *repo_model.Repository) []*SignCommitWithStatuses {
|
||||||
return ParseCommitsWithStatus(
|
return ParseCommitsWithStatus(
|
||||||
ParseCommitsWithSignature(
|
asymkey_model.ParseCommitsWithSignature(
|
||||||
user_model.ValidateCommitsWithEmails(commits),
|
user_model.ValidateCommitsWithEmails(commits),
|
||||||
repo,
|
repo.GetTrustModel(),
|
||||||
|
func(user *user_model.User) (bool, error) {
|
||||||
|
return IsUserRepoAdmin(repo, user)
|
||||||
|
},
|
||||||
),
|
),
|
||||||
repo,
|
repo,
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -328,11 +329,11 @@ func NewCommitStatus(opts NewCommitStatusOptions) error {
|
||||||
type SignCommitWithStatuses struct {
|
type SignCommitWithStatuses struct {
|
||||||
Status *CommitStatus
|
Status *CommitStatus
|
||||||
Statuses []*CommitStatus
|
Statuses []*CommitStatus
|
||||||
*SignCommit
|
*asymkey_model.SignCommit
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseCommitsWithStatus checks commits latest statuses and calculates its worst status state
|
// 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))
|
newCommits := make([]*SignCommitWithStatuses, 0, len(oldCommits))
|
||||||
|
|
||||||
for _, c := range oldCommits {
|
for _, c := range oldCommits {
|
||||||
|
|
|
@ -29,3 +29,16 @@ func ErrCancelledf(format string, args ...interface{}) error {
|
||||||
fmt.Sprintf(format, args...),
|
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)
|
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.
|
// ErrUserOwnRepos represents a "UserOwnRepos" kind of error.
|
||||||
type ErrUserOwnRepos struct {
|
type ErrUserOwnRepos struct {
|
||||||
UID int64
|
UID int64
|
||||||
|
@ -151,254 +138,6 @@ func (err ErrWikiInvalidFileName) Error() string {
|
||||||
return fmt.Sprintf("Invalid wiki filename: %s", err.FileName)
|
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)
|
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"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
setting.SetCustomPathAndConf("", "", "")
|
||||||
|
setting.LoadForTest()
|
||||||
|
}
|
||||||
|
|
||||||
// TestFixturesAreConsistent assert that test fixtures are consistent
|
// TestFixturesAreConsistent assert that test fixtures are consistent
|
||||||
func TestFixturesAreConsistent(t *testing.T) {
|
func TestFixturesAreConsistent(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
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
|
_ "image/jpeg" // Needed for jpeg support
|
||||||
|
|
||||||
admin_model "code.gitea.io/gitea/models/admin"
|
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/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
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
|
// Delete Deploy Keys
|
||||||
deployKeys, err := listDeployKeys(sess, &ListDeployKeysOptions{RepoID: repoID})
|
deployKeys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: repoID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("listDeployKeys: %v", err)
|
return fmt.Errorf("listDeployKeys: %v", err)
|
||||||
}
|
}
|
||||||
|
var needRewriteKeysFile = len(deployKeys) > 0
|
||||||
for _, dKey := range deployKeys {
|
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)
|
return fmt.Errorf("deleteDeployKeys: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1049,6 +1051,12 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
||||||
|
|
||||||
committer.Close()
|
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 should always delete the files after the database transaction succeed. If
|
||||||
// we delete the file but the database rollback, the repository will be broken.
|
// 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
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
@ -47,7 +48,7 @@ func GetStatistic() (stats Statistic) {
|
||||||
e := db.GetEngine(db.DefaultContext)
|
e := db.GetEngine(db.DefaultContext)
|
||||||
stats.Counter.User = user_model.CountUsers()
|
stats.Counter.User = user_model.CountUsers()
|
||||||
stats.Counter.Org = CountOrganizations()
|
stats.Counter.Org = CountOrganizations()
|
||||||
stats.Counter.PublicKey, _ = e.Count(new(PublicKey))
|
stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey))
|
||||||
stats.Counter.Repo = repo_model.CountRepositories(true)
|
stats.Counter.Repo = repo_model.CountRepositories(true)
|
||||||
stats.Counter.Watch, _ = e.Count(new(Watch))
|
stats.Counter.Watch, _ = e.Count(new(Watch))
|
||||||
stats.Counter.Star, _ = e.Count(new(Star))
|
stats.Counter.Star, _ = e.Count(new(Star))
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
_ "image/jpeg" // Needed for jpeg support
|
_ "image/jpeg" // Needed for jpeg support
|
||||||
|
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -234,23 +235,23 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***** START: PublicKey *****
|
// ***** START: PublicKey *****
|
||||||
if _, err = e.Delete(&PublicKey{OwnerID: u.ID}); err != nil {
|
if _, err = e.Delete(&asymkey_model.PublicKey{OwnerID: u.ID}); err != nil {
|
||||||
return fmt.Errorf("deletePublicKeys: %v", err)
|
return fmt.Errorf("deletePublicKeys: %v", err)
|
||||||
}
|
}
|
||||||
// ***** END: PublicKey *****
|
// ***** END: PublicKey *****
|
||||||
|
|
||||||
// ***** START: GPGPublicKey *****
|
// ***** START: GPGPublicKey *****
|
||||||
keys, err := listGPGKeys(e, u.ID, db.ListOptions{})
|
keys, err := asymkey_model.ListGPGKeys(ctx, u.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ListGPGKeys: %v", err)
|
return fmt.Errorf("ListGPGKeys: %v", err)
|
||||||
}
|
}
|
||||||
// Delete GPGKeyImport(s).
|
// Delete GPGKeyImport(s).
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if _, err = e.Delete(&GPGKeyImport{KeyID: key.KeyID}); err != nil {
|
if _, err = e.Delete(&asymkey_model.GPGKeyImport{KeyID: key.KeyID}); err != nil {
|
||||||
return fmt.Errorf("deleteGPGKeyImports: %v", err)
|
return fmt.Errorf("deleteGPGKeyImports: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err = e.Delete(&GPGKey{OwnerID: u.ID}); err != nil {
|
if _, err = e.Delete(&asymkey_model.GPGKey{OwnerID: u.ID}); err != nil {
|
||||||
return fmt.Errorf("deleteGPGKeys: %v", err)
|
return fmt.Errorf("deleteGPGKeys: %v", err)
|
||||||
}
|
}
|
||||||
// ***** END: GPGPublicKey *****
|
// ***** END: GPGPublicKey *****
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/login"
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
@ -121,71 +120,3 @@ func TestGetOrgRepositoryIDs(t *testing.T) {
|
||||||
// User 5's team has no access to any repo
|
// User 5's team has no access to any repo
|
||||||
assert.Len(t, accessibleRepos, 0)
|
assert.Len(t, accessibleRepos, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddLdapSSHPublicKeys(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
|
||||||
s := &login.Source{ID: 1}
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
keyString string
|
|
||||||
number int
|
|
||||||
keyContents []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
keyString: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment\n",
|
|
||||||
number: 1,
|
|
||||||
keyContents: []string{
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
keyString: `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment
|
|
||||||
ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment`,
|
|
||||||
number: 2,
|
|
||||||
keyContents: []string{
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
|
||||||
"ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag=",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
keyString: `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment
|
|
||||||
# comment asmdna,ndp
|
|
||||||
ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment`,
|
|
||||||
number: 2,
|
|
||||||
keyContents: []string{
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
|
||||||
"ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag=",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
keyString: `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment
|
|
||||||
382488320jasdj1lasmva/vasodifipi4193-fksma.cm
|
|
||||||
ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment`,
|
|
||||||
number: 2,
|
|
||||||
keyContents: []string{
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
|
||||||
"ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag=",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, kase := range testCases {
|
|
||||||
s.ID = int64(i) + 20
|
|
||||||
AddPublicKeysBySource(user, s, []string{kase.keyString})
|
|
||||||
keys, err := ListPublicKeysBySource(user.ID, s.ID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
assert.Len(t, keys, kase.number)
|
|
||||||
|
|
||||||
for _, key := range keys {
|
|
||||||
assert.Contains(t, kase.keyContents, key.Content)
|
|
||||||
}
|
|
||||||
for _, key := range keys {
|
|
||||||
DeletePublicKey(user, key.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
|
|
||||||
"github.com/editorconfig/editorconfig-core-go/v2"
|
"github.com/editorconfig/editorconfig-core-go/v2"
|
||||||
"github.com/unknwon/com"
|
"github.com/unknwon/com"
|
||||||
|
@ -120,7 +121,7 @@ func (r *Repository) CanCommitToBranch(doer *user_model.User) (CanCommitToBranch
|
||||||
requireSigned = protectedBranch.RequireSignedCommits
|
requireSigned = protectedBranch.RequireSignedCommits
|
||||||
}
|
}
|
||||||
|
|
||||||
sign, keyID, _, err := models.SignCRUDAction(r.Repository, doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName)
|
sign, keyID, _, err := asymkey_service.SignCRUDAction(r.Repository.RepoPath(), doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName)
|
||||||
|
|
||||||
canCommit := r.CanEnableEditor() && userCanPush
|
canCommit := r.CanEnableEditor() && userCanPush
|
||||||
if requireSigned {
|
if requireSigned {
|
||||||
|
@ -128,8 +129,8 @@ func (r *Repository) CanCommitToBranch(doer *user_model.User) (CanCommitToBranch
|
||||||
}
|
}
|
||||||
wontSignReason := ""
|
wontSignReason := ""
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrWontSign(err) {
|
if asymkey_service.IsErrWontSign(err) {
|
||||||
wontSignReason = string(err.(*models.ErrWontSign).Reason)
|
wontSignReason = string(err.(*asymkey_service.ErrWontSign).Reason)
|
||||||
err = nil
|
err = nil
|
||||||
} else {
|
} else {
|
||||||
wontSignReason = "error"
|
wontSignReason = "error"
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
@ -152,7 +153,7 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag {
|
||||||
|
|
||||||
// ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification
|
// ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification
|
||||||
func ToVerification(c *git.Commit) *api.PayloadCommitVerification {
|
func ToVerification(c *git.Commit) *api.PayloadCommitVerification {
|
||||||
verif := models.ParseCommitWithSignature(c)
|
verif := asymkey_model.ParseCommitWithSignature(c)
|
||||||
commitVerification := &api.PayloadCommitVerification{
|
commitVerification := &api.PayloadCommitVerification{
|
||||||
Verified: verif.Verified,
|
Verified: verif.Verified,
|
||||||
Reason: verif.Reason,
|
Reason: verif.Reason,
|
||||||
|
@ -170,8 +171,8 @@ func ToVerification(c *git.Commit) *api.PayloadCommitVerification {
|
||||||
return commitVerification
|
return commitVerification
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToPublicKey convert models.PublicKey to api.PublicKey
|
// ToPublicKey convert asymkey_model.PublicKey to api.PublicKey
|
||||||
func ToPublicKey(apiLink string, key *models.PublicKey) *api.PublicKey {
|
func ToPublicKey(apiLink string, key *asymkey_model.PublicKey) *api.PublicKey {
|
||||||
return &api.PublicKey{
|
return &api.PublicKey{
|
||||||
ID: key.ID,
|
ID: key.ID,
|
||||||
Key: key.Content,
|
Key: key.Content,
|
||||||
|
@ -183,7 +184,7 @@ func ToPublicKey(apiLink string, key *models.PublicKey) *api.PublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToGPGKey converts models.GPGKey to api.GPGKey
|
// ToGPGKey converts models.GPGKey to api.GPGKey
|
||||||
func ToGPGKey(key *models.GPGKey) *api.GPGKey {
|
func ToGPGKey(key *asymkey_model.GPGKey) *api.GPGKey {
|
||||||
subkeys := make([]*api.GPGKey, len(key.SubsKey))
|
subkeys := make([]*api.GPGKey, len(key.SubsKey))
|
||||||
for id, k := range key.SubsKey {
|
for id, k := range key.SubsKey {
|
||||||
subkeys[id] = &api.GPGKey{
|
subkeys[id] = &api.GPGKey{
|
||||||
|
@ -264,8 +265,8 @@ func ToGitHook(h *git.Hook) *api.GitHook {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDeployKey convert models.DeployKey to api.DeployKey
|
// ToDeployKey convert asymkey_model.DeployKey to api.DeployKey
|
||||||
func ToDeployKey(apiLink string, key *models.DeployKey) *api.DeployKey {
|
func ToDeployKey(apiLink string, key *asymkey_model.DeployKey) *api.DeployKey {
|
||||||
return &api.DeployKey{
|
return &api.DeployKey{
|
||||||
ID: key.ID,
|
ID: key.ID,
|
||||||
KeyID: key.KeyID,
|
KeyID: key.KeyID,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
@ -32,7 +32,7 @@ func checkAuthorizedKeys(logger log.Logger, autofix bool) error {
|
||||||
return fmt.Errorf("Unable to open authorized_keys file. ERROR: %v", err)
|
return fmt.Errorf("Unable to open authorized_keys file. ERROR: %v", err)
|
||||||
}
|
}
|
||||||
logger.Warn("Unable to open authorized_keys. (ERROR: %v). Attempting to rewrite...", err)
|
logger.Warn("Unable to open authorized_keys. (ERROR: %v). Attempting to rewrite...", err)
|
||||||
if err = models.RewriteAllPublicKeys(); err != nil {
|
if err = asymkey_model.RewriteAllPublicKeys(); err != nil {
|
||||||
logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
||||||
return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func checkAuthorizedKeys(logger log.Logger, autofix bool) error {
|
||||||
|
|
||||||
// now we regenerate and check if there are any lines missing
|
// now we regenerate and check if there are any lines missing
|
||||||
regenerated := &bytes.Buffer{}
|
regenerated := &bytes.Buffer{}
|
||||||
if err := models.RegeneratePublicKeys(regenerated); err != nil {
|
if err := asymkey_model.RegeneratePublicKeys(regenerated); err != nil {
|
||||||
logger.Critical("Unable to regenerate authorized_keys file. ERROR: %v", err)
|
logger.Critical("Unable to regenerate authorized_keys file. ERROR: %v", err)
|
||||||
return fmt.Errorf("Unable to regenerate authorized_keys file. ERROR: %v", err)
|
return fmt.Errorf("Unable to regenerate authorized_keys file. ERROR: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ func checkAuthorizedKeys(logger log.Logger, autofix bool) error {
|
||||||
return fmt.Errorf(`authorized_keys is out of date and should be regenerated with "gitea admin regenerate keys" or "gitea doctor --run authorized_keys --fix"`)
|
return fmt.Errorf(`authorized_keys is out of date and should be regenerated with "gitea admin regenerate keys" or "gitea doctor --run authorized_keys --fix"`)
|
||||||
}
|
}
|
||||||
logger.Warn("authorized_keys is out of date. Attempting rewrite...")
|
logger.Warn("authorized_keys is out of date. Attempting rewrite...")
|
||||||
err = models.RewriteAllPublicKeys()
|
err = asymkey_model.RewriteAllPublicKeys()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
||||||
return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %v", err)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -113,9 +114,11 @@ func (graph *Graph) LoadAndProcessCommits(repository *repo_model.Repository, git
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Verification = models.ParseCommitWithSignature(c.Commit)
|
c.Verification = asymkey_model.ParseCommitWithSignature(c.Commit)
|
||||||
|
|
||||||
_ = models.CalculateTrustStatus(c.Verification, repository, &keyMap)
|
_ = asymkey_model.CalculateTrustStatus(c.Verification, repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
|
||||||
|
return models.IsUserRepoAdmin(repository, user)
|
||||||
|
}, &keyMap)
|
||||||
|
|
||||||
statuses, err := models.GetLatestCommitStatus(repository.ID, c.Commit.ID.String(), db.ListOptions{})
|
statuses, err := models.GetLatestCommitStatus(repository.ID, c.Commit.ID.String(), db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -236,7 +239,7 @@ func newRefsFromRefNames(refNames []byte) []git.Reference {
|
||||||
type Commit struct {
|
type Commit struct {
|
||||||
Commit *git.Commit
|
Commit *git.Commit
|
||||||
User *user_model.User
|
User *user_model.User
|
||||||
Verification *models.CommitVerification
|
Verification *asymkey_model.CommitVerification
|
||||||
Status *models.CommitStatus
|
Status *models.CommitStatus
|
||||||
Flow int64
|
Flow int64
|
||||||
Row int
|
Row int
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
@ -19,12 +19,12 @@ import (
|
||||||
|
|
||||||
// KeyAndOwner is the response from ServNoCommand
|
// KeyAndOwner is the response from ServNoCommand
|
||||||
type KeyAndOwner struct {
|
type KeyAndOwner struct {
|
||||||
Key *models.PublicKey `json:"key"`
|
Key *asymkey_model.PublicKey `json:"key"`
|
||||||
Owner *user_model.User `json:"user"`
|
Owner *user_model.User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServNoCommand returns information about the provided key
|
// ServNoCommand returns information about the provided key
|
||||||
func ServNoCommand(ctx context.Context, keyID int64) (*models.PublicKey, *user_model.User, error) {
|
func ServNoCommand(ctx context.Context, keyID int64) (*asymkey_model.PublicKey, *user_model.User, error) {
|
||||||
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/serv/none/%d",
|
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/serv/none/%d",
|
||||||
keyID)
|
keyID)
|
||||||
resp, err := newInternalRequest(ctx, reqURL, "GET").Response()
|
resp, err := newInternalRequest(ctx, reqURL, "GET").Response()
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
|
|
||||||
"github.com/unknwon/com"
|
"github.com/unknwon/com"
|
||||||
)
|
)
|
||||||
|
@ -134,7 +135,7 @@ func initRepoCommit(tmpPath string, repo *repo_model.Repository, u *user_model.U
|
||||||
}
|
}
|
||||||
|
|
||||||
if git.CheckGitVersionAtLeast("1.7.9") == nil {
|
if git.CheckGitVersionAtLeast("1.7.9") == nil {
|
||||||
sign, keyID, signer, _ := models.SignInitialCommit(tmpPath, u)
|
sign, keyID, signer, _ := asymkey_service.SignInitialCommit(tmpPath, u)
|
||||||
if sign {
|
if sign {
|
||||||
args = append(args, "-S"+keyID)
|
args = append(args, "-S"+keyID)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
@ -172,9 +172,9 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||||
// look for the exact principal
|
// look for the exact principal
|
||||||
principalLoop:
|
principalLoop:
|
||||||
for _, principal := range cert.ValidPrincipals {
|
for _, principal := range cert.ValidPrincipals {
|
||||||
pkey, err := models.SearchPublicKeyByContentExact(principal)
|
pkey, err := asymkey_model.SearchPublicKeyByContentExact(principal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrKeyNotExist(err) {
|
if asymkey_model.IsErrKeyNotExist(err) {
|
||||||
log.Debug("Principal Rejected: %s Unknown Principal: %s", ctx.RemoteAddr(), principal)
|
log.Debug("Principal Rejected: %s Unknown Principal: %s", ctx.RemoteAddr(), principal)
|
||||||
continue principalLoop
|
continue principalLoop
|
||||||
}
|
}
|
||||||
|
@ -232,9 +232,9 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||||
log.Debug("Handle Public Key: %s Fingerprint: %s is not a certificate", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
|
log.Debug("Handle Public Key: %s Fingerprint: %s is not a certificate", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key))))
|
pkey, err := asymkey_model.SearchPublicKeyByContent(strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key))))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrKeyNotExist(err) {
|
if asymkey_model.IsErrKeyNotExist(err) {
|
||||||
if log.IsWarn() {
|
if log.IsWarn() {
|
||||||
log.Warn("Unknown public key: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
|
log.Warn("Unknown public key: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
|
||||||
log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
|
log.Warn("Failed authentication attempt from %s", ctx.RemoteAddr())
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -23,6 +24,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/routers/api/v1/user"
|
"code.gitea.io/gitea/routers/api/v1/user"
|
||||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
"code.gitea.io/gitea/services/mailer"
|
"code.gitea.io/gitea/services/mailer"
|
||||||
user_service "code.gitea.io/gitea/services/user"
|
user_service "code.gitea.io/gitea/services/user"
|
||||||
)
|
)
|
||||||
|
@ -381,10 +383,10 @@ func DeleteUserPublicKey(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeletePublicKey(u, ctx.ParamsInt64(":id")); err != nil {
|
if err := asymkey_service.DeletePublicKey(u, ctx.ParamsInt64(":id")); err != nil {
|
||||||
if models.IsErrKeyNotExist(err) {
|
if asymkey_model.IsErrKeyNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else if models.IsErrKeyAccessDenied(err) {
|
} else if asymkey_model.IsErrKeyAccessDenied(err) {
|
||||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "DeleteUserPublicKey", err)
|
ctx.Error(http.StatusInternalServerError, "DeleteUserPublicKey", err)
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SigningKey returns the public key of the default signing key if it exists
|
// SigningKey returns the public key of the default signing key if it exists
|
||||||
|
@ -52,7 +52,7 @@ func SigningKey(ctx *context.APIContext) {
|
||||||
path = ctx.Repo.Repository.RepoPath()
|
path = ctx.Repo.Repository.RepoPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := models.PublicSigningKey(path)
|
content, err := asymkey_service.PublicSigningKey(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "gpg export", err)
|
ctx.Error(http.StatusInternalServerError, "gpg export", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -10,7 +10,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -19,10 +20,11 @@ import (
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
// appendPrivateInformation appends the owner and key type information to api.PublicKey
|
// appendPrivateInformation appends the owner and key type information to api.PublicKey
|
||||||
func appendPrivateInformation(apiKey *api.DeployKey, key *models.DeployKey, repository *repo_model.Repository) (*api.DeployKey, error) {
|
func appendPrivateInformation(apiKey *api.DeployKey, key *asymkey_model.DeployKey, repository *repo_model.Repository) (*api.DeployKey, error) {
|
||||||
apiKey.ReadOnly = key.Mode == perm.AccessModeRead
|
apiKey.ReadOnly = key.Mode == perm.AccessModeRead
|
||||||
if repository.ID == key.RepoID {
|
if repository.ID == key.RepoID {
|
||||||
apiKey.Repository = convert.ToRepo(repository, key.Mode)
|
apiKey.Repository = convert.ToRepo(repository, key.Mode)
|
||||||
|
@ -78,20 +80,20 @@ func ListDeployKeys(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/DeployKeyList"
|
// "$ref": "#/responses/DeployKeyList"
|
||||||
|
|
||||||
opts := &models.ListDeployKeysOptions{
|
opts := &asymkey_model.ListDeployKeysOptions{
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
KeyID: ctx.FormInt64("key_id"),
|
KeyID: ctx.FormInt64("key_id"),
|
||||||
Fingerprint: ctx.FormString("fingerprint"),
|
Fingerprint: ctx.FormString("fingerprint"),
|
||||||
}
|
}
|
||||||
|
|
||||||
keys, err := models.ListDeployKeys(opts)
|
keys, err := asymkey_model.ListDeployKeys(db.DefaultContext, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := models.CountDeployKeys(opts)
|
count, err := asymkey_model.CountDeployKeys(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
|
@ -142,9 +144,9 @@ func GetDeployKey(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/DeployKey"
|
// "$ref": "#/responses/DeployKey"
|
||||||
|
|
||||||
key, err := models.GetDeployKeyByID(ctx.ParamsInt64(":id"))
|
key, err := asymkey_model.GetDeployKeyByID(db.DefaultContext, ctx.ParamsInt64(":id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrDeployKeyNotExist(err) {
|
if asymkey_model.IsErrDeployKeyNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetDeployKeyByID", err)
|
ctx.Error(http.StatusInternalServerError, "GetDeployKeyByID", err)
|
||||||
|
@ -167,9 +169,9 @@ func GetDeployKey(ctx *context.APIContext) {
|
||||||
|
|
||||||
// HandleCheckKeyStringError handle check key error
|
// HandleCheckKeyStringError handle check key error
|
||||||
func HandleCheckKeyStringError(ctx *context.APIContext, err error) {
|
func HandleCheckKeyStringError(ctx *context.APIContext, err error) {
|
||||||
if models.IsErrSSHDisabled(err) {
|
if db.IsErrSSHDisabled(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", "SSH is disabled")
|
ctx.Error(http.StatusUnprocessableEntity, "", "SSH is disabled")
|
||||||
} else if models.IsErrKeyUnableVerify(err) {
|
} else if asymkey_model.IsErrKeyUnableVerify(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", "Unable to verify key content")
|
ctx.Error(http.StatusUnprocessableEntity, "", "Unable to verify key content")
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("Invalid key content: %v", err))
|
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("Invalid key content: %v", err))
|
||||||
|
@ -179,13 +181,13 @@ func HandleCheckKeyStringError(ctx *context.APIContext, err error) {
|
||||||
// HandleAddKeyError handle add key error
|
// HandleAddKeyError handle add key error
|
||||||
func HandleAddKeyError(ctx *context.APIContext, err error) {
|
func HandleAddKeyError(ctx *context.APIContext, err error) {
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrDeployKeyAlreadyExist(err):
|
case asymkey_model.IsErrDeployKeyAlreadyExist(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", "This key has already been added to this repository")
|
ctx.Error(http.StatusUnprocessableEntity, "", "This key has already been added to this repository")
|
||||||
case models.IsErrKeyAlreadyExist(err):
|
case asymkey_model.IsErrKeyAlreadyExist(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", "Key content has been used as non-deploy key")
|
ctx.Error(http.StatusUnprocessableEntity, "", "Key content has been used as non-deploy key")
|
||||||
case models.IsErrKeyNameAlreadyUsed(err):
|
case asymkey_model.IsErrKeyNameAlreadyUsed(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", "Key title has been used")
|
ctx.Error(http.StatusUnprocessableEntity, "", "Key title has been used")
|
||||||
case models.IsErrDeployKeyNameAlreadyUsed(err):
|
case asymkey_model.IsErrDeployKeyNameAlreadyUsed(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", "A key with the same name already exists")
|
ctx.Error(http.StatusUnprocessableEntity, "", "A key with the same name already exists")
|
||||||
default:
|
default:
|
||||||
ctx.Error(http.StatusInternalServerError, "AddKey", err)
|
ctx.Error(http.StatusInternalServerError, "AddKey", err)
|
||||||
|
@ -223,13 +225,13 @@ func CreateDeployKey(ctx *context.APIContext) {
|
||||||
// "$ref": "#/responses/validationError"
|
// "$ref": "#/responses/validationError"
|
||||||
|
|
||||||
form := web.GetForm(ctx).(*api.CreateKeyOption)
|
form := web.GetForm(ctx).(*api.CreateKeyOption)
|
||||||
content, err := models.CheckPublicKeyString(form.Key)
|
content, err := asymkey_model.CheckPublicKeyString(form.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HandleCheckKeyStringError(ctx, err)
|
HandleCheckKeyStringError(ctx, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := models.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, form.ReadOnly)
|
key, err := asymkey_model.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, form.ReadOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HandleAddKeyError(ctx, err)
|
HandleAddKeyError(ctx, err)
|
||||||
return
|
return
|
||||||
|
@ -268,8 +270,8 @@ func DeleteDeploykey(ctx *context.APIContext) {
|
||||||
// "403":
|
// "403":
|
||||||
// "$ref": "#/responses/forbidden"
|
// "$ref": "#/responses/forbidden"
|
||||||
|
|
||||||
if err := models.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
|
if err := asymkey_service.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
|
||||||
if models.IsErrKeyAccessDenied(err) {
|
if asymkey_model.IsErrKeyAccessDenied(err) {
|
||||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "DeleteDeployKey", err)
|
ctx.Error(http.StatusInternalServerError, "DeleteDeployKey", err)
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
"code.gitea.io/gitea/services/forms"
|
"code.gitea.io/gitea/services/forms"
|
||||||
issue_service "code.gitea.io/gitea/services/issue"
|
issue_service "code.gitea.io/gitea/services/issue"
|
||||||
pull_service "code.gitea.io/gitea/services/pull"
|
pull_service "code.gitea.io/gitea/services/pull"
|
||||||
|
@ -810,7 +811,7 @@ func MergePullRequest(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := pull_service.IsSignedIfRequired(pr, ctx.User); err != nil {
|
if _, err := pull_service.IsSignedIfRequired(pr, ctx.User); err != nil {
|
||||||
if !models.IsErrWontSign(err) {
|
if !asymkey_service.IsErrWontSign(err) {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsSignedIfRequired", err)
|
ctx.Error(http.StatusInternalServerError, "IsSignedIfRequired", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1023,7 +1023,7 @@ func Delete(ctx *context.APIContext) {
|
||||||
ctx.Repo.GitRepo.Close()
|
ctx.Repo.GitRepo.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo_service.DeleteRepository(ctx.User, repo); err != nil {
|
if err := repo_service.DeleteRepository(ctx.User, repo, true); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "DeleteRepository", err)
|
ctx.Error(http.StatusInternalServerError, "DeleteRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
|
@ -18,7 +18,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func listGPGKeys(ctx *context.APIContext, uid int64, listOptions db.ListOptions) {
|
func listGPGKeys(ctx *context.APIContext, uid int64, listOptions db.ListOptions) {
|
||||||
keys, err := models.ListGPGKeys(uid, listOptions)
|
keys, err := asymkey_model.ListGPGKeys(db.DefaultContext, uid, listOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "ListGPGKeys", err)
|
ctx.Error(http.StatusInternalServerError, "ListGPGKeys", err)
|
||||||
return
|
return
|
||||||
|
@ -29,7 +29,7 @@ func listGPGKeys(ctx *context.APIContext, uid int64, listOptions db.ListOptions)
|
||||||
apiKeys[i] = convert.ToGPGKey(keys[i])
|
apiKeys[i] = convert.ToGPGKey(keys[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
total, err := models.CountUserGPGKeys(uid)
|
total, err := asymkey_model.CountUserGPGKeys(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
|
@ -114,9 +114,9 @@ func GetGPGKey(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
key, err := models.GetGPGKeyByID(ctx.ParamsInt64(":id"))
|
key, err := asymkey_model.GetGPGKeyByID(ctx.ParamsInt64(":id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrGPGKeyNotExist(err) {
|
if asymkey_model.IsErrGPGKeyNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetGPGKeyByID", err)
|
ctx.Error(http.StatusInternalServerError, "GetGPGKeyByID", err)
|
||||||
|
@ -128,12 +128,12 @@ func GetGPGKey(ctx *context.APIContext) {
|
||||||
|
|
||||||
// CreateUserGPGKey creates new GPG key to given user by ID.
|
// CreateUserGPGKey creates new GPG key to given user by ID.
|
||||||
func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid int64) {
|
func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid int64) {
|
||||||
token := models.VerificationToken(ctx.User, 1)
|
token := asymkey_model.VerificationToken(ctx.User, 1)
|
||||||
lastToken := models.VerificationToken(ctx.User, 0)
|
lastToken := asymkey_model.VerificationToken(ctx.User, 0)
|
||||||
|
|
||||||
keys, err := models.AddGPGKey(uid, form.ArmoredKey, token, form.Signature)
|
keys, err := asymkey_model.AddGPGKey(uid, form.ArmoredKey, token, form.Signature)
|
||||||
if err != nil && models.IsErrGPGInvalidTokenSignature(err) {
|
if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
|
||||||
keys, err = models.AddGPGKey(uid, form.ArmoredKey, lastToken, form.Signature)
|
keys, err = asymkey_model.AddGPGKey(uid, form.ArmoredKey, lastToken, form.Signature)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HandleAddGPGKeyError(ctx, err, token)
|
HandleAddGPGKeyError(ctx, err, token)
|
||||||
|
@ -156,7 +156,7 @@ func GetVerificationToken(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
token := models.VerificationToken(ctx.User, 1)
|
token := asymkey_model.VerificationToken(ctx.User, 1)
|
||||||
ctx.PlainText(http.StatusOK, []byte(token))
|
ctx.PlainText(http.StatusOK, []byte(token))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,25 +178,25 @@ func VerifyUserGPGKey(ctx *context.APIContext) {
|
||||||
// "$ref": "#/responses/validationError"
|
// "$ref": "#/responses/validationError"
|
||||||
|
|
||||||
form := web.GetForm(ctx).(*api.VerifyGPGKeyOption)
|
form := web.GetForm(ctx).(*api.VerifyGPGKeyOption)
|
||||||
token := models.VerificationToken(ctx.User, 1)
|
token := asymkey_model.VerificationToken(ctx.User, 1)
|
||||||
lastToken := models.VerificationToken(ctx.User, 0)
|
lastToken := asymkey_model.VerificationToken(ctx.User, 0)
|
||||||
|
|
||||||
_, err := models.VerifyGPGKey(ctx.User.ID, form.KeyID, token, form.Signature)
|
_, err := asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, token, form.Signature)
|
||||||
if err != nil && models.IsErrGPGInvalidTokenSignature(err) {
|
if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
|
||||||
_, err = models.VerifyGPGKey(ctx.User.ID, form.KeyID, lastToken, form.Signature)
|
_, err = asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, lastToken, form.Signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrGPGInvalidTokenSignature(err) {
|
if asymkey_model.IsErrGPGInvalidTokenSignature(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "GPGInvalidSignature", fmt.Sprintf("The provided GPG key, signature and token do not match or token is out of date. Provide a valid signature for the token: %s", token))
|
ctx.Error(http.StatusUnprocessableEntity, "GPGInvalidSignature", fmt.Sprintf("The provided GPG key, signature and token do not match or token is out of date. Provide a valid signature for the token: %s", token))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Error(http.StatusInternalServerError, "VerifyUserGPGKey", err)
|
ctx.Error(http.StatusInternalServerError, "VerifyUserGPGKey", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := models.GetGPGKeysByKeyID(form.KeyID)
|
key, err := asymkey_model.GetGPGKeysByKeyID(form.KeyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrGPGKeyNotExist(err) {
|
if asymkey_model.IsErrGPGKeyNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetGPGKeysByKeyID", err)
|
ctx.Error(http.StatusInternalServerError, "GetGPGKeysByKeyID", err)
|
||||||
|
@ -255,8 +255,8 @@ func DeleteGPGKey(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
if err := models.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
|
if err := asymkey_model.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
|
||||||
if models.IsErrGPGKeyAccessDenied(err) {
|
if asymkey_model.IsErrGPGKeyAccessDenied(err) {
|
||||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "DeleteGPGKey", err)
|
ctx.Error(http.StatusInternalServerError, "DeleteGPGKey", err)
|
||||||
|
@ -270,15 +270,15 @@ func DeleteGPGKey(ctx *context.APIContext) {
|
||||||
// HandleAddGPGKeyError handle add GPGKey error
|
// HandleAddGPGKeyError handle add GPGKey error
|
||||||
func HandleAddGPGKeyError(ctx *context.APIContext, err error, token string) {
|
func HandleAddGPGKeyError(ctx *context.APIContext, err error, token string) {
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrGPGKeyAccessDenied(err):
|
case asymkey_model.IsErrGPGKeyAccessDenied(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyAccessDenied", "You do not have access to this GPG key")
|
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyAccessDenied", "You do not have access to this GPG key")
|
||||||
case models.IsErrGPGKeyIDAlreadyUsed(err):
|
case asymkey_model.IsErrGPGKeyIDAlreadyUsed(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyIDAlreadyUsed", "A key with the same id already exists")
|
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyIDAlreadyUsed", "A key with the same id already exists")
|
||||||
case models.IsErrGPGKeyParsing(err):
|
case asymkey_model.IsErrGPGKeyParsing(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyParsing", err)
|
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyParsing", err)
|
||||||
case models.IsErrGPGNoEmailFound(err):
|
case asymkey_model.IsErrGPGNoEmailFound(err):
|
||||||
ctx.Error(http.StatusNotFound, "GPGNoEmailFound", fmt.Sprintf("None of the emails attached to the GPG key could be found. It may still be added if you provide a valid signature for the token: %s", token))
|
ctx.Error(http.StatusNotFound, "GPGNoEmailFound", fmt.Sprintf("None of the emails attached to the GPG key could be found. It may still be added if you provide a valid signature for the token: %s", token))
|
||||||
case models.IsErrGPGInvalidTokenSignature(err):
|
case asymkey_model.IsErrGPGInvalidTokenSignature(err):
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "GPGInvalidSignature", fmt.Sprintf("The provided GPG key, signature and token do not match or token is out of date. Provide a valid signature for the token: %s", token))
|
ctx.Error(http.StatusUnprocessableEntity, "GPGInvalidSignature", fmt.Sprintf("The provided GPG key, signature and token do not match or token is out of date. Provide a valid signature for the token: %s", token))
|
||||||
default:
|
default:
|
||||||
ctx.Error(http.StatusInternalServerError, "AddGPGKey", err)
|
ctx.Error(http.StatusInternalServerError, "AddGPGKey", err)
|
||||||
|
|
|
@ -7,7 +7,7 @@ package user
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -17,13 +17,14 @@ import (
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/routers/api/v1/repo"
|
"code.gitea.io/gitea/routers/api/v1/repo"
|
||||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
// appendPrivateInformation appends the owner and key type information to api.PublicKey
|
// appendPrivateInformation appends the owner and key type information to api.PublicKey
|
||||||
func appendPrivateInformation(apiKey *api.PublicKey, key *models.PublicKey, defaultUser *user_model.User) (*api.PublicKey, error) {
|
func appendPrivateInformation(apiKey *api.PublicKey, key *asymkey_model.PublicKey, defaultUser *user_model.User) (*api.PublicKey, error) {
|
||||||
if key.Type == models.KeyTypeDeploy {
|
if key.Type == asymkey_model.KeyTypeDeploy {
|
||||||
apiKey.KeyType = "deploy"
|
apiKey.KeyType = "deploy"
|
||||||
} else if key.Type == models.KeyTypeUser {
|
} else if key.Type == asymkey_model.KeyTypeUser {
|
||||||
apiKey.KeyType = "user"
|
apiKey.KeyType = "user"
|
||||||
|
|
||||||
if defaultUser.ID == key.OwnerID {
|
if defaultUser.ID == key.OwnerID {
|
||||||
|
@ -47,7 +48,7 @@ func composePublicKeysAPILink() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func listPublicKeys(ctx *context.APIContext, user *user_model.User) {
|
func listPublicKeys(ctx *context.APIContext, user *user_model.User) {
|
||||||
var keys []*models.PublicKey
|
var keys []*asymkey_model.PublicKey
|
||||||
var err error
|
var err error
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
|
@ -58,14 +59,14 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) {
|
||||||
// Querying not just listing
|
// Querying not just listing
|
||||||
if username != "" {
|
if username != "" {
|
||||||
// Restrict to provided uid
|
// Restrict to provided uid
|
||||||
keys, err = models.SearchPublicKey(user.ID, fingerprint)
|
keys, err = asymkey_model.SearchPublicKey(user.ID, fingerprint)
|
||||||
} else {
|
} else {
|
||||||
// Unrestricted
|
// Unrestricted
|
||||||
keys, err = models.SearchPublicKey(0, fingerprint)
|
keys, err = asymkey_model.SearchPublicKey(0, fingerprint)
|
||||||
}
|
}
|
||||||
count = len(keys)
|
count = len(keys)
|
||||||
} else {
|
} else {
|
||||||
total, err2 := models.CountPublicKeys(user.ID)
|
total, err2 := asymkey_model.CountPublicKeys(user.ID)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
|
@ -73,7 +74,7 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) {
|
||||||
count = int(total)
|
count = int(total)
|
||||||
|
|
||||||
// Use ListPublicKeys
|
// Use ListPublicKeys
|
||||||
keys, err = models.ListPublicKeys(user.ID, utils.GetListOptions(ctx))
|
keys, err = asymkey_model.ListPublicKeys(user.ID, utils.GetListOptions(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -177,9 +178,9 @@ func GetPublicKey(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
key, err := models.GetPublicKeyByID(ctx.ParamsInt64(":id"))
|
key, err := asymkey_model.GetPublicKeyByID(ctx.ParamsInt64(":id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrKeyNotExist(err) {
|
if asymkey_model.IsErrKeyNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetPublicKeyByID", err)
|
ctx.Error(http.StatusInternalServerError, "GetPublicKeyByID", err)
|
||||||
|
@ -197,13 +198,13 @@ func GetPublicKey(ctx *context.APIContext) {
|
||||||
|
|
||||||
// CreateUserPublicKey creates new public key to given user by ID.
|
// CreateUserPublicKey creates new public key to given user by ID.
|
||||||
func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) {
|
func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) {
|
||||||
content, err := models.CheckPublicKeyString(form.Key)
|
content, err := asymkey_model.CheckPublicKeyString(form.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
repo.HandleCheckKeyStringError(ctx, err)
|
repo.HandleCheckKeyStringError(ctx, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := models.AddPublicKey(uid, form.Title, content, 0)
|
key, err := asymkey_model.AddPublicKey(uid, form.Title, content, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
repo.HandleAddKeyError(ctx, err)
|
repo.HandleAddKeyError(ctx, err)
|
||||||
return
|
return
|
||||||
|
@ -263,7 +264,7 @@ func DeletePublicKey(ctx *context.APIContext) {
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
id := ctx.ParamsInt64(":id")
|
id := ctx.ParamsInt64(":id")
|
||||||
externallyManaged, err := models.PublicKeyIsExternallyManaged(id)
|
externallyManaged, err := asymkey_model.PublicKeyIsExternallyManaged(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "PublicKeyIsExternallyManaged", err)
|
ctx.Error(http.StatusInternalServerError, "PublicKeyIsExternallyManaged", err)
|
||||||
}
|
}
|
||||||
|
@ -271,10 +272,10 @@ func DeletePublicKey(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusForbidden, "", "SSH Key is externally managed for this user")
|
ctx.Error(http.StatusForbidden, "", "SSH Key is externally managed for this user")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeletePublicKey(ctx.User, id); err != nil {
|
if err := asymkey_service.DeletePublicKey(ctx.User, id); err != nil {
|
||||||
if models.IsErrKeyNotExist(err) {
|
if asymkey_model.IsErrKeyNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else if models.IsErrKeyAccessDenied(err) {
|
} else if asymkey_model.IsErrKeyAccessDenied(err) {
|
||||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "DeletePublicKey", err)
|
ctx.Error(http.StatusInternalServerError, "DeletePublicKey", err)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/modules/appstate"
|
"code.gitea.io/gitea/modules/appstate"
|
||||||
"code.gitea.io/gitea/modules/cache"
|
"code.gitea.io/gitea/modules/cache"
|
||||||
"code.gitea.io/gitea/modules/eventsource"
|
"code.gitea.io/gitea/modules/eventsource"
|
||||||
|
@ -87,7 +88,7 @@ func syncAppPathForGit(ctx context.Context) error {
|
||||||
mustInitCtx(ctx, repo_service.SyncRepositoryHooks)
|
mustInitCtx(ctx, repo_service.SyncRepositoryHooks)
|
||||||
|
|
||||||
log.Info("re-write ssh public keys ...")
|
log.Info("re-write ssh public keys ...")
|
||||||
mustInit(models.RewriteAllPublicKeys)
|
mustInit(asymkey_model.RewriteAllPublicKeys)
|
||||||
|
|
||||||
runtimeState.LastAppPath = setting.AppPath
|
runtimeState.LastAppPath = setting.AppPath
|
||||||
return appstate.AppState.Set(runtimeState)
|
return appstate.AppState.Set(runtimeState)
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
|
@ -97,7 +97,7 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
verification := models.ParseCommitWithSignature(commit)
|
verification := asymkey_model.ParseCommitWithSignature(commit)
|
||||||
if !verification.Verified {
|
if !verification.Verified {
|
||||||
cancel()
|
cancel()
|
||||||
return &errUnverifiedCommit{
|
return &errUnverifiedCommit{
|
||||||
|
|
|
@ -8,7 +8,7 @@ package private
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
@ -18,16 +18,16 @@ import (
|
||||||
func UpdatePublicKeyInRepo(ctx *context.PrivateContext) {
|
func UpdatePublicKeyInRepo(ctx *context.PrivateContext) {
|
||||||
keyID := ctx.ParamsInt64(":id")
|
keyID := ctx.ParamsInt64(":id")
|
||||||
repoID := ctx.ParamsInt64(":repoid")
|
repoID := ctx.ParamsInt64(":repoid")
|
||||||
if err := models.UpdatePublicKeyUpdated(keyID); err != nil {
|
if err := asymkey_model.UpdatePublicKeyUpdated(keyID); err != nil {
|
||||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||||
Err: err.Error(),
|
Err: err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
deployKey, err := models.GetDeployKeyByRepo(keyID, repoID)
|
deployKey, err := asymkey_model.GetDeployKeyByRepo(keyID, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrDeployKeyNotExist(err) {
|
if asymkey_model.IsErrDeployKeyNotExist(err) {
|
||||||
ctx.PlainText(http.StatusOK, []byte("success"))
|
ctx.PlainText(http.StatusOK, []byte("success"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func UpdatePublicKeyInRepo(ctx *context.PrivateContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
deployKey.UpdatedUnix = timeutil.TimeStampNow()
|
deployKey.UpdatedUnix = timeutil.TimeStampNow()
|
||||||
if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
|
if err = asymkey_model.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
|
||||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||||
Err: err.Error(),
|
Err: err.Error(),
|
||||||
})
|
})
|
||||||
|
@ -52,7 +52,7 @@ func UpdatePublicKeyInRepo(ctx *context.PrivateContext) {
|
||||||
func AuthorizedPublicKeyByContent(ctx *context.PrivateContext) {
|
func AuthorizedPublicKeyByContent(ctx *context.PrivateContext) {
|
||||||
content := ctx.FormString("content")
|
content := ctx.FormString("content")
|
||||||
|
|
||||||
publicKey, err := models.SearchPublicKeyByContent(content)
|
publicKey, err := asymkey_model.SearchPublicKeyByContent(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||||
Err: err.Error(),
|
Err: err.Error(),
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -34,9 +35,9 @@ func ServNoCommand(ctx *context.PrivateContext) {
|
||||||
}
|
}
|
||||||
results := private.KeyAndOwner{}
|
results := private.KeyAndOwner{}
|
||||||
|
|
||||||
key, err := models.GetPublicKeyByID(keyID)
|
key, err := asymkey_model.GetPublicKeyByID(keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrKeyNotExist(err) {
|
if asymkey_model.IsErrKeyNotExist(err) {
|
||||||
ctx.JSON(http.StatusUnauthorized, private.Response{
|
ctx.JSON(http.StatusUnauthorized, private.Response{
|
||||||
Err: fmt.Sprintf("Cannot find key: %d", keyID),
|
Err: fmt.Sprintf("Cannot find key: %d", keyID),
|
||||||
})
|
})
|
||||||
|
@ -50,7 +51,7 @@ func ServNoCommand(ctx *context.PrivateContext) {
|
||||||
}
|
}
|
||||||
results.Key = key
|
results.Key = key
|
||||||
|
|
||||||
if key.Type == models.KeyTypeUser || key.Type == models.KeyTypePrincipal {
|
if key.Type == asymkey_model.KeyTypeUser || key.Type == asymkey_model.KeyTypePrincipal {
|
||||||
user, err := user_model.GetUserByID(key.OwnerID)
|
user, err := user_model.GetUserByID(key.OwnerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if user_model.IsErrUserNotExist(err) {
|
if user_model.IsErrUserNotExist(err) {
|
||||||
|
@ -184,9 +185,9 @@ func ServCommand(ctx *context.PrivateContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the Public Key represented by the keyID
|
// Get the Public Key represented by the keyID
|
||||||
key, err := models.GetPublicKeyByID(keyID)
|
key, err := asymkey_model.GetPublicKeyByID(keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrKeyNotExist(err) {
|
if asymkey_model.IsErrKeyNotExist(err) {
|
||||||
ctx.JSON(http.StatusNotFound, private.ErrServCommand{
|
ctx.JSON(http.StatusNotFound, private.ErrServCommand{
|
||||||
Results: results,
|
Results: results,
|
||||||
Err: fmt.Sprintf("Cannot find key: %d", keyID),
|
Err: fmt.Sprintf("Cannot find key: %d", keyID),
|
||||||
|
@ -205,7 +206,7 @@ func ServCommand(ctx *context.PrivateContext) {
|
||||||
results.UserID = key.OwnerID
|
results.UserID = key.OwnerID
|
||||||
|
|
||||||
// If repo doesn't exist, deploy key doesn't make sense
|
// If repo doesn't exist, deploy key doesn't make sense
|
||||||
if !repoExist && key.Type == models.KeyTypeDeploy {
|
if !repoExist && key.Type == asymkey_model.KeyTypeDeploy {
|
||||||
ctx.JSON(http.StatusNotFound, private.ErrServCommand{
|
ctx.JSON(http.StatusNotFound, private.ErrServCommand{
|
||||||
Results: results,
|
Results: results,
|
||||||
Err: fmt.Sprintf("Cannot find repository %s/%s", results.OwnerName, results.RepoName),
|
Err: fmt.Sprintf("Cannot find repository %s/%s", results.OwnerName, results.RepoName),
|
||||||
|
@ -216,15 +217,15 @@ func ServCommand(ctx *context.PrivateContext) {
|
||||||
// Deploy Keys have ownerID set to 0 therefore we can't use the owner
|
// Deploy Keys have ownerID set to 0 therefore we can't use the owner
|
||||||
// So now we need to check if the key is a deploy key
|
// So now we need to check if the key is a deploy key
|
||||||
// We'll keep hold of the deploy key here for permissions checking
|
// We'll keep hold of the deploy key here for permissions checking
|
||||||
var deployKey *models.DeployKey
|
var deployKey *asymkey_model.DeployKey
|
||||||
var user *user_model.User
|
var user *user_model.User
|
||||||
if key.Type == models.KeyTypeDeploy {
|
if key.Type == asymkey_model.KeyTypeDeploy {
|
||||||
results.IsDeployKey = true
|
results.IsDeployKey = true
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
deployKey, err = models.GetDeployKeyByRepo(key.ID, repo.ID)
|
deployKey, err = asymkey_model.GetDeployKeyByRepo(key.ID, repo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrDeployKeyNotExist(err) {
|
if asymkey_model.IsErrDeployKeyNotExist(err) {
|
||||||
ctx.JSON(http.StatusNotFound, private.ErrServCommand{
|
ctx.JSON(http.StatusNotFound, private.ErrServCommand{
|
||||||
Results: results,
|
Results: results,
|
||||||
Err: fmt.Sprintf("Public (Deploy) Key: %d:%s is not authorized to %s %s/%s.", key.ID, key.Name, modeString, results.OwnerName, results.RepoName),
|
Err: fmt.Sprintf("Public (Deploy) Key: %d:%s is not authorized to %s %s/%s.", key.ID, key.Name, modeString, results.OwnerName, results.RepoName),
|
||||||
|
@ -297,7 +298,7 @@ func ServCommand(ctx *context.PrivateContext) {
|
||||||
owner.Visibility.IsPrivate() ||
|
owner.Visibility.IsPrivate() ||
|
||||||
(user != nil && user.IsRestricted) || // user will be nil if the key is a deploykey
|
(user != nil && user.IsRestricted) || // user will be nil if the key is a deploykey
|
||||||
setting.Service.RequireSignInView) {
|
setting.Service.RequireSignInView) {
|
||||||
if key.Type == models.KeyTypeDeploy {
|
if key.Type == asymkey_model.KeyTypeDeploy {
|
||||||
if deployKey.Mode < mode {
|
if deployKey.Mode < mode {
|
||||||
ctx.JSON(http.StatusUnauthorized, private.ErrServCommand{
|
ctx.JSON(http.StatusUnauthorized, private.ErrServCommand{
|
||||||
Results: results,
|
Results: results,
|
||||||
|
|
|
@ -52,7 +52,7 @@ func DeleteRepo(ctx *context.Context) {
|
||||||
ctx.Repo.GitRepo.Close()
|
ctx.Repo.GitRepo.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo_service.DeleteRepository(ctx.User, repo); err != nil {
|
if err := repo_service.DeleteRepository(ctx.User, repo, true); err != nil {
|
||||||
ctx.ServerError("DeleteRepository", err)
|
ctx.ServerError("DeleteRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -344,13 +345,15 @@ func Diff(ctx *context.Context) {
|
||||||
ctx.Data["CommitStatus"] = models.CalcCommitStatus(statuses)
|
ctx.Data["CommitStatus"] = models.CalcCommitStatus(statuses)
|
||||||
ctx.Data["CommitStatuses"] = statuses
|
ctx.Data["CommitStatuses"] = statuses
|
||||||
|
|
||||||
verification := models.ParseCommitWithSignature(commit)
|
verification := asymkey_model.ParseCommitWithSignature(commit)
|
||||||
ctx.Data["Verification"] = verification
|
ctx.Data["Verification"] = verification
|
||||||
ctx.Data["Author"] = user_model.ValidateCommitWithEmail(commit)
|
ctx.Data["Author"] = user_model.ValidateCommitWithEmail(commit)
|
||||||
ctx.Data["Parents"] = parents
|
ctx.Data["Parents"] = parents
|
||||||
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
|
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
|
||||||
|
|
||||||
if err := models.CalculateTrustStatus(verification, ctx.Repo.Repository, nil); err != nil {
|
if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
|
||||||
|
return models.IsUserRepoAdmin(ctx.Repo.Repository, user)
|
||||||
|
}, nil); err != nil {
|
||||||
ctx.ServerError("CalculateTrustStatus", err)
|
ctx.ServerError("CalculateTrustStatus", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/upload"
|
"code.gitea.io/gitea/modules/upload"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
comment_service "code.gitea.io/gitea/services/comments"
|
comment_service "code.gitea.io/gitea/services/comments"
|
||||||
"code.gitea.io/gitea/services/forms"
|
"code.gitea.io/gitea/services/forms"
|
||||||
issue_service "code.gitea.io/gitea/services/issue"
|
issue_service "code.gitea.io/gitea/services/issue"
|
||||||
|
@ -1583,12 +1584,12 @@ func ViewIssue(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
ctx.Data["WillSign"] = false
|
ctx.Data["WillSign"] = false
|
||||||
if ctx.User != nil {
|
if ctx.User != nil {
|
||||||
sign, key, _, err := pull.SignMerge(ctx.User, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitRefName())
|
sign, key, _, err := asymkey_service.SignMerge(pull, ctx.User, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitRefName())
|
||||||
ctx.Data["WillSign"] = sign
|
ctx.Data["WillSign"] = sign
|
||||||
ctx.Data["SigningKey"] = key
|
ctx.Data["SigningKey"] = key
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrWontSign(err) {
|
if asymkey_service.IsErrWontSign(err) {
|
||||||
ctx.Data["WontSignReason"] = err.(*models.ErrWontSign).Reason
|
ctx.Data["WontSignReason"] = err.(*asymkey_service.ErrWontSign).Reason
|
||||||
} else {
|
} else {
|
||||||
ctx.Data["WontSignReason"] = "error"
|
ctx.Data["WontSignReason"] = "error"
|
||||||
log.Error("Error whilst checking if could sign pr %d in repo %s. Error: %v", pull.ID, pull.BaseRepo.FullName(), err)
|
log.Error("Error whilst checking if could sign pr %d in repo %s. Error: %v", pull.ID, pull.BaseRepo.FullName(), err)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
@ -34,6 +35,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/routers/utils"
|
"code.gitea.io/gitea/routers/utils"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
"code.gitea.io/gitea/services/forms"
|
"code.gitea.io/gitea/services/forms"
|
||||||
"code.gitea.io/gitea/services/mailer"
|
"code.gitea.io/gitea/services/mailer"
|
||||||
"code.gitea.io/gitea/services/migrations"
|
"code.gitea.io/gitea/services/migrations"
|
||||||
|
@ -62,7 +64,7 @@ func Settings(ctx *context.Context) {
|
||||||
ctx.Data["DisableNewPushMirrors"] = setting.Mirror.DisableNewPush
|
ctx.Data["DisableNewPushMirrors"] = setting.Mirror.DisableNewPush
|
||||||
ctx.Data["DefaultMirrorInterval"] = setting.Mirror.DefaultInterval
|
ctx.Data["DefaultMirrorInterval"] = setting.Mirror.DefaultInterval
|
||||||
|
|
||||||
signing, _ := models.SigningKey(ctx.Repo.Repository.RepoPath())
|
signing, _ := asymkey_service.SigningKey(ctx.Repo.Repository.RepoPath())
|
||||||
ctx.Data["SigningKeyAvailable"] = len(signing) > 0
|
ctx.Data["SigningKeyAvailable"] = len(signing) > 0
|
||||||
ctx.Data["SigningSettings"] = setting.Repository.Signing
|
ctx.Data["SigningSettings"] = setting.Repository.Signing
|
||||||
pushMirrors, err := repo_model.GetPushMirrorsByRepoID(ctx.Repo.Repository.ID)
|
pushMirrors, err := repo_model.GetPushMirrorsByRepoID(ctx.Repo.Repository.ID)
|
||||||
|
@ -476,7 +478,6 @@ func SettingsPost(ctx *context.Context) {
|
||||||
|
|
||||||
case "signing":
|
case "signing":
|
||||||
changed := false
|
changed := false
|
||||||
|
|
||||||
trustModel := repo_model.ToTrustModel(form.TrustModel)
|
trustModel := repo_model.ToTrustModel(form.TrustModel)
|
||||||
if trustModel != repo.TrustModel {
|
if trustModel != repo.TrustModel {
|
||||||
repo.TrustModel = trustModel
|
repo.TrustModel = trustModel
|
||||||
|
@ -673,7 +674,7 @@ func SettingsPost(ctx *context.Context) {
|
||||||
ctx.Repo.GitRepo.Close()
|
ctx.Repo.GitRepo.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo_service.DeleteRepository(ctx.User, ctx.Repo.Repository); err != nil {
|
if err := repo_service.DeleteRepository(ctx.User, ctx.Repo.Repository, true); err != nil {
|
||||||
ctx.ServerError("DeleteRepository", err)
|
ctx.ServerError("DeleteRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1029,7 +1030,7 @@ func DeployKeys(ctx *context.Context) {
|
||||||
ctx.Data["PageIsSettingsKeys"] = true
|
ctx.Data["PageIsSettingsKeys"] = true
|
||||||
ctx.Data["DisableSSH"] = setting.SSH.Disabled
|
ctx.Data["DisableSSH"] = setting.SSH.Disabled
|
||||||
|
|
||||||
keys, err := models.ListDeployKeys(&models.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
|
keys, err := asymkey_model.ListDeployKeys(db.DefaultContext, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListDeployKeys", err)
|
ctx.ServerError("ListDeployKeys", err)
|
||||||
return
|
return
|
||||||
|
@ -1045,7 +1046,7 @@ func DeployKeysPost(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
|
ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
|
||||||
ctx.Data["PageIsSettingsKeys"] = true
|
ctx.Data["PageIsSettingsKeys"] = true
|
||||||
|
|
||||||
keys, err := models.ListDeployKeys(&models.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
|
keys, err := asymkey_model.ListDeployKeys(db.DefaultContext, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListDeployKeys", err)
|
ctx.ServerError("ListDeployKeys", err)
|
||||||
return
|
return
|
||||||
|
@ -1057,11 +1058,11 @@ func DeployKeysPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := models.CheckPublicKeyString(form.Content)
|
content, err := asymkey_model.CheckPublicKeyString(form.Content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrSSHDisabled(err) {
|
if db.IsErrSSHDisabled(err) {
|
||||||
ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
|
ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
|
||||||
} else if models.IsErrKeyUnableVerify(err) {
|
} else if asymkey_model.IsErrKeyUnableVerify(err) {
|
||||||
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
||||||
} else {
|
} else {
|
||||||
ctx.Data["HasError"] = true
|
ctx.Data["HasError"] = true
|
||||||
|
@ -1072,20 +1073,20 @@ func DeployKeysPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := models.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, !form.IsWritable)
|
key, err := asymkey_model.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, !form.IsWritable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Data["HasError"] = true
|
ctx.Data["HasError"] = true
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrDeployKeyAlreadyExist(err):
|
case asymkey_model.IsErrDeployKeyAlreadyExist(err):
|
||||||
ctx.Data["Err_Content"] = true
|
ctx.Data["Err_Content"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_been_used"), tplDeployKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.settings.key_been_used"), tplDeployKeys, &form)
|
||||||
case models.IsErrKeyAlreadyExist(err):
|
case asymkey_model.IsErrKeyAlreadyExist(err):
|
||||||
ctx.Data["Err_Content"] = true
|
ctx.Data["Err_Content"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplDeployKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplDeployKeys, &form)
|
||||||
case models.IsErrKeyNameAlreadyUsed(err):
|
case asymkey_model.IsErrKeyNameAlreadyUsed(err):
|
||||||
ctx.Data["Err_Title"] = true
|
ctx.Data["Err_Title"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
||||||
case models.IsErrDeployKeyNameAlreadyUsed(err):
|
case asymkey_model.IsErrDeployKeyNameAlreadyUsed(err):
|
||||||
ctx.Data["Err_Title"] = true
|
ctx.Data["Err_Title"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
||||||
default:
|
default:
|
||||||
|
@ -1101,7 +1102,7 @@ func DeployKeysPost(ctx *context.Context) {
|
||||||
|
|
||||||
// DeleteDeployKey response for deleting a deploy key
|
// DeleteDeployKey response for deleting a deploy key
|
||||||
func DeleteDeployKey(ctx *context.Context) {
|
func DeleteDeployKey(ctx *context.Context) {
|
||||||
if err := models.DeleteDeployKey(ctx.User, ctx.FormInt64("id")); err != nil {
|
if err := asymkey_service.DeleteDeployKey(ctx.User, ctx.FormInt64("id")); err != nil {
|
||||||
ctx.Flash.Error("DeleteDeployKey: " + err.Error())
|
ctx.Flash.Error("DeleteDeployKey: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success"))
|
ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success"))
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -61,7 +62,7 @@ func TestAddReadOnlyDeployKey(t *testing.T) {
|
||||||
DeployKeysPost(ctx)
|
DeployKeysPost(ctx)
|
||||||
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
|
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
|
||||||
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &models.DeployKey{
|
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||||
Name: addKeyForm.Title,
|
Name: addKeyForm.Title,
|
||||||
Content: addKeyForm.Content,
|
Content: addKeyForm.Content,
|
||||||
Mode: perm.AccessModeRead,
|
Mode: perm.AccessModeRead,
|
||||||
|
@ -91,7 +92,7 @@ func TestAddReadWriteOnlyDeployKey(t *testing.T) {
|
||||||
DeployKeysPost(ctx)
|
DeployKeysPost(ctx)
|
||||||
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
|
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
|
||||||
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &models.DeployKey{
|
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||||
Name: addKeyForm.Title,
|
Name: addKeyForm.Title,
|
||||||
Content: addKeyForm.Content,
|
Content: addKeyForm.Content,
|
||||||
Mode: perm.AccessModeWrite,
|
Mode: perm.AccessModeWrite,
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
|
@ -777,9 +778,11 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
|
||||||
ctx.Data["LatestCommit"] = latestCommit
|
ctx.Data["LatestCommit"] = latestCommit
|
||||||
if latestCommit != nil {
|
if latestCommit != nil {
|
||||||
|
|
||||||
verification := models.ParseCommitWithSignature(latestCommit)
|
verification := asymkey_model.ParseCommitWithSignature(latestCommit)
|
||||||
|
|
||||||
if err := models.CalculateTrustStatus(verification, ctx.Repo.Repository, nil); err != nil {
|
if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
|
||||||
|
return models.IsUserRepoAdmin(ctx.Repo.Repository, user)
|
||||||
|
}, nil); err != nil {
|
||||||
ctx.ServerError("CalculateTrustStatus", err)
|
ctx.ServerError("CalculateTrustStatus", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -827,7 +828,7 @@ func repoIDMap(ctxUser *user_model.User, issueCountByRepo map[int64]int64, unitT
|
||||||
|
|
||||||
// ShowSSHKeys output all the ssh keys of user by uid
|
// ShowSSHKeys output all the ssh keys of user by uid
|
||||||
func ShowSSHKeys(ctx *context.Context, uid int64) {
|
func ShowSSHKeys(ctx *context.Context, uid int64) {
|
||||||
keys, err := models.ListPublicKeys(uid, db.ListOptions{})
|
keys, err := asymkey_model.ListPublicKeys(uid, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListPublicKeys", err)
|
ctx.ServerError("ListPublicKeys", err)
|
||||||
return
|
return
|
||||||
|
@ -843,7 +844,7 @@ func ShowSSHKeys(ctx *context.Context, uid int64) {
|
||||||
|
|
||||||
// ShowGPGKeys output all the public GPG keys of user by uid
|
// ShowGPGKeys output all the public GPG keys of user by uid
|
||||||
func ShowGPGKeys(ctx *context.Context, uid int64) {
|
func ShowGPGKeys(ctx *context.Context, uid int64) {
|
||||||
keys, err := models.ListGPGKeys(uid, db.ListOptions{})
|
keys, err := asymkey_model.ListGPGKeys(db.DefaultContext, uid, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListGPGKeys", err)
|
ctx.ServerError("ListGPGKeys", err)
|
||||||
return
|
return
|
||||||
|
@ -851,9 +852,9 @@ func ShowGPGKeys(ctx *context.Context, uid int64) {
|
||||||
entities := make([]*openpgp.Entity, 0)
|
entities := make([]*openpgp.Entity, 0)
|
||||||
failedEntitiesID := make([]string, 0)
|
failedEntitiesID := make([]string, 0)
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
e, err := models.GPGKeyToEntity(k)
|
e, err := asymkey_model.GPGKeyToEntity(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrGPGKeyImportNotExist(err) {
|
if asymkey_model.IsErrGPGKeyImportNotExist(err) {
|
||||||
failedEntitiesID = append(failedEntitiesID, k.KeyID)
|
failedEntitiesID = append(failedEntitiesID, k.KeyID)
|
||||||
continue //Skip previous import without backup of imported armored key
|
continue //Skip previous import without backup of imported armored key
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ package setting
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
"code.gitea.io/gitea/services/forms"
|
"code.gitea.io/gitea/services/forms"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -51,9 +52,9 @@ func KeysPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
switch form.Type {
|
switch form.Type {
|
||||||
case "principal":
|
case "principal":
|
||||||
content, err := models.CheckPrincipalKeyString(ctx.User, form.Content)
|
content, err := asymkey_model.CheckPrincipalKeyString(ctx.User, form.Content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrSSHDisabled(err) {
|
if db.IsErrSSHDisabled(err) {
|
||||||
ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
|
ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Error(ctx.Tr("form.invalid_ssh_principal", err.Error()))
|
ctx.Flash.Error(ctx.Tr("form.invalid_ssh_principal", err.Error()))
|
||||||
|
@ -61,10 +62,10 @@ func KeysPost(ctx *context.Context) {
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err = models.AddPrincipalKey(ctx.User.ID, content, 0); err != nil {
|
if _, err = asymkey_model.AddPrincipalKey(ctx.User.ID, content, 0); err != nil {
|
||||||
ctx.Data["HasPrincipalError"] = true
|
ctx.Data["HasPrincipalError"] = true
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrKeyAlreadyExist(err), models.IsErrKeyNameAlreadyUsed(err):
|
case asymkey_model.IsErrKeyAlreadyExist(err), asymkey_model.IsErrKeyNameAlreadyUsed(err):
|
||||||
loadKeysData(ctx)
|
loadKeysData(ctx)
|
||||||
|
|
||||||
ctx.Data["Err_Content"] = true
|
ctx.Data["Err_Content"] = true
|
||||||
|
@ -77,36 +78,36 @@ func KeysPost(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
|
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
case "gpg":
|
case "gpg":
|
||||||
token := models.VerificationToken(ctx.User, 1)
|
token := asymkey_model.VerificationToken(ctx.User, 1)
|
||||||
lastToken := models.VerificationToken(ctx.User, 0)
|
lastToken := asymkey_model.VerificationToken(ctx.User, 0)
|
||||||
|
|
||||||
keys, err := models.AddGPGKey(ctx.User.ID, form.Content, token, form.Signature)
|
keys, err := asymkey_model.AddGPGKey(ctx.User.ID, form.Content, token, form.Signature)
|
||||||
if err != nil && models.IsErrGPGInvalidTokenSignature(err) {
|
if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
|
||||||
keys, err = models.AddGPGKey(ctx.User.ID, form.Content, lastToken, form.Signature)
|
keys, err = asymkey_model.AddGPGKey(ctx.User.ID, form.Content, lastToken, form.Signature)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Data["HasGPGError"] = true
|
ctx.Data["HasGPGError"] = true
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrGPGKeyParsing(err):
|
case asymkey_model.IsErrGPGKeyParsing(err):
|
||||||
ctx.Flash.Error(ctx.Tr("form.invalid_gpg_key", err.Error()))
|
ctx.Flash.Error(ctx.Tr("form.invalid_gpg_key", err.Error()))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
case models.IsErrGPGKeyIDAlreadyUsed(err):
|
case asymkey_model.IsErrGPGKeyIDAlreadyUsed(err):
|
||||||
loadKeysData(ctx)
|
loadKeysData(ctx)
|
||||||
|
|
||||||
ctx.Data["Err_Content"] = true
|
ctx.Data["Err_Content"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("settings.gpg_key_id_used"), tplSettingsKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("settings.gpg_key_id_used"), tplSettingsKeys, &form)
|
||||||
case models.IsErrGPGInvalidTokenSignature(err):
|
case asymkey_model.IsErrGPGInvalidTokenSignature(err):
|
||||||
loadKeysData(ctx)
|
loadKeysData(ctx)
|
||||||
ctx.Data["Err_Content"] = true
|
ctx.Data["Err_Content"] = true
|
||||||
ctx.Data["Err_Signature"] = true
|
ctx.Data["Err_Signature"] = true
|
||||||
ctx.Data["KeyID"] = err.(models.ErrGPGInvalidTokenSignature).ID
|
ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGInvalidTokenSignature).ID
|
||||||
ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form)
|
||||||
case models.IsErrGPGNoEmailFound(err):
|
case asymkey_model.IsErrGPGNoEmailFound(err):
|
||||||
loadKeysData(ctx)
|
loadKeysData(ctx)
|
||||||
|
|
||||||
ctx.Data["Err_Content"] = true
|
ctx.Data["Err_Content"] = true
|
||||||
ctx.Data["Err_Signature"] = true
|
ctx.Data["Err_Signature"] = true
|
||||||
ctx.Data["KeyID"] = err.(models.ErrGPGNoEmailFound).ID
|
ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGNoEmailFound).ID
|
||||||
ctx.RenderWithErr(ctx.Tr("settings.gpg_no_key_email_found"), tplSettingsKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("settings.gpg_no_key_email_found"), tplSettingsKeys, &form)
|
||||||
default:
|
default:
|
||||||
ctx.ServerError("AddPublicKey", err)
|
ctx.ServerError("AddPublicKey", err)
|
||||||
|
@ -124,21 +125,21 @@ func KeysPost(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.add_gpg_key_success", keyIDs))
|
ctx.Flash.Success(ctx.Tr("settings.add_gpg_key_success", keyIDs))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
case "verify_gpg":
|
case "verify_gpg":
|
||||||
token := models.VerificationToken(ctx.User, 1)
|
token := asymkey_model.VerificationToken(ctx.User, 1)
|
||||||
lastToken := models.VerificationToken(ctx.User, 0)
|
lastToken := asymkey_model.VerificationToken(ctx.User, 0)
|
||||||
|
|
||||||
keyID, err := models.VerifyGPGKey(ctx.User.ID, form.KeyID, token, form.Signature)
|
keyID, err := asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, token, form.Signature)
|
||||||
if err != nil && models.IsErrGPGInvalidTokenSignature(err) {
|
if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
|
||||||
keyID, err = models.VerifyGPGKey(ctx.User.ID, form.KeyID, lastToken, form.Signature)
|
keyID, err = asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, lastToken, form.Signature)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Data["HasGPGVerifyError"] = true
|
ctx.Data["HasGPGVerifyError"] = true
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrGPGInvalidTokenSignature(err):
|
case asymkey_model.IsErrGPGInvalidTokenSignature(err):
|
||||||
loadKeysData(ctx)
|
loadKeysData(ctx)
|
||||||
ctx.Data["VerifyingID"] = form.KeyID
|
ctx.Data["VerifyingID"] = form.KeyID
|
||||||
ctx.Data["Err_Signature"] = true
|
ctx.Data["Err_Signature"] = true
|
||||||
ctx.Data["KeyID"] = err.(models.ErrGPGInvalidTokenSignature).ID
|
ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGInvalidTokenSignature).ID
|
||||||
ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form)
|
||||||
default:
|
default:
|
||||||
ctx.ServerError("VerifyGPG", err)
|
ctx.ServerError("VerifyGPG", err)
|
||||||
|
@ -147,11 +148,11 @@ func KeysPost(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.verify_gpg_key_success", keyID))
|
ctx.Flash.Success(ctx.Tr("settings.verify_gpg_key_success", keyID))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
case "ssh":
|
case "ssh":
|
||||||
content, err := models.CheckPublicKeyString(form.Content)
|
content, err := asymkey_model.CheckPublicKeyString(form.Content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrSSHDisabled(err) {
|
if db.IsErrSSHDisabled(err) {
|
||||||
ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
|
ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
|
||||||
} else if models.IsErrKeyUnableVerify(err) {
|
} else if asymkey_model.IsErrKeyUnableVerify(err) {
|
||||||
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
|
ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
|
||||||
|
@ -160,20 +161,20 @@ func KeysPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = models.AddPublicKey(ctx.User.ID, form.Title, content, 0); err != nil {
|
if _, err = asymkey_model.AddPublicKey(ctx.User.ID, form.Title, content, 0); err != nil {
|
||||||
ctx.Data["HasSSHError"] = true
|
ctx.Data["HasSSHError"] = true
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrKeyAlreadyExist(err):
|
case asymkey_model.IsErrKeyAlreadyExist(err):
|
||||||
loadKeysData(ctx)
|
loadKeysData(ctx)
|
||||||
|
|
||||||
ctx.Data["Err_Content"] = true
|
ctx.Data["Err_Content"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplSettingsKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplSettingsKeys, &form)
|
||||||
case models.IsErrKeyNameAlreadyUsed(err):
|
case asymkey_model.IsErrKeyNameAlreadyUsed(err):
|
||||||
loadKeysData(ctx)
|
loadKeysData(ctx)
|
||||||
|
|
||||||
ctx.Data["Err_Title"] = true
|
ctx.Data["Err_Title"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), tplSettingsKeys, &form)
|
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), tplSettingsKeys, &form)
|
||||||
case models.IsErrKeyUnableVerify(err):
|
case asymkey_model.IsErrKeyUnableVerify(err):
|
||||||
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
default:
|
default:
|
||||||
|
@ -196,14 +197,14 @@ func DeleteKey(ctx *context.Context) {
|
||||||
|
|
||||||
switch ctx.FormString("type") {
|
switch ctx.FormString("type") {
|
||||||
case "gpg":
|
case "gpg":
|
||||||
if err := models.DeleteGPGKey(ctx.User, ctx.FormInt64("id")); err != nil {
|
if err := asymkey_model.DeleteGPGKey(ctx.User, ctx.FormInt64("id")); err != nil {
|
||||||
ctx.Flash.Error("DeleteGPGKey: " + err.Error())
|
ctx.Flash.Error("DeleteGPGKey: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
|
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
|
||||||
}
|
}
|
||||||
case "ssh":
|
case "ssh":
|
||||||
keyID := ctx.FormInt64("id")
|
keyID := ctx.FormInt64("id")
|
||||||
external, err := models.PublicKeyIsExternallyManaged(keyID)
|
external, err := asymkey_model.PublicKeyIsExternallyManaged(keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("sshKeysExternalManaged", err)
|
ctx.ServerError("sshKeysExternalManaged", err)
|
||||||
return
|
return
|
||||||
|
@ -213,13 +214,13 @@ func DeleteKey(ctx *context.Context) {
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := models.DeletePublicKey(ctx.User, keyID); err != nil {
|
if err := asymkey_service.DeletePublicKey(ctx.User, keyID); err != nil {
|
||||||
ctx.Flash.Error("DeletePublicKey: " + err.Error())
|
ctx.Flash.Error("DeletePublicKey: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success"))
|
ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success"))
|
||||||
}
|
}
|
||||||
case "principal":
|
case "principal":
|
||||||
if err := models.DeletePublicKey(ctx.User, ctx.FormInt64("id")); err != nil {
|
if err := asymkey_service.DeletePublicKey(ctx.User, ctx.FormInt64("id")); err != nil {
|
||||||
ctx.Flash.Error("DeletePublicKey: " + err.Error())
|
ctx.Flash.Error("DeletePublicKey: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.ssh_principal_deletion_success"))
|
ctx.Flash.Success(ctx.Tr("settings.ssh_principal_deletion_success"))
|
||||||
|
@ -234,32 +235,32 @@ func DeleteKey(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadKeysData(ctx *context.Context) {
|
func loadKeysData(ctx *context.Context) {
|
||||||
keys, err := models.ListPublicKeys(ctx.User.ID, db.ListOptions{})
|
keys, err := asymkey_model.ListPublicKeys(ctx.User.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListPublicKeys", err)
|
ctx.ServerError("ListPublicKeys", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Keys"] = keys
|
ctx.Data["Keys"] = keys
|
||||||
|
|
||||||
externalKeys, err := models.PublicKeysAreExternallyManaged(keys)
|
externalKeys, err := asymkey_model.PublicKeysAreExternallyManaged(keys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListPublicKeys", err)
|
ctx.ServerError("ListPublicKeys", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["ExternalKeys"] = externalKeys
|
ctx.Data["ExternalKeys"] = externalKeys
|
||||||
|
|
||||||
gpgkeys, err := models.ListGPGKeys(ctx.User.ID, db.ListOptions{})
|
gpgkeys, err := asymkey_model.ListGPGKeys(db.DefaultContext, ctx.User.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListGPGKeys", err)
|
ctx.ServerError("ListGPGKeys", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["GPGKeys"] = gpgkeys
|
ctx.Data["GPGKeys"] = gpgkeys
|
||||||
tokenToSign := models.VerificationToken(ctx.User, 1)
|
tokenToSign := asymkey_model.VerificationToken(ctx.User, 1)
|
||||||
|
|
||||||
// generate a new aes cipher using the csrfToken
|
// generate a new aes cipher using the csrfToken
|
||||||
ctx.Data["TokenToSign"] = tokenToSign
|
ctx.Data["TokenToSign"] = tokenToSign
|
||||||
|
|
||||||
principals, err := models.ListPrincipalKeys(ctx.User.ID, db.ListOptions{})
|
principals, err := asymkey_model.ListPrincipalKeys(ctx.User.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListPrincipalKeys", err)
|
ctx.ServerError("ListPrincipalKeys", err)
|
||||||
return
|
return
|
||||||
|
|
30
services/asymkey/deploy_key.go
Normal file
30
services/asymkey/deploy_key.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// 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 (
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 := models.DeleteDeployKey(ctx, doer, id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := committer.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return asymkey_model.RewriteAllPublicKeys()
|
||||||
|
}
|
16
services/asymkey/main_test.go
Normal file
16
services/asymkey/main_test.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// 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 asymkey
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
unittest.MainTest(m, filepath.Join("..", ".."))
|
||||||
|
}
|
|
@ -1,15 +1,17 @@
|
||||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package asymkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -63,6 +65,22 @@ func signingModeFromStrings(modeStrings []string) []signingMode {
|
||||||
return returnable
|
return returnable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
// SigningKey returns the KeyID and git Signature for the repo
|
// SigningKey returns the KeyID and git Signature for the repo
|
||||||
func SigningKey(repoPath string) (string, *git.Signature) {
|
func SigningKey(repoPath string) (string, *git.Signature) {
|
||||||
if setting.Repository.Signing.SigningKey == "none" {
|
if setting.Repository.Signing.SigningKey == "none" {
|
||||||
|
@ -124,7 +142,7 @@ Loop:
|
||||||
case always:
|
case always:
|
||||||
break Loop
|
break Loop
|
||||||
case pubkey:
|
case pubkey:
|
||||||
keys, err := ListGPGKeys(u.ID, db.ListOptions{})
|
keys, err := asymkey_model.ListGPGKeys(db.DefaultContext, u.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", nil, err
|
return false, "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -145,9 +163,9 @@ Loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignWikiCommit determines if we should sign the commits to this repository wiki
|
// SignWikiCommit determines if we should sign the commits to this repository wiki
|
||||||
func SignWikiCommit(repo *repo_model.Repository, u *user_model.User) (bool, string, *git.Signature, error) {
|
func SignWikiCommit(repoWikiPath string, u *user_model.User) (bool, string, *git.Signature, error) {
|
||||||
rules := signingModeFromStrings(setting.Repository.Signing.Wiki)
|
rules := signingModeFromStrings(setting.Repository.Signing.Wiki)
|
||||||
signingKey, sig := SigningKey(repo.WikiPath())
|
signingKey, sig := SigningKey(repoWikiPath)
|
||||||
if signingKey == "" {
|
if signingKey == "" {
|
||||||
return false, "", nil, &ErrWontSign{noKey}
|
return false, "", nil, &ErrWontSign{noKey}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +178,7 @@ Loop:
|
||||||
case always:
|
case always:
|
||||||
break Loop
|
break Loop
|
||||||
case pubkey:
|
case pubkey:
|
||||||
keys, err := ListGPGKeys(u.ID, db.ListOptions{})
|
keys, err := asymkey_model.ListGPGKeys(db.DefaultContext, u.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", nil, err
|
return false, "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -176,7 +194,7 @@ Loop:
|
||||||
return false, "", nil, &ErrWontSign{twofa}
|
return false, "", nil, &ErrWontSign{twofa}
|
||||||
}
|
}
|
||||||
case parentSigned:
|
case parentSigned:
|
||||||
gitRepo, err := git.OpenRepository(repo.WikiPath())
|
gitRepo, err := git.OpenRepository(repoWikiPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", nil, err
|
return false, "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -188,7 +206,7 @@ Loop:
|
||||||
if commit.Signature == nil {
|
if commit.Signature == nil {
|
||||||
return false, "", nil, &ErrWontSign{parentSigned}
|
return false, "", nil, &ErrWontSign{parentSigned}
|
||||||
}
|
}
|
||||||
verification := ParseCommitWithSignature(commit)
|
verification := asymkey_model.ParseCommitWithSignature(commit)
|
||||||
if !verification.Verified {
|
if !verification.Verified {
|
||||||
return false, "", nil, &ErrWontSign{parentSigned}
|
return false, "", nil, &ErrWontSign{parentSigned}
|
||||||
}
|
}
|
||||||
|
@ -198,9 +216,9 @@ Loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignCRUDAction determines if we should sign a CRUD commit to this repository
|
// SignCRUDAction determines if we should sign a CRUD commit to this repository
|
||||||
func SignCRUDAction(repo *repo_model.Repository, u *user_model.User, tmpBasePath, parentCommit string) (bool, string, *git.Signature, error) {
|
func SignCRUDAction(repoPath string, u *user_model.User, tmpBasePath, parentCommit string) (bool, string, *git.Signature, error) {
|
||||||
rules := signingModeFromStrings(setting.Repository.Signing.CRUDActions)
|
rules := signingModeFromStrings(setting.Repository.Signing.CRUDActions)
|
||||||
signingKey, sig := SigningKey(repo.RepoPath())
|
signingKey, sig := SigningKey(repoPath)
|
||||||
if signingKey == "" {
|
if signingKey == "" {
|
||||||
return false, "", nil, &ErrWontSign{noKey}
|
return false, "", nil, &ErrWontSign{noKey}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +231,7 @@ Loop:
|
||||||
case always:
|
case always:
|
||||||
break Loop
|
break Loop
|
||||||
case pubkey:
|
case pubkey:
|
||||||
keys, err := ListGPGKeys(u.ID, db.ListOptions{})
|
keys, err := asymkey_model.ListGPGKeys(db.DefaultContext, u.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", nil, err
|
return false, "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -241,7 +259,7 @@ Loop:
|
||||||
if commit.Signature == nil {
|
if commit.Signature == nil {
|
||||||
return false, "", nil, &ErrWontSign{parentSigned}
|
return false, "", nil, &ErrWontSign{parentSigned}
|
||||||
}
|
}
|
||||||
verification := ParseCommitWithSignature(commit)
|
verification := asymkey_model.ParseCommitWithSignature(commit)
|
||||||
if !verification.Verified {
|
if !verification.Verified {
|
||||||
return false, "", nil, &ErrWontSign{parentSigned}
|
return false, "", nil, &ErrWontSign{parentSigned}
|
||||||
}
|
}
|
||||||
|
@ -249,3 +267,122 @@ Loop:
|
||||||
}
|
}
|
||||||
return true, signingKey, sig, nil
|
return true, signingKey, sig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignMerge determines if we should sign a PR merge commit to the base repository
|
||||||
|
func SignMerge(pr *models.PullRequest, 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 := asymkey_model.ListGPGKeys(db.DefaultContext, 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 := models.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 := asymkey_model.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 := asymkey_model.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 := asymkey_model.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 := asymkey_model.ParseCommitWithSignature(commit)
|
||||||
|
if !verification.Verified {
|
||||||
|
return false, "", nil, &ErrWontSign{commitsSigned}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, signingKey, signer, nil
|
||||||
|
}
|
49
services/asymkey/ssh_key.go
Normal file
49
services/asymkey/ssh_key.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// 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 (
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
|
||||||
|
func DeletePublicKey(doer *user_model.User, id int64) (err error) {
|
||||||
|
key, err := asymkey_model.GetPublicKeyByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has access to delete this key.
|
||||||
|
if !doer.IsAdmin && doer.ID != key.OwnerID {
|
||||||
|
return asymkey_model.ErrKeyAccessDenied{
|
||||||
|
UserID: doer.ID,
|
||||||
|
KeyID: key.ID,
|
||||||
|
Note: "public",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, committer, err := db.TxContext()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
if err = asymkey_model.DeletePublicKeys(ctx, id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = committer.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
committer.Close()
|
||||||
|
|
||||||
|
if key.Type == asymkey_model.KeyTypePrincipal {
|
||||||
|
return asymkey_model.RewriteAllPrincipalKeys()
|
||||||
|
}
|
||||||
|
|
||||||
|
return asymkey_model.RewriteAllPublicKeys()
|
||||||
|
}
|
83
services/asymkey/ssh_key_test.go
Normal file
83
services/asymkey/ssh_key_test.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// 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 (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
|
"code.gitea.io/gitea/models/login"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAddLdapSSHPublicKeys(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
||||||
|
s := &login.Source{ID: 1}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
keyString string
|
||||||
|
number int
|
||||||
|
keyContents []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
keyString: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment\n",
|
||||||
|
number: 1,
|
||||||
|
keyContents: []string{
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyString: `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment
|
||||||
|
ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment`,
|
||||||
|
number: 2,
|
||||||
|
keyContents: []string{
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
||||||
|
"ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag=",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyString: `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment
|
||||||
|
# comment asmdna,ndp
|
||||||
|
ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment`,
|
||||||
|
number: 2,
|
||||||
|
keyContents: []string{
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
||||||
|
"ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag=",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyString: `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment
|
||||||
|
382488320jasdj1lasmva/vasodifipi4193-fksma.cm
|
||||||
|
ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment`,
|
||||||
|
number: 2,
|
||||||
|
keyContents: []string{
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM=",
|
||||||
|
"ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag=",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, kase := range testCases {
|
||||||
|
s.ID = int64(i) + 20
|
||||||
|
asymkey_model.AddPublicKeysBySource(user, s, []string{kase.keyString})
|
||||||
|
keys, err := asymkey_model.ListPublicKeysBySource(user.ID, s.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
assert.Len(t, keys, kase.number)
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
assert.Contains(t, kase.keyContents, key.Content)
|
||||||
|
}
|
||||||
|
for _, key := range keys {
|
||||||
|
DeletePublicKey(user, key.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -59,8 +59,8 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str
|
||||||
}
|
}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
if isAttributeSSHPublicKeySet && models.SynchronizePublicKeys(user, source.loginSource, sr.SSHPublicKey) {
|
if isAttributeSSHPublicKeySet && asymkey_model.SynchronizePublicKeys(user, source.loginSource, sr.SSHPublicKey) {
|
||||||
return user, models.RewriteAllPublicKeys()
|
return user, asymkey_model.RewriteAllPublicKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
|
@ -95,8 +95,8 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str
|
||||||
|
|
||||||
mailer.SendRegisterNotifyMail(user)
|
mailer.SendRegisterNotifyMail(user)
|
||||||
|
|
||||||
if isAttributeSSHPublicKeySet && models.AddPublicKeysBySource(user, source.loginSource, sr.SSHPublicKey) {
|
if isAttributeSSHPublicKeySet && asymkey_model.AddPublicKeysBySource(user, source.loginSource, sr.SSHPublicKey) {
|
||||||
err = models.RewriteAllPublicKeys()
|
err = asymkey_model.RewriteAllPublicKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil && len(source.AttributeAvatar) > 0 {
|
if err == nil && len(source.AttributeAvatar) > 0 {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -68,7 +68,7 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
|
||||||
log.Warn("SyncExternalUsers: Cancelled at update of %s before completed update of users", source.loginSource.Name)
|
log.Warn("SyncExternalUsers: Cancelled at update of %s before completed update of users", source.loginSource.Name)
|
||||||
// Rewrite authorized_keys file if LDAP Public SSH Key attribute is set and any key was added or removed
|
// Rewrite authorized_keys file if LDAP Public SSH Key attribute is set and any key was added or removed
|
||||||
if sshKeysNeedUpdate {
|
if sshKeysNeedUpdate {
|
||||||
err = models.RewriteAllPublicKeys()
|
err = asymkey_model.RewriteAllPublicKeys()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RewriteAllPublicKeys: %v", err)
|
log.Error("RewriteAllPublicKeys: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
|
||||||
|
|
||||||
if err == nil && isAttributeSSHPublicKeySet {
|
if err == nil && isAttributeSSHPublicKeySet {
|
||||||
log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", source.loginSource.Name, usr.Name)
|
log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", source.loginSource.Name, usr.Name)
|
||||||
if models.AddPublicKeysBySource(usr, source.loginSource, su.SSHPublicKey) {
|
if asymkey_model.AddPublicKeysBySource(usr, source.loginSource, su.SSHPublicKey) {
|
||||||
sshKeysNeedUpdate = true
|
sshKeysNeedUpdate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
|
||||||
}
|
}
|
||||||
} else if updateExisting {
|
} else if updateExisting {
|
||||||
// Synchronize SSH Public Key if that attribute is set
|
// Synchronize SSH Public Key if that attribute is set
|
||||||
if isAttributeSSHPublicKeySet && models.SynchronizePublicKeys(usr, source.loginSource, su.SSHPublicKey) {
|
if isAttributeSSHPublicKeySet && asymkey_model.SynchronizePublicKeys(usr, source.loginSource, su.SSHPublicKey) {
|
||||||
sshKeysNeedUpdate = true
|
sshKeysNeedUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
|
||||||
|
|
||||||
// Rewrite authorized_keys file if LDAP Public SSH Key attribute is set and any key was added or removed
|
// Rewrite authorized_keys file if LDAP Public SSH Key attribute is set and any key was added or removed
|
||||||
if sshKeysNeedUpdate {
|
if sshKeysNeedUpdate {
|
||||||
err = models.RewriteAllPublicKeys()
|
err = asymkey_model.RewriteAllPublicKeys()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RewriteAllPublicKeys: %v", err)
|
log.Error("RewriteAllPublicKeys: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/updatechecker"
|
"code.gitea.io/gitea/modules/updatechecker"
|
||||||
|
@ -67,7 +68,7 @@ func registerRewriteAllPublicKeys() {
|
||||||
RunAtStart: false,
|
RunAtStart: false,
|
||||||
Schedule: "@every 72h",
|
Schedule: "@every 72h",
|
||||||
}, func(_ context.Context, _ *user_model.User, _ Config) error {
|
}, func(_ context.Context, _ *user_model.User, _ Config) error {
|
||||||
return models.RewriteAllPublicKeys()
|
return asymkey_model.RewriteAllPublicKeys()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ func registerRewriteAllPrincipalKeys() {
|
||||||
RunAtStart: false,
|
RunAtStart: false,
|
||||||
Schedule: "@every 72h",
|
Schedule: "@every 72h",
|
||||||
}, func(_ context.Context, _ *user_model.User, _ Config) error {
|
}, func(_ context.Context, _ *user_model.User, _ Config) error {
|
||||||
return models.RewriteAllPrincipalKeys()
|
return asymkey_model.RewriteAllPrincipalKeys()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/references"
|
"code.gitea.io/gitea/modules/references"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
issue_service "code.gitea.io/gitea/services/issue"
|
issue_service "code.gitea.io/gitea/services/issue"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -218,7 +219,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
|
||||||
// Determine if we should sign
|
// Determine if we should sign
|
||||||
signArg := ""
|
signArg := ""
|
||||||
if git.CheckGitVersionAtLeast("1.7.9") == nil {
|
if git.CheckGitVersionAtLeast("1.7.9") == nil {
|
||||||
sign, keyID, signer, _ := pr.SignMerge(doer, tmpBasePath, "HEAD", trackingBranch)
|
sign, keyID, signer, _ := asymkey_service.SignMerge(pr, doer, tmpBasePath, "HEAD", trackingBranch)
|
||||||
if sign {
|
if sign {
|
||||||
signArg = "-S" + keyID
|
signArg = "-S" + keyID
|
||||||
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
||||||
|
@ -553,7 +554,7 @@ func IsSignedIfRequired(pr *models.PullRequest, doer *user_model.User) (bool, er
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sign, _, _, err := pr.SignMerge(doer, pr.BaseRepo.RepoPath(), pr.BaseBranch, pr.GetGitRefName())
|
sign, _, _, err := asymkey_service.SignMerge(pr, doer, pr.BaseRepo.RepoPath(), pr.BaseBranch, pr.GetGitRefName())
|
||||||
|
|
||||||
return sign, err
|
return sign, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -171,7 +170,7 @@ func doArchive(r *ArchiveRequest) (*repo_model.RepoArchiver, error) {
|
||||||
rd.Close()
|
rd.Close()
|
||||||
}()
|
}()
|
||||||
var done = make(chan error)
|
var done = make(chan error)
|
||||||
repo, err := models.LoadArchiverRepo(archiver)
|
repo, err := repo_model.GetRepositoryByID(archiver.RepoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("archiver.LoadRepo failed: %v", err)
|
return nil, fmt.Errorf("archiver.LoadRepo failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -55,7 +56,7 @@ func CountDivergingCommits(repo *repo_model.Repository, branch string) (*git.Div
|
||||||
// GetPayloadCommitVerification returns the verification information of a commit
|
// GetPayloadCommitVerification returns the verification information of a commit
|
||||||
func GetPayloadCommitVerification(commit *git.Commit) *structs.PayloadCommitVerification {
|
func GetPayloadCommitVerification(commit *git.Commit) *structs.PayloadCommitVerification {
|
||||||
verification := &structs.PayloadCommitVerification{}
|
verification := &structs.PayloadCommitVerification{}
|
||||||
commitVerification := models.ParseCommitWithSignature(commit)
|
commitVerification := asymkey_model.ParseCommitWithSignature(commit)
|
||||||
if commit.Signature != nil {
|
if commit.Signature != nil {
|
||||||
verification.Signature = commit.Signature.Signature
|
verification.Signature = commit.Signature.Signature
|
||||||
verification.Payload = commit.Signature.Payload
|
verification.Payload = commit.Signature.Payload
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
"code.gitea.io/gitea/services/gitdiff"
|
"code.gitea.io/gitea/services/gitdiff"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -217,7 +218,7 @@ func (t *TemporaryUploadRepository) CommitTreeWithDate(author, committer *user_m
|
||||||
|
|
||||||
// Determine if we should sign
|
// Determine if we should sign
|
||||||
if git.CheckGitVersionAtLeast("1.7.9") == nil {
|
if git.CheckGitVersionAtLeast("1.7.9") == nil {
|
||||||
sign, keyID, signer, _ := models.SignCRUDAction(t.repo, author, t.basePath, "HEAD")
|
sign, keyID, signer, _ := asymkey_service.SignCRUDAction(t.repo.RepoPath(), author, t.basePath, "HEAD")
|
||||||
if sign {
|
if sign {
|
||||||
args = append(args, "-S"+keyID)
|
args = append(args, "-S"+keyID)
|
||||||
if t.repo.GetTrustModel() == repo_model.CommitterTrustModel || t.repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
if t.repo.GetTrustModel() == repo_model.CommitterTrustModel || t.repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
|
|
||||||
stdcharset "golang.org/x/net/html/charset"
|
stdcharset "golang.org/x/net/html/charset"
|
||||||
|
@ -458,9 +459,9 @@ func VerifyBranchProtection(repo *repo_model.Repository, doer *user_model.User,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if protectedBranch.RequireSignedCommits {
|
if protectedBranch.RequireSignedCommits {
|
||||||
_, _, _, err := models.SignCRUDAction(repo, doer, repo.RepoPath(), branchName)
|
_, _, _, err := asymkey_service.SignCRUDAction(repo.RepoPath(), doer, repo.RepoPath(), branchName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !models.IsErrWontSign(err) {
|
if !asymkey_service.IsErrWontSign(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return models.ErrUserCannotCommit{
|
return models.ErrUserCannotCommit{
|
||||||
|
|
|
@ -31,13 +31,15 @@ func CreateRepository(doer, owner *user_model.User, opts models.CreateRepoOption
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRepository deletes a repository for a user or organization.
|
// DeleteRepository deletes a repository for a user or organization.
|
||||||
func DeleteRepository(doer *user_model.User, repo *repo_model.Repository) error {
|
func DeleteRepository(doer *user_model.User, repo *repo_model.Repository, notify bool) error {
|
||||||
if err := pull_service.CloseRepoBranchesPulls(doer, repo); err != nil {
|
if err := pull_service.CloseRepoBranchesPulls(doer, repo); err != nil {
|
||||||
log.Error("CloseRepoBranchesPulls failed: %v", err)
|
log.Error("CloseRepoBranchesPulls failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the repo itself has webhooks, we need to trigger them before deleting it...
|
if notify {
|
||||||
notification.NotifyDeleteRepository(doer, repo)
|
// If the repo itself has webhooks, we need to trigger them before deleting it...
|
||||||
|
notification.NotifyDeleteRepository(doer, repo)
|
||||||
|
}
|
||||||
|
|
||||||
err := models.DeleteRepository(doer, repo.OwnerID, repo.ID)
|
err := models.DeleteRepository(doer, repo.OwnerID, repo.ID)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
admin_model "code.gitea.io/gitea/models/admin"
|
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/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -31,11 +32,11 @@ func DeleteUser(u *user_model.User) error {
|
||||||
return fmt.Errorf("%s is an organization not a user", u.Name)
|
return fmt.Errorf("%s is an organization not a user", u.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, commiter, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer commiter.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
// Note: A user owns any repository or belongs to any organization
|
// Note: A user owns any repository or belongs to any organization
|
||||||
// cannot perform delete operation.
|
// cannot perform delete operation.
|
||||||
|
@ -60,14 +61,15 @@ func DeleteUser(u *user_model.User) error {
|
||||||
return fmt.Errorf("DeleteUser: %v", err)
|
return fmt.Errorf("DeleteUser: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := commiter.Commit(); err != nil {
|
if err := committer.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
committer.Close()
|
||||||
|
|
||||||
if err = models.RewriteAllPublicKeys(); err != nil {
|
if err = asymkey_model.RewriteAllPublicKeys(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = models.RewriteAllPrincipalKeys(); err != nil {
|
if err = asymkey_model.RewriteAllPrincipalKeys(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/sync"
|
"code.gitea.io/gitea/modules/sync"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -225,7 +226,7 @@ func updateWikiPage(doer *user_model.User, repo *repo_model.Repository, oldWikiN
|
||||||
|
|
||||||
committer := doer.NewGitSig()
|
committer := doer.NewGitSig()
|
||||||
|
|
||||||
sign, signingKey, signer, _ := models.SignWikiCommit(repo, doer)
|
sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(repo.WikiPath(), doer)
|
||||||
if sign {
|
if sign {
|
||||||
commitTreeOpts.KeyID = signingKey
|
commitTreeOpts.KeyID = signingKey
|
||||||
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
||||||
|
@ -343,7 +344,7 @@ func DeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, wikiName
|
||||||
|
|
||||||
committer := doer.NewGitSig()
|
committer := doer.NewGitSig()
|
||||||
|
|
||||||
sign, signingKey, signer, _ := models.SignWikiCommit(repo, doer)
|
sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(repo.WikiPath(), doer)
|
||||||
if sign {
|
if sign {
|
||||||
commitTreeOpts.KeyID = signingKey
|
commitTreeOpts.KeyID = signingKey
|
||||||
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
|
||||||
|
|
Loading…
Add table
Reference in a new issue