package internal import ( "context" "github.com/tech/sendico/pkg/auth" "github.com/tech/sendico/pkg/db/account" "github.com/tech/sendico/pkg/db/organization" "github.com/tech/sendico/pkg/db/policy" "github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/mutil/mzap" "go.mongodb.org/mongo-driver/bson/primitive" "go.uber.org/zap" ) // AccountManager provides helper methods for account management operations type AccountManager struct { logger mlogger.Logger accountDB account.DB orgDB organization.DB policyDB policy.DB authManager auth.Manager } // NewAccountManager creates a new AccountManager instance func NewAccountManager( logger mlogger.Logger, accountDB account.DB, orgDB organization.DB, policyDB policy.DB, authManager auth.Manager, ) *AccountManager { var namedLogger mlogger.Logger if logger != nil { namedLogger = logger.Named("account_manager") } return &AccountManager{ logger: namedLogger, accountDB: accountDB, orgDB: orgDB, policyDB: policyDB, authManager: authManager, } } // DeleteOrganization deletes an organization and all its associated data // The caller is responsible for wrapping this in a transaction func (m *AccountManager) DeleteOrganization(ctx context.Context, orgRef primitive.ObjectID) error { m.logger.Debug("Deleting organization", mzap.ObjRef("org_ref", orgRef)) // Delete organization roles if err := m.deleteOrganizationRoles(ctx, orgRef); err != nil { m.logger.Warn("Failed to delete organization roles", zap.Error(err), mzap.ObjRef("org_ref", orgRef)) return err } // Delete organization policies if err := m.deleteOrganizationPolicies(ctx, orgRef); err != nil { m.logger.Warn("Failed to delete organization policies", zap.Error(err), mzap.ObjRef("org_ref", orgRef)) return err } // Finally delete the organization itself if err := m.orgDB.Delete(ctx, primitive.NilObjectID, orgRef); err != nil { m.logger.Warn("Failed to delete organization", zap.Error(err), mzap.ObjRef("org_ref", orgRef)) return err } m.logger.Info("Successfully deleted organization", mzap.ObjRef("org_ref", orgRef)) return nil } // DeleteAccount deletes an account and all its associated data // The caller is responsible for wrapping this in a transaction func (m *AccountManager) DeleteAccount(ctx context.Context, accountRef primitive.ObjectID) error { m.logger.Debug("Deleting account", mzap.ObjRef("account_ref", accountRef)) // Delete the account if err := m.accountDB.Delete(ctx, accountRef); err != nil { m.logger.Warn("Failed to delete account", zap.Error(err), mzap.ObjRef("account_ref", accountRef)) return err } m.logger.Info("Successfully deleted account", mzap.ObjRef("account_ref", accountRef)) return nil } // DeleteAll deletes all data for a given account and organization // The caller is responsible for wrapping this in a transaction func (m *AccountManager) DeleteAll(ctx context.Context, accountRef, organizationRef primitive.ObjectID) error { m.logger.Debug("Deleting all data", mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef)) // Delete organization first (which will cascade delete all related data) if err := m.DeleteOrganization(ctx, organizationRef); err != nil { m.logger.Warn("Failed to delete organization", zap.Error(err), mzap.ObjRef("organization_ref", organizationRef)) return err } // Delete account if err := m.DeleteAccount(ctx, accountRef); err != nil { m.logger.Warn("Failed to delete account", zap.Error(err), mzap.ObjRef("account_ref", accountRef)) return err } m.logger.Info("Successfully deleted all data", mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef)) return nil } // deleteOrganizationRoles deletes all roles for an organization func (m *AccountManager) deleteOrganizationRoles(ctx context.Context, orgRef primitive.ObjectID) error { // Get all roles for the organization roles, err := m.authManager.Role().List(ctx, orgRef) if err != nil { m.logger.Warn("Failed to list organization roles", zap.Error(err), mzap.ObjRef("org_ref", orgRef)) return err } // Delete each role for _, role := range roles { if err := m.authManager.Role().Delete(ctx, role.ID); err != nil { m.logger.Warn("Failed to delete role", zap.Error(err), mzap.ObjRef("role_ref", role.ID), mzap.ObjRef("org_ref", orgRef)) return err } } m.logger.Info("Successfully deleted organization roles", zap.Int("count", len(roles)), mzap.ObjRef("org_ref", orgRef)) return nil } // deleteOrganizationPolicies deletes all policies for an organization func (m *AccountManager) deleteOrganizationPolicies(_ context.Context, _ primitive.ObjectID) error { // Note: PolicyDB is used for both roles and policies, but the interface is unclear // This would need to be implemented differently or skipped for now m.logger.Warn("Policy deletion not implemented - interface unclear") return nil }