s
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
// Shared access-check primitives and errors.
|
||||
//
|
||||
// state defines its own error sentinels (ErrDenied / ErrInvalidToken /
|
||||
// ErrRepoNotFound) and stays free of any gitrpc dependency -- the cmd layer
|
||||
// maps these to HTTP/SSH outcomes. hasAccess is the single ACL-rank check
|
||||
// shared by the SSH and PAT access paths.
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"simplegit/common"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrDenied means the caller is not permitted: an anonymous caller needing
|
||||
// a grant, or an authenticated caller whose ACL grant is insufficient.
|
||||
ErrDenied = errors.New("access denied")
|
||||
// ErrInvalidToken means a PAT was presented but could not be matched (unknown
|
||||
// hash) or has expired. Distinct from anonymous (no PAT at all).
|
||||
ErrInvalidToken = errors.New("invalid or expired token")
|
||||
// ErrRepoNotFound means no DB row for the (owner, name). Surfaced to callers
|
||||
// of Open/RepoPath; access paths map it to ErrDenied so existence is never
|
||||
// leaked.
|
||||
ErrRepoNotFound = errors.New("repository not found")
|
||||
// ErrNamespaceNotFound means no repo exists in the namespace yet, so its
|
||||
// shared NamespaceID cannot be resolved. CreateRepo treats this as "mint a
|
||||
// new NamespaceID"; ACLUpsertOnNS surfaces it (grant before any repo exists).
|
||||
ErrNamespaceNotFound = errors.New("namespace does not exist")
|
||||
)
|
||||
|
||||
// hasAccess reports whether the credential (credType, credID) holds an ACL grant
|
||||
// satisfying perm on the repo (repoID) or its namespace (nsID). ACL targets are
|
||||
// polymorphic -- TargetTypeRepo or TargetTypeNS -- so a grant on either applies,
|
||||
// and the best-ranked matching grant wins. No grant means false (the public-read
|
||||
// shortcut is handled by the caller before this is called).
|
||||
func (s *LocalState) hasAccess(credType CredType, credID, repoID, nsID int64, perm common.Perm) (bool, error) {
|
||||
var acls []ACL
|
||||
err := s.engine.Where("cred_type = ? AND cred_id = ? AND ((target_type = ? AND target_id = ?) OR (target_type = ? AND target_id = ?))",
|
||||
credType, credID, TargetTypeRepo, repoID, TargetTypeNS, nsID).Find(&acls)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("lookup acl: %w", err)
|
||||
}
|
||||
best := 0
|
||||
for _, a := range acls {
|
||||
if r := common.Perm(a.Perm).PermRank(); r > best {
|
||||
best = r
|
||||
}
|
||||
}
|
||||
return best >= perm.PermRank(), nil
|
||||
}
|
||||
Reference in New Issue
Block a user