77 lines
1.6 KiB
Go
77 lines
1.6 KiB
Go
package state
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"golang.org/x/crypto/ssh"
|
|
|
|
"simplegit/common"
|
|
)
|
|
|
|
func (s *LocalState) AccessBySSHKey(ctx context.Context, key ssh.PublicKey, owner, name string, perm common.Perm) (bool, error) {
|
|
r, err := s.findRepo(owner, name)
|
|
if err != nil {
|
|
if errors.Is(err, ErrRepoNotFound) {
|
|
return false, ErrDenied
|
|
}
|
|
return false, err
|
|
}
|
|
|
|
var sk SSHKey
|
|
has, err := s.engine.Where("fingerprint = ?", fingerprint(key)).Get(&sk)
|
|
if err != nil {
|
|
return false, fmt.Errorf("lookup ssh key: %w", err)
|
|
}
|
|
if !has {
|
|
return false, ErrDenied
|
|
}
|
|
|
|
now := time.Now()
|
|
if _, err := s.engine.ID(sk.ID).Cols("last_used_at").Update(&SSHKey{LastUsedAt: &now}); err == nil {
|
|
sk.LastUsedAt = &now
|
|
}
|
|
|
|
if perm == common.PermRead && !r.IsPrivate {
|
|
return true, nil
|
|
}
|
|
ok, err := s.hasAccess(CredTypeSSH, sk.ID, r.ID, r.NamespaceID, perm)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !ok {
|
|
return false, ErrDenied
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (s *LocalState) KnownSSHKey(key ssh.PublicKey) (bool, error) {
|
|
var sk SSHKey
|
|
has, err := s.engine.Where("fingerprint = ?", fingerprint(key)).Get(&sk)
|
|
if err != nil {
|
|
return false, fmt.Errorf("lookup ssh key: %w", err)
|
|
}
|
|
if !has {
|
|
return false, ErrDenied
|
|
}
|
|
|
|
hasGrant, err := s.keyHasGrant(sk.ID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !hasGrant {
|
|
return false, ErrDenied
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (s *LocalState) keyHasGrant(credID int64) (bool, error) {
|
|
count, err := s.engine.Where("cred_type = ? AND cred_id = ?", CredTypeSSH, credID).Count(&ACL{})
|
|
if err != nil {
|
|
return false, fmt.Errorf("count ssh key grants: %w", err)
|
|
}
|
|
return count > 0, nil
|
|
}
|