Documentation
¶
Overview ¶
Package userstore is a SQLite-backed store for users, personal access tokens, per-repo memberships, and invite keys. The git-backed repo content itself lives in gitstore — userstore only owns access metadata.
Index ¶
- Constants
- Variables
- type Activity
- type InviteKey
- type Membership
- type PAT
- type Store
- func (s *Store) AddMember(repoID, userID, role string) error
- func (s *Store) Close() error
- func (s *Store) CountActivity(repoID string) (int, error)
- func (s *Store) CountOwnedRepos(userID string) (int, error)
- func (s *Store) CountRepoMembers(repoID string) (int, error)
- func (s *Store) CountUsers() (int, error)
- func (s *Store) DB() *sql.DB
- func (s *Store) DeleteInviteKey(repoID, keyID string) error
- func (s *Store) DeletePAT(userID, patID string) error
- func (s *Store) GetRole(repoID, userID string) (string, error)
- func (s *Store) GetUserByEmail(email string) (*User, error)
- func (s *Store) GetUserByID(id string) (*User, error)
- func (s *Store) IsMember(repoID, userID string) (bool, error)
- func (s *Store) ListActivity(repoID string, limit, offset int) ([]Activity, error)
- func (s *Store) ListInviteKeys(repoID string) ([]InviteKey, error)
- func (s *Store) ListPATs(userID string) ([]PAT, error)
- func (s *Store) ListRepoMembers(repoID string) ([]Membership, error)
- func (s *Store) ListUserRepos(userID string) ([]Membership, error)
- func (s *Store) MintInviteKey(repoID, createdBy, label string) (*InviteKey, string, error)
- func (s *Store) MintPAT(userID, label string) (*PAT, string, error)
- func (s *Store) RecordActivity(repoID, userID, action, detail string) error
- func (s *Store) RemoveMember(repoID, userID string) error
- func (s *Store) RepoHasOwner(repoID string) (bool, error)
- func (s *Store) RepoOwners(repoID string) ([]string, error)
- func (s *Store) ResolveInviteKey(raw string) (string, error)
- func (s *Store) ResolvePAT(raw string) (string, error)
- func (s *Store) UpsertGoogleUser(email, name, googleSub string) (*User, bool, error)
- type User
Constants ¶
const ( RoleOwner = "owner" RoleMember = "member" )
RoleOwner has full control of a repo (mint invite keys, delete repo). RoleMember can read and write pages.
const InviteKeyPrefix = "ctxi_"
InviteKeyPrefix marks raw repo invite keys (separates them from PATs at a glance).
const PATPrefix = "ctxp_"
PATPrefix is prepended to every personal access token's raw value so they are visually distinct from session JWTs / invite keys when leaked.
Variables ¶
var ErrExpired = errors.New("userstore: invite key expired")
ErrExpired is returned when an invite key exists but has passed its expiry.
var ErrLastOwner = errors.New("userstore: cannot remove the last owner")
ErrLastOwner is returned when removing a member would leave a repo with no owner.
var ErrNotFound = errors.New("userstore: not found")
ErrNotFound is returned when a lookup misses.
Functions ¶
This section is empty.
Types ¶
type Activity ¶
Activity is one recorded member action (push/pull) on a repo. Email is joined in from the users table by ListActivity. Detail is an opaque JSON blob (pushed paths for "push", client/agent for "pull"); "" when absent.
type InviteKey ¶
type InviteKey struct {
ID string
RepoID string
Label string
CreatedBy string
CreatedAt time.Time
ExpiresAt time.Time
}
InviteKey is a stored row (no raw secret).
type Membership ¶
type Membership struct {
RepoID string
UserID string
Role string
AddedAt time.Time
// Email is populated by ListRepoMembers (joined from the users table).
// Queries that do not join users leave it empty.
Email string
}
Membership describes one (repo_id, user_id) row.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store wraps the SQLite database holding access metadata.
func (*Store) AddMember ¶
AddMember adds userID to repoID with the given role (idempotent). If a row already exists, the role is preserved (call with RoleOwner first when claiming a brand-new repo).
func (*Store) CountActivity ¶
CountActivity returns the total number of events stored for repoID (bounded by activityRetentionPerRepo). Used to drive pagination.
func (*Store) CountOwnedRepos ¶ added in v0.5.0
CountOwnedRepos returns how many distinct repos the user owns (role=owner). The hosted quota policy compares this against the free-tier repo cap.
func (*Store) CountRepoMembers ¶ added in v0.5.0
CountRepoMembers returns the number of people with any role in repo. The owner counts as a member, matching the free-tier "N members per repo" cap.
func (*Store) CountUsers ¶
CountUsers returns the total number of users.
func (*Store) DeleteInviteKey ¶
DeleteInviteKey revokes an invite key. Caller MUST verify the user is an owner of the repo.
func (*Store) GetUserByEmail ¶
GetUserByEmail returns a user by email (case-insensitive) or ErrNotFound.
func (*Store) GetUserByID ¶
GetUserByID returns a user by id or ErrNotFound.
func (*Store) ListActivity ¶
ListActivity returns a page of events for repoID (reverse-chronological), each with the actor's email joined from the users table. limit <= 0 defaults to 50; offset < 0 is treated as 0.
func (*Store) ListInviteKeys ¶
ListInviteKeys returns every invite key for a repo (no raw values).
func (*Store) ListRepoMembers ¶
func (s *Store) ListRepoMembers(repoID string) ([]Membership, error)
ListRepoMembers returns every member of a repo, with each member's email joined in from the users table.
func (*Store) ListUserRepos ¶
func (s *Store) ListUserRepos(userID string) ([]Membership, error)
ListUserRepos returns every repo_id the user belongs to, with their role.
func (*Store) MintInviteKey ¶
MintInviteKey creates a new invite key for repo, returning the row and the raw key (only returned once).
func (*Store) MintPAT ¶
MintPAT creates a new PAT for user_id with the given label and returns both the database record and the raw token (only returned once).
func (*Store) RecordActivity ¶
RecordActivity appends one event to a repo's feed, then prunes the feed back to activityRetentionPerRepo newest events. Best-effort: callers log-and-ignore.
func (*Store) RemoveMember ¶
RemoveMember removes userID from repoID. It returns ErrNotFound if the user is not a member, or ErrLastOwner if removing them would leave the repo with no owner.
func (*Store) RepoHasOwner ¶
RepoHasOwner reports whether at least one row exists for repo with role=owner.
func (*Store) RepoOwners ¶ added in v0.5.0
RepoOwners returns the user IDs of every owner of repo (possibly empty). The hosted quota policy treats a repo as uncapped if any owner is subscribed.
func (*Store) ResolveInviteKey ¶
ResolveInviteKey returns the repo_id for a raw invite key. It returns ErrNotFound if the key is unknown, or ErrExpired if it has passed its TTL.
func (*Store) ResolvePAT ¶
ResolvePAT returns the user_id for a raw PAT, or ErrNotFound. Also bumps last_used_at.
func (*Store) UpsertGoogleUser ¶
UpsertGoogleUser creates a user keyed by Google sub/email or updates the existing row's name and last_login_at. Returns the resulting User and whether this was a fresh insert (the very first sign-in for this email).