1
0
forked from wrenn/wrenn

Destroy owned sandboxes on user disable and fix OAuth login resilience

When an admin disables a user, all active sandboxes (running, paused,
hibernated) for teams they own are now destroyed and their API keys
are deleted. User queries now filter by status column instead of
deleted_at, so re-enabling a user always works. OAuth login paths
use ensureDefaultTeam to auto-create a team if the user has none,
matching the email/password login behavior.
This commit is contained in:
2026-04-16 06:37:51 +06:00
parent 9ea847923c
commit fb4b67adb3
8 changed files with 97 additions and 17 deletions

View File

@ -13,7 +13,8 @@ import (
// UserService provides user management operations.
type UserService struct {
DB *db.Queries
DB *db.Queries
SandboxSvc *SandboxService
}
// AdminUserRow is the shape returned by AdminListUsers.
@ -71,6 +72,36 @@ func (s *UserService) SetUserStatus(ctx context.Context, userID pgtype.UUID, sta
if err := s.DB.DeleteAPIKeysByCreator(ctx, userID); err != nil {
slog.Warn("failed to delete API keys for deactivated user", "user_id", userID, "error", err)
}
s.destroySandboxesForOwnedTeams(ctx, userID)
}
return nil
}
// destroySandboxesForOwnedTeams destroys all active sandboxes (running, paused,
// hibernated, starting) for every team the user owns. Best-effort: errors are
// logged but do not prevent the user from being disabled.
func (s *UserService) destroySandboxesForOwnedTeams(ctx context.Context, userID pgtype.UUID) {
if s.SandboxSvc == nil {
return
}
teamIDs, err := s.DB.GetOwnedTeamIDs(ctx, userID)
if err != nil {
slog.Warn("failed to list owned teams for sandbox cleanup", "user_id", userID, "error", err)
return
}
for _, teamID := range teamIDs {
sandboxes, err := s.DB.ListActiveSandboxesByTeam(ctx, teamID)
if err != nil {
slog.Warn("failed to list active sandboxes for team", "team_id", teamID, "user_id", userID, "error", err)
continue
}
for _, sb := range sandboxes {
if err := s.SandboxSvc.Destroy(ctx, sb.ID, teamID); err != nil {
slog.Warn("failed to destroy sandbox during user disable",
"sandbox_id", sb.ID, "team_id", teamID, "user_id", userID, "error", err)
}
}
}
}