ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / internal/modules/auth/service_users.go

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / internal/modules/auth/service_users.go
DateNot specified in source
RepositoryJanady13/missionmatch
Revision39df94f92b2a33f852481fe1954dabed841524bb
Branchw0-aedt-compliance
Path or archive memberinternal/modules/auth/service_users.go
Original SHA-2563d8cfb88cfa1d5503413ea13b6f0d92d16b440e0e4b61c9602041e66a697852b
Git blob SHAc34106fbb05311c83704c455f8c81e95c9ba6ba0
Reading-copy SHA-2565441ed5cede91fb7aa62bc450256ca809e0af494212debd07c43066879533d69

Original source ↗

Recovered source transcript

Credential-bearing and unrelated personal details were removed from this reading copy. The source identity and original checksum remain recorded.

package auth import ( "context" "errors" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" "github.com/missionworkforce/missionmatch/internal/platform/audit" "github.com/missionworkforce/missionmatch/internal/platform/security" "github.com/missionworkforce/missionmatch/internal/platform/tenant" ) // ErrEmailInUse is returned when an invite targets an email that already exists (global uniqueness). var ErrEmailInUse = errors.New("auth: email already in use") // targetUser is the org scoped view of a user read inside a tenant tx. Because the read runs under // RLS, a row only comes back when the target is in the actor's org, which is the same org proof. type targetUser struct { id uuid.UUID email string role string status string } // Invite creates an invited user in the actor's org and a one time activation token. The capability // (user.invite) is enforced by middleware; the separation of duties bound (invited role strictly // below the actor) is enforced here. func (s *Service) Invite(ctx context.Context, in InviteInput, ip, ua string) (InviteResult, error) { if _, err := s.db(); err != nil { return InviteResult{}, err } actor, ok := tenant.UserFromContext(ctx) if !ok { return InviteResult{}, ErrForbidden } org, ok := tenant.OrgFromContext(ctx) if !ok { return InviteResult{}, tenant.ErrNoTenant } if !security.ValidRole(security.Role(in.Role)) || !security.CanInvite(security.Role(actor.Role), security.Role(in.Role)) { // Record the over authority attempt in the org's own audit trail (in tenant), matching the // ChangeRole denial, so a privilege escalation attempt is visible to the org, not only the // platform NULL org log. _ = s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { return s.auditTx(ctx, tx, actor, audit.Event{ Action: "authz.deny", EntityType: "capability", EntityID: "user.invite", IPAddress: ip, UserAgent: ua, NewValues: reasonJSON("invited role not below actor")}) }) return InviteResult{}, ErrForbidden } token, tokenHash, err := security.NewSessionToken() if err != nil { return InviteResult{}, err } var newUserID uuid.UUID err = s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { e := tx.QueryRow(ctx, `INSERT INTO users (organization_id, email, full_name, role, status) VALUES (NULLIF(current_setting('app.current_org_id', true), '')::uuid, $1, $2, $3, 'invited') RETURNING id`, in.Email, in.FullName, in.Role).Scan(&newUserID) if isUniqueViolation(e) { return ErrEmailInUse } if e != nil { return e } if _, e := tx.Exec(ctx, `SELECT auth_create_invite($1,$2,$3,$4,$5,$6,$7)`, mustUUID(org), in.Email, newUserID, tokenHash, in.Role, s.deps.InviteSeconds, mustUUID(actor.UserID)); e != nil { return e } return s.auditTx(ctx, tx, actor, audit.Event{Action: "user.invite.created", EntityType: "user", EntityID: newUserID.String(), IPAddress: ip, UserAgent: ua}) }) if err != nil { return InviteResult{}, err } return InviteResult{Token: token, UserID: newUserID.String()}, nil } // AcceptInvite redeems an invite or activation token, sets the password, and issues an auth_pending // session so the new user proceeds to MFA enrollment. It is public and token keyed. func (s *Service) AcceptInvite(ctx context.Context, in AcceptInput, ip, ua string) (LoginResult, error) { db, err := s.db() if err != nil { return LoginResult{}, err } hash, ver, err := s.deps.Hasher.Hash(in.Password) if err != nil { return LoginResult{}, err // includes ErrPasswordTooLong } var userID, orgID uuid.UUID err = db.QueryRow(ctx, `SELECT user_id, organization_id FROM auth_accept_invite($1,$2,$3)`, security.HashSessionToken(in.Token), hash, ver).Scan(&userID, &orgID) if errors.Is(err, pgx.ErrNoRows) { return LoginResult{}, ErrInvalidCredentials // invalid, expired, used, or a mismatched invite } if err != nil { return LoginResult{}, err } token, tokenHash, err := security.NewSessionToken() if err != nil { return LoginResult{}, err } if _, err := db.Exec(ctx, `SELECT auth_create_session($1,$2,$3,'auth_pending',false,$4,$4,$5,$6)`, tokenHash, userID, orgID, s.deps.PendingSeconds, ip, ua); err != nil { return LoginResult{}, err } _ = s.deps.Audit.System(ctx, audit.Event{Action: "user.invite.accepted", ActorUserID: &userID, IPAddress: ip, UserAgent: ua}) return LoginResult{Token: token, MFAEnrolled: false}, nil } // ReissueRecovery issues a fresh single use activation link for a target user after proving same org // membership through an RLS scoped read. The target redeems it to set a new password. This is the // admin recovery path; public self serve forgot password is [credential removed] to sub phase 2.9. func (s *Service) ReissueRecovery(ctx context.Context, targetID string, ip, ua string) (InviteResult, error) { if _, err := s.db(); err != nil { return InviteResult{}, err } actor, ok := tenant.UserFromContext(ctx) if !ok { return InviteResult{}, ErrForbidden } org, ok := tenant.OrgFromContext(ctx) if !ok { return InviteResult{}, tenant.ErrNoTenant } token, tokenHash, err := security.NewSessionToken() if err != nil { return InviteResult{}, err } var target targetUser err = s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { t, e := readTarget(ctx, tx, targetID) if e != nil { return e } target = t if !security.OutRanks(security.Role(actor.Role), security.Role(t.role)) { return ErrForbidden } if _, e := tx.Exec(ctx, `SELECT auth_create_invite($1,$2,$3,$4,$5,$6,$7)`, mustUUID(org), t.email, t.id, tokenHash, t.role, s.deps.InviteSeconds, mustUUID(actor.UserID)); e != nil { return e } return s.auditTx(ctx, tx, actor, audit.Event{Action: "user.recovery.reissued", EntityType: "user", EntityID: t.id.String(), IPAddress: ip, UserAgent: ua}) }) if err != nil { return InviteResult{}, err } return InviteResult{Token: token, UserID: target.id.String()}, nil } // ChangeRole sets a target user's role, enforcing that the actor outranks both the current and the // new role and never changes their own role. Because no role outranks owner, owner accounts cannot be // demoted or promoted to through the API; owner replacement is a migrator operation. It revokes the // target's sessions so a downgrade cannot ride an old elevated session. func (s *Service) ChangeRole(ctx context.Context, targetID string, in RoleChangeInput, ip, ua string) error { if _, err := s.db(); err != nil { return err } actor, ok := tenant.UserFromContext(ctx) if !ok { return ErrForbidden } if actor.UserID == targetID { return ErrForbidden // no self role change } if !security.ValidRole(security.Role(in.Role)) { return ErrBadRequest } return s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { t, e := readTarget(ctx, tx, targetID) if e != nil { return e } if !security.OutRanks(security.Role(actor.Role), security.Role(t.role)) || !security.OutRanks(security.Role(actor.Role), security.Role(in.Role)) { _ = s.auditTx(ctx, tx, actor, audit.Event{Action: "authz.deny", EntityType: "user", EntityID: t.id.String(), IPAddress: ip, UserAgent: ua, NewValues: reasonJSON("role change above authority")}) return ErrForbidden } if _, e := tx.Exec(ctx, `UPDATE users SET role = $1, updated_at = now() WHERE id = $2`, in.Role, t.id); e != nil { return e } if _, e := tx.Exec(ctx, `SELECT auth_revoke_user_sessions($1,$2)`, t.id, nil); e != nil { return e } return s.auditTx(ctx, tx, actor, audit.Event{ Action: "authz.permission.change", EntityType: "user", EntityID: t.id.String(), OldValues: reasonRole(t.role), NewValues: reasonRole(in.Role), IPAddress: ip, UserAgent: ua}) }) } // ChangeStatus enables or disables a target user. Disabling revokes the target's sessions. func (s *Service) ChangeStatus(ctx context.Context, targetID string, in StatusChangeInput, ip, ua string) error { if _, err := s.db(); err != nil { return err } actor, ok := tenant.UserFromContext(ctx) if !ok { return ErrForbidden } if actor.UserID == targetID { return ErrForbidden } if in.Status != "active" && in.Status != "disabled" { return ErrBadRequest } return s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { t, e := readTarget(ctx, tx, targetID) if e != nil { return e } if !security.OutRanks(security.Role(actor.Role), security.Role(t.role)) { return ErrForbidden } if _, e := tx.Exec(ctx, `UPDATE users SET status = $1, updated_at = now() WHERE id = $2`, in.Status, t.id); e != nil { return e } action := "user.enabled" if in.Status == "disabled" { action = "user.disabled" if _, e := tx.Exec(ctx, `SELECT auth_revoke_user_sessions($1,$2)`, t.id, nil); e != nil { return e } } return s.auditTx(ctx, tx, actor, audit.Event{Action: action, EntityType: "user", EntityID: t.id.String(), IPAddress: ip, UserAgent: ua}) }) } // ResetMFA clears a target user's MFA (admin path), after proving same org and that the actor // outranks the target. The target must re enroll on next login. The target's sessions are revoked. func (s *Service) ResetMFA(ctx context.Context, targetID string, ip, ua string) error { if _, err := s.db(); err != nil { return err } actor, ok := tenant.UserFromContext(ctx) if !ok { return ErrForbidden } return s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { t, e := readTarget(ctx, tx, targetID) if e != nil { return e } if !security.OutRanks(security.Role(actor.Role), security.Role(t.role)) && actor.UserID != targetID { return ErrForbidden } if _, e := tx.Exec(ctx, `SELECT auth_mfa_reset($1)`, t.id); e != nil { return e } if _, e := tx.Exec(ctx, `SELECT auth_revoke_user_sessions($1,$2)`, t.id, nil); e != nil { return e } return s.auditTx(ctx, tx, actor, audit.Event{Action: "auth.mfa.reset", EntityType: "user", EntityID: t.id.String(), IPAddress: ip, UserAgent: ua}) }) } // SessionInfo returns the SPA view of the current authenticated session. func (s *Service) SessionInfo(ctx context.Context) (SessionInfo, error) { if _, err := s.db(); err != nil { return SessionInfo{}, err } p, ok := tenant.UserFromContext(ctx) if !ok { return SessionInfo{}, ErrForbidden } org, _ := tenant.OrgFromContext(ctx) info := SessionInfo{UserID: p.UserID, OrgID: org, Role: p.Role} err := s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { return tx.QueryRow(ctx, `SELECT mfa_enrolled FROM users WHERE id = $1`, mustUUID(p.UserID)).Scan(&info.MFAEnrolled) }) return info, err } // ListUsers returns the org's users (RLS scoped). Gated on RequireRole(admin) at the route. func (s *Service) ListUsers(ctx context.Context) ([]UserSummary, error) { if _, err := s.db(); err != nil { return nil, err } var out []UserSummary err := s.deps.DB.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { rows, e := tx.Query(ctx, `SELECT id, email, full_name, role, status, mfa_enrolled FROM users ORDER BY created_at DESC LIMIT 500`) if e != nil { return e } defer rows.Close() for rows.Next() { var u UserSummary var id uuid.UUID if e := rows.Scan(&id, &u.Email, &u.FullName, &u.Role, &u.Status, &u.MFAEnrolled); e != nil { return e } u.ID = id.String() out = append(out, u) } return rows.Err() }) return out, err } // auditSessionRejected records a probing or stale token attempt against a non empty session cookie. func (s *Service) auditSessionRejected(ctx context.Context, ip, ua string) { _ = s.deps.Audit.System(ctx, audit.Event{Action: "auth.session.rejected", IPAddress: ip, UserAgent: ua}) } // readTarget reads a user inside the tenant tx. RLS scopes it to the actor's org, so a not found row // proves the target is in another org (or does not exist): the same org check is the read itself. func readTarget(ctx context.Context, tx pgx.Tx, id string) (targetUser, error) { uid := mustUUID(id) var t targetUser err := tx.QueryRow(ctx, `SELECT id, email, role, status FROM users WHERE id = $1`, uid).Scan(&t.id, &t.email, &t.role, &t.status) if errors.Is(err, pgx.ErrNoRows) { return targetUser{}, ErrNotFound } return t, err } func (s *Service) auditTx(ctx context.Context, tx pgx.Tx, actor tenant.Principal, e audit.Event) error { id := mustUUID(actor.UserID) e.ActorUserID = &id return s.deps.Audit.OnTx(ctx, tx, e) } func isUniqueViolation(err error) bool { var pgErr *pgconn.PgError return errors.As(err, &pgErr) && pgErr.Code == "23505" }

Search equations, builds, manuscript text, and recovered sources.