83 lines
2.0 KiB
Go
83 lines
2.0 KiB
Go
package users
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/auth"
|
|
"github.com/ultisuite/ulti-backend/internal/permission"
|
|
)
|
|
|
|
// IsPlatformAdmin reports whether the user row is marked platform_admin.
|
|
func IsPlatformAdmin(ctx context.Context, db *pgxpool.Pool, externalID string) (bool, error) {
|
|
if db == nil || externalID == "" {
|
|
return false, nil
|
|
}
|
|
var admin bool
|
|
err := db.QueryRow(ctx, `
|
|
SELECT platform_admin FROM users WHERE external_id = $1
|
|
`, externalID).Scan(&admin)
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return false, nil
|
|
}
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return admin, nil
|
|
}
|
|
|
|
// GrantPlatformAdmin sets platform_admin for the given external_id.
|
|
func GrantPlatformAdmin(ctx context.Context, db *pgxpool.Pool, externalID string) error {
|
|
if db == nil {
|
|
return fmt.Errorf("database not configured")
|
|
}
|
|
if externalID == "" {
|
|
return fmt.Errorf("missing external id")
|
|
}
|
|
tag, err := db.Exec(ctx, `
|
|
UPDATE users SET platform_admin = true, updated_at = NOW()
|
|
WHERE external_id = $1
|
|
`, externalID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if tag.RowsAffected() == 0 {
|
|
return pgx.ErrNoRows
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ApplyPlatformAdminGroups adds admin RBAC groups when the user is platform_admin.
|
|
func ApplyPlatformAdminGroups(ctx context.Context, db *pgxpool.Pool, claims *auth.Claims) error {
|
|
if claims == nil || db == nil {
|
|
return nil
|
|
}
|
|
admin, err := IsPlatformAdmin(ctx, db, claims.Sub)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if admin {
|
|
claims.Groups = permission.WithPlatformAdmin(claims.Groups)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func bootstrapFirstUserAdmin(ctx context.Context, db *pgxpool.Pool, userID string) error {
|
|
var hasAdmin bool
|
|
if err := db.QueryRow(ctx, `SELECT EXISTS(SELECT 1 FROM users WHERE platform_admin = true)`).Scan(&hasAdmin); err != nil {
|
|
return err
|
|
}
|
|
if hasAdmin {
|
|
return nil
|
|
}
|
|
_, err := db.Exec(ctx, `
|
|
UPDATE users SET platform_admin = true, updated_at = NOW()
|
|
WHERE id = $1
|
|
`, userID)
|
|
return err
|
|
}
|