coverage~bigbes/sr-ht-doltede3b0bbauthn/ctx.go

Coverage
100.0% 6/6 statements
Δ
โ€”
Blob
c960924
Uncovered nothing — every instrumented line ran
1 // Package authn resolves the SourceHut caller for a dolt.sr.ht request across
2 // the four authentication flows the service accepts:
3 //
4 // - the unified-login cookie (web UI), via OptionalCookieMiddleware;
5 // - a meta.sr.ht personal access token (dolt clone/push --user + Basic auth),
6 // via ResolveBasic;
7 // - a dolt Ed25519 keypair (dolt login / Bearer EdDSA JWT), via ResolveDoltJWT;
8 // - an Authorization: Bearer credential on the /mcp surface, via ResolveBearer:
9 // either a tokens.sr.ht working token, verified through sr-ht-ecore's shared
10 // validator and scoped by core.GrantRead, or a meta PAT presented without a
11 // username (bearer.go, docs/DESIGN.mcp.md ยง4).
12 //
13 // It reuses core-go's token/cookie primitives (auth.DecodeBearerToken,
14 // auth.LookupUser, auth.LookupTokenRevocation, crypto.DecryptWithoutExpiration)
15 // and dolt's creds.PubKeyToKIDStr for key-id derivation, and produces
16 // *auth.AuthContext values that AsCoreCaller maps onto the pure core.Caller
17 // domain type for the access-control matrix in package core.
18 //
19 // Production wiring: the cookie middleware and the resolvers read the meta.sr.ht
20 // user database and config from the request context, so the caller must install
21 // config.Middleware and database.Middleware upstream (see cmd/doltsrht). The
22 // meta-lookup and token-revocation calls are funnelled through the package-level
23 // MetaBackend so tests can stub them without a database or network.
24 package authn
25
26 import (
27 "context"
28
29 "sourcecraft.dev/bigbes/sr-ht-core/auth"
30
31 "sourcecraft.dev/bigbes/sr-ht-dolt/core"
32 )
33
34 // AuthMethodDoltKey labels an AuthContext resolved from a dolt Ed25519 keypair
35 // JWT. core-go has no such method; we never call auth.AuthContext.Access (which
36 // would panic on an unknown method) โ€” access is decided by core.Allowed โ€” so a
37 // private label is safe and keeps dolt-key auth distinguishable from OAuth2.
38 const AuthMethodDoltKey = "DOLT_KEY"
39
40 type contextKey struct{ name string }
41
42 var callerCtxKey = &contextKey{"authn.caller"}
43
44 // WithCaller returns a copy of ctx carrying the resolved caller. A nil ac is
45 // stored as-is and reads back as anonymous via CallerFromContext.
46 4 func WithCaller(ctx context.Context, ac *auth.AuthContext) context.Context {
47 4 return context.WithValue(ctx, callerCtxKey, ac)
48 4 }
49
50 // CallerFromContext returns the caller stored by WithCaller, or nil for an
51 // anonymous request. Unlike core-go's auth.ForContext it never panics on a
52 // missing value: an unauthenticated request is a normal, expected state for
53 // dolt.sr.ht (public browsing and public clones).
54 12 func CallerFromContext(ctx context.Context) *auth.AuthContext {
55 12 ac, _ := ctx.Value(callerCtxKey).(*auth.AuthContext)
56 12 return ac
57 12 }
58
59 // AsCoreCaller maps a resolved *auth.AuthContext onto the pure core.Caller
60 // domain type consumed by core.Allowed. A nil ac (anonymous) maps to a nil
61 // caller. Suspended is derived from the meta UserType, which independently
62 // gates every write operation.
63 6 func AsCoreCaller(ac *auth.AuthContext) *core.Caller {
64 6 if ac == nil {
65 1 return nil
66 1 }
67 5 return &core.Caller{
68 5 UserID: ac.UserID,
69 5 Username: ac.Username,
70 5 UserType: core.UserType(ac.UserType),
71 5 Suspended: ac.UserType == auth.USER_TYPE_SUSPENDED,
72 5 }
73 }