Files
creator-hub/internal/controlplane/api/account_deletion.go
T

117 lines
4.0 KiB
Go

package api
import (
"context"
"errors"
"net/http"
"time"
"github.com/gofiber/fiber/v3"
accountdomain "git.ipao.vip/rogee/creator-hub/internal/account"
"git.ipao.vip/rogee/creator-hub/internal/creator"
hub "git.ipao.vip/rogee/creator-hub/internal/environment"
)
func registerAccountDeletion(app *fiber.App, phaseAStore *accountdomain.Store, hubStore *hub.Store, creatorStore *creator.Store, credentials accountdomain.CredentialBridge) {
app.Delete("/api/phase-a/accounts/:id", func(c fiber.Ctx) error {
accountID := c.Params("id")
if err := phaseAStore.CheckAccountDeletion(c.Context(), accountID); err != nil {
return phaseAError(c, err)
}
if err := creatorStore.CheckOwnedAccountDeletion(c.Context(), accountID); err != nil {
return creatorError(c, err)
}
environment, hasEnvironment, err := accountEnvironment(c.Context(), hubStore, accountID)
if err != nil {
return hubError(c, err)
}
unlock := func() {}
if hasEnvironment {
aliases := []string{environment.Alias}
exitIDs := []string{}
if environment.Exit.ID != "" {
exitIDs = append(exitIDs, environment.Exit.ID)
}
unlock, err = hubStore.LockResources(c.Context(), aliases, exitIDs)
if err != nil {
return hubError(c, err)
}
defer unlock()
gateway, gatewayErr := hubStore.GetGateway(c.Context(), environment.Gateway)
if gatewayErr != nil {
return hubError(c, gatewayErr)
}
if err := creatorStore.InvalidateListener(c.Context(), accountID, "账号删除"); err != nil {
return creatorError(c, err)
}
if _, err := removeGatewayRuntime(c.Context(), hubStore, gateway, environment); err != nil {
return hubError(c, err)
}
if err := purgeAccountProfile(c.Context(), gateway, environment); err != nil {
return hubError(c, err)
}
}
if err := phaseAStore.DeleteAccountData(c.Context(), accountID); err != nil {
return phaseAError(c, err)
}
if err := creatorStore.DeleteOwnedAccountData(c.Context(), accountID); err != nil {
return creatorError(c, err)
}
if hasEnvironment {
if err := hubStore.DeleteAccountEnvironment(c.Context(), accountID); err != nil {
return hubError(c, err)
}
}
if err := phaseAStore.DeleteAccount(c.Context(), accountID, credentials); err != nil {
return phaseAError(c, err)
}
return c.SendStatus(fiber.StatusNoContent)
})
app.Delete("/api/creator/competitors/:id", func(c fiber.Ctx) error {
if err := creatorStore.DeleteCompetitor(c.Context(), c.Params("id")); err != nil {
return creatorError(c, err)
}
return c.SendStatus(fiber.StatusNoContent)
})
}
type environmentContextStore interface {
GetEnvironmentContextForAccount(context.Context, string) (hub.EnvironmentContext, error)
}
func accountEnvironment(ctx context.Context, store environmentContextStore, accountID string) (hub.EnvironmentContext, bool, error) {
if store == nil {
return hub.EnvironmentContext{}, false, creator.ErrUnavailable
}
environment, err := store.GetEnvironmentContextForAccount(ctx, accountID)
if errors.Is(err, hub.ErrNotFound) {
return hub.EnvironmentContext{}, false, nil
}
if err != nil {
return hub.EnvironmentContext{}, false, err
}
return environment, true, nil
}
func purgeAccountProfile(ctx context.Context, gateway hub.Gateway, environment hub.EnvironmentContext) error {
payload := gatewayCleanupGenerationPayload(environment)
payload["purge_profile"] = true
status, body, err := gatewayCall(ctx, gateway, http.MethodDelete, "/v1/browsers/"+environment.Alias, payload, 30*time.Second)
if err != nil {
return gatewayUnreachable(err)
}
if status == http.StatusNoContent || status == http.StatusNotFound {
return nil
}
return gatewayRejected(status, body)
}
// RegisterAccountDeletion exposes destructive account routes to the grouped API package.
func RegisterAccountDeletion(app *fiber.App, accountStore *accountdomain.Store, environmentStore *hub.Store, creatorStore *creator.Store, credentials accountdomain.CredentialBridge) {
registerAccountDeletion(app, accountStore, environmentStore, creatorStore, credentials)
}