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 }