This commit is contained in:
2026-08-14 00:06:43 +02:00
parent 841a05572e
commit a9395585f8
22 changed files with 326 additions and 22 deletions
+1
View File
@@ -7,6 +7,7 @@ var (
ErrPasswordTooShort = errors.New("password must be at least 8 characters")
ErrUserNotFound = errors.New("user not found")
ErrNotCompanyMember = errors.New("not a member of company")
ErrCompanyNotFound = errors.New("company not found")
ErrInviteNotFound = errors.New("invite not found")
ErrEmailRequired = errors.New("email is required")
ErrSyntheticEmail = errors.New("synthetic migration email cannot receive invites")
+54
View File
@@ -469,7 +469,61 @@ func (s *Service) ListUserCompanies(ctx context.Context, userID uuid.UUID) ([]Co
return out, rows.Err()
}
// ListCompanies returns tenants for platform staff company switching (id + name).
// Ordered with A1 / demo sandboxes first, then name. Caps at limit (default 500).
func (s *Service) ListCompanies(ctx context.Context, limit int) ([]Company, error) {
if s == nil || s.Pool == nil {
return nil, errors.New("auth service unavailable")
}
if limit <= 0 || limit > 2000 {
limit = 500
}
const a1LegacyCompanyID = "97e1a309-3d23-4aa2-b518-8e8d7afdfec7"
rows, err := s.Pool.Query(ctx, `
SELECT c.id, c.name
FROM companies c
ORDER BY
CASE
WHEN lower(c.name) = 'a1 slovenija' THEN 0
WHEN lower(c.name) = 'local demo co' THEN 0
WHEN lower(COALESCE(c.legacy_company_id, '')) = lower($1) THEN 0
WHEN lower(c.name) IN ('platform demo', 'demo') THEN 1
ELSE 2
END,
c.name
LIMIT $2`, a1LegacyCompanyID, limit)
if err != nil {
return nil, err
}
defer rows.Close()
out := make([]Company, 0)
for rows.Next() {
var c Company
if err := rows.Scan(&c.ID, &c.Name); err != nil {
return nil, err
}
out = append(out, c)
}
return out, rows.Err()
}
// CompanyByID loads a single company or ErrNotCompanyMember-style miss via pgx.ErrNoRows.
func (s *Service) CompanyByID(ctx context.Context, companyID uuid.UUID) (Company, error) {
if s == nil || s.Pool == nil {
return Company{}, errors.New("auth service unavailable")
}
var c Company
err := s.Pool.QueryRow(ctx, `SELECT id, name FROM companies WHERE id = $1`, companyID).Scan(&c.ID, &c.Name)
if errors.Is(err, pgx.ErrNoRows) {
return Company{}, ErrCompanyNotFound
}
return c, err
}
func (s *Service) EnsureMembership(ctx context.Context, userID, companyID uuid.UUID) (Membership, error) {
if s == nil || s.Pool == nil {
return Membership{}, ErrNotCompanyMember
}
var m Membership
err := s.Pool.QueryRow(ctx, `
SELECT id, company_id, user_id, role, status
+5 -4
View File
@@ -26,8 +26,9 @@ func NewSessionManager(pool *pgxpool.Pool, cookieName string, secure bool, idleH
}
const (
SessionUserIDKey = "user_id"
SessionCompanyIDKey = "company_id"
SessionImpersonatorIDKey = "impersonator_id" // non-prod user switch: original admin/demo
SessionVersionKey = "session_version" // must match users.session_version
SessionUserIDKey = "user_id"
SessionCompanyIDKey = "company_id"
SessionImpersonatorIDKey = "impersonator_id" // non-prod user switch: original admin/demo
SessionStaffHomeCompanyKey = "staff_home_company_id" // platform admin tenant switch: home company to revert to
SessionVersionKey = "session_version" // must match users.session_version
)