This commit is contained in:
Jabberwocky238
2026-07-15 11:06:48 -04:00
commit c746f88bbe
69 changed files with 14975 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
// Private-DB models for simplegit.
//
// This is a credential-centric access model: there is NO users table. The two
// things that can authenticate a git operation are an SSH public key or a PAT,
// and each is granted access to repos directly via the ACL table. This matches
// the Store interface (cmd/listener.go): AccessBySSHKey / AccessByToken resolve
// a credential and check it against a repo, with no user id in between.
//
// Anonymous access (no credential) is governed by Repo.IsPrivate: a public repo
// allows anonymous read; write always requires a credential. That special case
// lives in the store layer, not in ACL -- ACL only records explicit grants.
//
// xorm derives the schema from the struct tags via Sync2 (see InitEngine), so
// there is no hand-written DDL. GonicMapper is required so SSHKey -> "ssh_key"
// (the default SnakeMapper would produce "s_s_h_key"); this matches
// simpleconsole, whose raw-SQL joins rely on the same names.
package state
import (
"time"
"xorm.io/xorm"
"xorm.io/xorm/names"
)
// BaseModel is the common row shape: auto-increment PK plus xorm-managed
// created/updated/deleted timestamps (soft-delete via DeletedAt).
type BaseModel struct {
ID int64 `xorm:"pk autoincr" json:"id"`
CreatedAt time.Time `xorm:"created" json:"created_at"`
UpdatedAt time.Time `xorm:"updated" json:"updated_at"`
DeletedAt *time.Time `xorm:"deleted" json:"deleted_at,omitempty"`
}
// Repo is a registered repository. The on-disk bare repo lives under the git
// root; this row is the authority for its namespace/name and visibility.
type Repo struct {
BaseModel `xorm:"extends"`
NamespaceID int64 `xorm:"notnull unique(cred)" json:"namespace_id"`
Namespace string `xorm:"varchar(255) notnull index" json:"namespace"`
NameID int64 `xorm:"notnull unique(cred)" json:"name_id"`
Name string `xorm:"varchar(255) notnull" json:"name"`
IsPrivate bool `xorm:"default false" json:"is_private"` // public repos allow anonymous read
}
// SSHKey is a registered public key, resolved by fingerprint in AccessBySSHKey.
type SSHKey struct {
BaseModel `xorm:"extends"`
PublicKey string `xorm:"text notnull" json:"-"`
Fingerprint string `xorm:"varchar(255) unique notnull" json:"fingerprint"` // "SHA256:..."
KeyType string `xorm:"varchar(50) notnull" json:"key_type"` // ssh-ed25519, ssh-rsa, ...
Comment string `xorm:"varchar(255)" json:"comment,omitempty"`
LastUsedAt *time.Time `xorm:"" json:"last_used_at,omitempty"`
}
// PAT is an opaque HTTP credential. Only its sha256 hash is stored; the
// plaintext is returned once at creation. AccessByToken hashes the presented
// token and looks it up here by token_hash.
type PAT struct {
BaseModel `xorm:"extends"`
TokenHash string `xorm:"varchar(64) unique notnull" json:"-"` // hex(sha256(plaintext))
Prefix string `xorm:"varchar(20)" json:"prefix"` // first chars, for display only
Name string `xorm:"varchar(255)" json:"name"`
ExpiresAt *time.Time `xorm:"" json:"expires_at,omitempty"`
LastUsedAt *time.Time `xorm:"" json:"last_used_at,omitempty"`
}
// ACL grants a credential access to a repo. CredType selects which table CredID
// points at -- the foreign key is polymorphic by design, so it is NOT
// database-enforced: deleting a credential must clean up its ACL rows in the
// store layer. The unique(cred) group means one grant per credential per repo;
// raise it by updating perm, not by inserting a duplicate.
type ACL struct {
BaseModel `xorm:"extends"`
CredType int `xorm:"notnull unique(cred) index" json:"cred_type"` // CredTypePAT or CredTypeSSH
CredID int64 `xorm:"notnull unique(cred)" json:"cred_id"` // pats.id or ssh_keys.id (per CredType)
TargetType int `xorm:"notnull unique(cred) index" json:"target_type"` // TargetType
TargetID int64 `xorm:"notnull unique(cred)" json:"target_id"`
Perm string `xorm:"varchar(20) default 'read'" json:"perm"` // PermRead | PermWrite | PermAdmin
}
type CredType int
// Credential kinds for ACL.CredType.
const (
CredTypePAT CredType = 0 // HTTP transport (PAT)
CredTypeSSH CredType = 1 // SSH transport (public key)
)
type TargetType int
const (
TargetTypeRepo TargetType = 0
TargetTypeNS TargetType = 1
)
// InitEngine opens an xorm engine on driver/dsn, applies the GonicMapper (see
// package doc), and syncs all model tables. It mirrors simpleconsole's
// models.InitEngine so the two services share table/column naming.
func InitEngine(driverName, dataSourceName string) (*xorm.Engine, error) {
engine, err := xorm.NewEngine(driverName, dataSourceName)
if err != nil {
return nil, err
}
engine.SetTableMapper(names.GonicMapper{})
engine.SetColumnMapper(names.GonicMapper{})
if err := engine.Sync2(
new(Repo),
new(SSHKey),
new(PAT),
new(ACL),
); err != nil {
return nil, err
}
return engine, nil
}