mirror of https://github.com/go-gitea/gitea
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 * mergepull/17941/head
parent
0a9fcf63a4
commit
3ca5dc7e32
@ -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) |
||||
} |
@ -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", |
||||
) |
||||
} |
@ -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 |
||||
} |
@ -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() |
||||
} |
@ -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("..", "..")) |
||||
} |
@ -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() |
||||
} |
@ -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) |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue