package meta import ( "context" "nadir/internal/auth" "nadir/internal/module" "nadir/internal/rbac" "github.com/danielgtaylor/huma/v2" ) // WhoamiInput carries the session cookie. The endpoint is not behind the RBAC // middleware (it requires no specific permission), so it validates the session // itself. type WhoamiInput struct { SessionID string `cookie:"nadir_session_id"` } // WhoamiBody reports who the caller is and, per module, which permissions they // actually hold. Combined with /api/_modules (the full module/permission grid), // this gives the frontend everything it needs to render the permission matrix. type WhoamiBody struct { Username string `json:"username" example:"urania" doc:"Authenticated username"` Permissions map[string][]string `json:"permissions" doc:"Module ID -> permissions the caller holds. Modules where they hold none are omitted."` } type WhoamiOutput struct{ Body WhoamiBody } // RegisterWhoami adds the current-user endpoint. It resolves the caller's // concrete grants by asking the RBAC store about each module's permissions, // so "*" wildcards in roles are expanded for free. func RegisterWhoami(api huma.API, sessions *auth.SessionStore, roles *rbac.RBAC, mods []module.Module) { huma.Register(api, huma.Operation{ OperationID: "whoami", Method: "GET", Path: "/api/whoami", Summary: "Get the current user and their permissions", Description: "Returns the authenticated username and, per module, the " + "permissions the caller holds (wildcards resolved). Pair with " + "/api/_modules to render the full permission matrix.", Tags: []string{"Meta"}, Errors: []int{401}, }, func(ctx context.Context, in *WhoamiInput) (*WhoamiOutput, error) { sess, ok := sessions.GetByToken(in.SessionID) if !ok { return nil, huma.Error401Unauthorized("unauthorized") } held := make(map[string][]string) for _, m := range mods { var perms []string for _, p := range m.Permissions() { if roles.Can(sess.Username, m.ID(), p) { perms = append(perms, string(p)) } } if len(perms) > 0 { held[m.ID()] = perms } } out := &WhoamiOutput{} out.Body = WhoamiBody{Username: sess.Username, Permissions: held} return out, nil }) }