refactor(api): 删掉没有调用方的 QuotaAvailable,修正 passkey last_used_at 的过时注释
This commit is contained in:
5 files changed
+9
-45
No files matched your search
@@ -80,7 +80,8 @@ sequenceDiagram
|
||||
API-->>Panel: 412 not_linked
|
||||
else linked
|
||||
Repo-->>API: true
|
||||
API->>Repo: QuotaAvailable(user_id)
|
||||
API->>Repo: QuotaCheck(user_id, the server's real size)
|
||||
Note over API,Repo: all four caps: servers, CPU, memory, storage
|
||||
alt quota exhausted
|
||||
Repo-->>API: false
|
||||
API-->>Panel: 403 quota_exceeded
|
||||
|
||||
@@ -335,15 +335,14 @@ func (f *fakeRepo) ServerByName(_ context.Context, n string) (*ServerRecord, err
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
func (f *fakeRepo) IsLinked(_ context.Context, u string) (bool, error) { return f.linked[u], nil }
|
||||
func (f *fakeRepo) QuotaAvailable(_ context.Context, u string) (bool, error) { return f.quota[u], nil }
|
||||
func (f *fakeRepo) IsLinked(_ context.Context, u string) (bool, error) { return f.linked[u], nil }
|
||||
|
||||
func (f *fakeRepo) QuotaCheck(_ context.Context, userID string, _ string, incoming ResourceSpec) (bool, error) {
|
||||
f.quotaChecked = append(f.quotaChecked, incoming)
|
||||
// For hermetic tests, QuotaCheck delegates to the same QuotaAvailable
|
||||
// store — tests that care about per-dimension checks should use
|
||||
// fakeQuotas with direct inspection.
|
||||
return f.QuotaAvailable(context.TODO(), userID)
|
||||
// For hermetic tests, QuotaCheck answers from the per-user quota flag —
|
||||
// tests that care about per-dimension checks should use fakeQuotas with
|
||||
// direct inspection.
|
||||
return f.quota[userID], nil
|
||||
}
|
||||
|
||||
func (f *fakeRepo) UpdateServerResources(ctx context.Context, name string, cpu, mem, stor int) error {
|
||||
|
||||
@@ -346,32 +346,6 @@ func (p *PGRepo) CompleteOwnerSetup(ctx context.Context, newUserID, code string,
|
||||
return userID, mcUUID, authSource, nil
|
||||
}
|
||||
|
||||
// QuotaAvailable treats a missing quota row or a NULL max_servers as unlimited;
|
||||
// otherwise it compares the live owned-server count against the cap (spec §9.3).
|
||||
// It is the single-dimension convenience read; handlers use the four-dimension
|
||||
// QuotaCheck. The former audit-#4 TOCTOU (check and claim in separate statements)
|
||||
// is closed inside ClaimServer, which re-runs the four-dimension gate under a
|
||||
// per-user advisory lock in the SAME transaction as the ownership write.
|
||||
func (p *PGRepo) QuotaAvailable(ctx context.Context, userID string) (bool, error) {
|
||||
var maxServers sql.NullInt64
|
||||
switch err := p.db.QueryRowContext(ctx,
|
||||
`SELECT max_servers FROM quotas WHERE user_id = $1`, userID).Scan(&maxServers); {
|
||||
case errors.Is(err, sql.ErrNoRows):
|
||||
return true, nil
|
||||
case err != nil:
|
||||
return false, err
|
||||
}
|
||||
if !maxServers.Valid {
|
||||
return true, nil
|
||||
}
|
||||
var n int64
|
||||
if err := p.db.QueryRowContext(ctx,
|
||||
`SELECT count(*) FROM servers WHERE owner_id = $1 AND deleted_at IS NULL`, userID).Scan(&n); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return n < maxServers.Int64, nil
|
||||
}
|
||||
|
||||
// QuotaCheck reports whether accepting a server with resource spec `incoming`
|
||||
// would push userID over any quota cap. excludeName is the server row whose own
|
||||
// cached resources should be excluded ("" for a fresh claim where the row
|
||||
|
||||
@@ -166,9 +166,8 @@ type StaffUser struct {
|
||||
// be public (unlike a session token), so it is safe at rest. CredentialID is the
|
||||
// authenticator's globally-unique handle (base64url) and PublicKey the COSE key
|
||||
// (base64); SignCount is the uint32 signature counter captured at registration.
|
||||
// LastUsedAt is nil until an assertion stamps it. The passkey login door now exists
|
||||
// (Public /auth/passkey/login/{begin,finish}, #72), but no path yet writes
|
||||
// last_used_at, so in practice it stays nil; wiring the stamp is a follow-up there.
|
||||
// LastUsedAt is nil until a passkey sign-in or step-up stamps it
|
||||
// (AdvanceCredentialSignCount, with the advanced counter).
|
||||
type PasskeyCredential struct {
|
||||
ID string
|
||||
UserID string
|
||||
@@ -326,9 +325,6 @@ type Repo interface {
|
||||
// the API clock so expiry is testable. It returns the effective userID plus the
|
||||
// bound mc_uuid and authSource (for the response + audit).
|
||||
RedeemPlayerBindCode(ctx context.Context, newUserID, code string, now time.Time) (userID, mcUUID, authSource string, err error)
|
||||
// QuotaAvailable reports whether the user is under their max_servers quota
|
||||
// (spec §9.3 step ②, evaluated before provisioning).
|
||||
QuotaAvailable(ctx context.Context, userID string) (bool, error)
|
||||
// QuotaCheck reports whether claiming a server with the given resource spec
|
||||
// would push the user over any of their four quota caps: max_servers,
|
||||
// max_cpu_milli, max_memory_mb, and max_storage_gb (spec §9.3 / §22). A nil
|
||||
|
||||
@@ -605,9 +605,6 @@ func TestSetQuotasReplacesEveryCap(t *testing.T) {
|
||||
|
||||
set(api.QuotaInput{MaxServers: n(0), MaxCPUMilli: n(2000), MaxMemoryMB: n(4096), MaxStorageGB: n(20)}, "0/2000/4096/20")
|
||||
gate(false)
|
||||
if ok, err := repo.QuotaAvailable(ctx, u.ID); err != nil || ok {
|
||||
t.Fatalf("QuotaAvailable at max_servers 0 = %v, %v; want false", ok, err)
|
||||
}
|
||||
if _, err := repo.ClaimServer(ctx, name, u.ID); !errors.Is(err, api.ErrQuotaExceeded) {
|
||||
t.Fatalf("claim at max_servers 0 = %v, want ErrQuotaExceeded", err)
|
||||
}
|
||||
@@ -618,9 +615,6 @@ func TestSetQuotasReplacesEveryCap(t *testing.T) {
|
||||
gate(false)
|
||||
set(api.QuotaInput{}, "-/-/-/-")
|
||||
gate(true)
|
||||
if ok, err := repo.QuotaAvailable(ctx, u.ID); err != nil || !ok {
|
||||
t.Fatalf("QuotaAvailable with every cap lifted = %v, %v; want true", ok, err)
|
||||
}
|
||||
if claimed, err := repo.ClaimServer(ctx, name, u.ID); err != nil || !claimed {
|
||||
t.Fatalf("claim with every cap lifted = %v, %v; want claimed", claimed, err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user