'use server'; import { revalidatePath } from 'next/cache'; import { redirect } from 'next/navigation'; import { enhanceAction } from '@kit/next/actions'; import { getLogger } from '@kit/shared/logger'; import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { BanUserSchema, DeleteAccountSchema, DeleteUserSchema, ImpersonateUserSchema, ReactivateUserSchema, UpdateAccountRoleSchema, } from './schema/admin-actions.schema'; import { CreateCompanySchema } from './schema/create-company.schema'; import { CreateUserSchema } from './schema/create-user.schema'; import { ResetPasswordSchema } from './schema/reset-password.schema'; import { createAdminAccountsService } from './services/admin-accounts.service'; import { createAdminAuthUserService } from './services/admin-auth-user.service'; import { createCreateCompanyAccountService } from './services/admin-create-company-account.service'; import { adminAction } from './utils/admin-action'; import { getAdminSdk } from './utils/medusa-sdk'; /** * @name banUserAction * @description Ban a user from the system. */ export const banUserAction = adminAction( enhanceAction( async ({ userId }) => { const service = getAdminAuthService(); const logger = await getLogger(); logger.info({ userId }, `Super Admin is banning user...`); await service.banUser(userId); logger.info({ userId }, `Super Admin has successfully banned user`); revalidateAdmin(); return { success: true, }; }, { schema: BanUserSchema, }, ), ); /** * @name reactivateUserAction * @description Reactivate a user in the system. */ export const reactivateUserAction = adminAction( enhanceAction( async ({ userId }) => { const service = getAdminAuthService(); const logger = await getLogger(); logger.info({ userId }, `Super Admin is reactivating user...`); await service.reactivateUser(userId); logger.info({ userId }, `Super Admin has successfully reactivated user`); revalidateAdmin(); return { success: true, }; }, { schema: ReactivateUserSchema, }, ), ); /** * @name impersonateUserAction * @description Impersonate a user in the system. */ export const impersonateUserAction = adminAction( enhanceAction( async ({ userId }) => { const service = getAdminAuthService(); const logger = await getLogger(); logger.info({ userId }, `Super Admin is impersonating user...`); return await service.impersonateUser(userId); }, { schema: ImpersonateUserSchema, }, ), ); /** * @name deleteUserAction * @description Delete a user from the system. */ export const deleteUserAction = adminAction( enhanceAction( async ({ userId }) => { const service = getAdminAuthService(); const logger = await getLogger(); logger.info({ userId }, `Super Admin is deleting user...`); await service.deleteUser(userId); logger.info({ userId }, `Super Admin has successfully deleted user`); revalidateAdmin(); return redirect('/admin/accounts'); }, { schema: DeleteUserSchema, }, ), ); /** * @name deleteAccountAction * @description Delete an account from the system. */ export const deleteAccountAction = adminAction( enhanceAction( async ({ accountId }) => { const service = getAdminAccountsService(); const logger = await getLogger(); logger.info({ accountId }, `Super Admin is deleting account...`); const { name: customerGroupName } = await service.getAccount(accountId); try { await service.deleteAccount(accountId); } catch (e) { logger.error({ accountId }, `Error deleting company account`); throw e; } const medusa = getAdminSdk(); const { customer_groups } = await medusa.admin.customerGroup.list(); const customerGroup = customer_groups.find( ({ name }) => name === customerGroupName, ); if (customerGroup) { try { await medusa.admin.customerGroup.delete(customerGroup.id); } catch (e) { logger.error( { accountId }, `Error deleting Medusa customer group for company ${customerGroupName}`, ); throw e; } } logger.info( { accountId }, `Super Admin has successfully deleted account`, ); revalidateAdmin(); return redirect('/admin/accounts'); }, { schema: DeleteAccountSchema, }, ), ); /** * @name createUserAction * @description Create a new user in the system. */ export const createUserAction = adminAction( enhanceAction( async ({ email, password, emailConfirm, personalCode }) => { const adminClient = getSupabaseServerAdminClient(); const logger = await getLogger(); logger.info({ email }, `Super Admin is creating a new user...`); const { data, error } = await adminClient.auth.admin.createUser({ email, password, email_confirm: emailConfirm, }); if (error) { logger.error({ error }, `Error creating user`); throw new Error(`Error creating user: ${error.message}`); } logger.info( { userId: data.user.id }, `Super Admin has successfully created a new user`, ); const { error: accountError } = await adminClient .schema('medreport') .from('accounts') .update({ personal_code: personalCode }) .eq('id', data.user.id); if (accountError) { logger.error( { accountError }, 'Error inserting personal code to accounts', ); throw new Error(`Error saving personal code: ${accountError.message}`); } revalidateAdmin(); return { success: true, user: data.user, }; }, { schema: CreateUserSchema, }, ), ); /** * @name resetPasswordAction * @description Reset a user's password by sending a password reset email. */ export const resetPasswordAction = adminAction( enhanceAction( async ({ userId }) => { const service = getAdminAuthService(); const logger = await getLogger(); logger.info({ userId }, `Super Admin is resetting user password...`); const result = await service.resetPassword(userId); logger.info( { userId }, `Super Admin has successfully sent password reset email`, ); revalidateAdmin(); return result; }, { schema: ResetPasswordSchema, }, ), ); export const createCompanyAccountAction = enhanceAction( async ({ name, ownerPersonalCode }, user) => { const logger = await getLogger(); const client = getSupabaseServerClient(); const service = createCreateCompanyAccountService(client); const ctx = { name: 'team-accounts.create', userId: user.id, accountName: name, }; logger.info(ctx, `Creating company account...`); const { data, error } = await service.createNewOrganizationAccount({ name, ownerPersonalCode, }); if (error) { logger.error({ ...ctx, error }, `Failed to create company account`); return { error: true, }; } logger.info(ctx, `Company account created`); logger.info(ctx, `Creating Medusa customer group`); const medusa = getAdminSdk(); const { customer_groups: existingCustomerGroups } = await medusa.admin.customerGroup.list(); const isExisting = existingCustomerGroups.find( (group) => group.name === name, ); if (isExisting) { logger.info(ctx, `Customer group already exists`); } else { logger.info(ctx, `Creating Medusa customer group`); const { data: account } = await client .schema('medreport') .from('accounts') .select('medusa_account_id') .eq('personal_code', ownerPersonalCode) .single() .throwOnError(); const medusaAccountId = account.medusa_account_id; if (!medusaAccountId) { logger.error(ctx, `User has no Medusa account ID`); } else { const { customer_group: { id: customerGroupId }, } = await medusa.admin.customerGroup.create({ name }); const { customers } = await medusa.admin.customer.list({ id: medusaAccountId, }); if (customers.length !== 1) { logger.error(ctx, `Customer not found`); } else { const customerId = customers[0]!.id; await medusa.admin.customer.batchCustomerGroups(customerId, { add: [customerGroupId], }); } } } redirect(`/admin/accounts/${data.id}`); }, { schema: CreateCompanySchema, }, ); /** * @name updateRoleAction * @description Update application role for user */ export const updateRoleAction = adminAction( enhanceAction( async ({ accountId, role }) => { const service = getAdminAccountsService(); const logger = await getLogger(); logger.info({ accountId }, `Super Admin is updating account role...`); await service.updateRole(accountId, role); logger.info({ accountId }, `Successfully changed role`); revalidateAdmin(); return { success: true }; }, { schema: UpdateAccountRoleSchema, }, ), ); function revalidateAdmin() { revalidatePath('/admin', 'layout'); } function getAdminAuthService() { const client = getSupabaseServerClient(); const adminClient = getSupabaseServerAdminClient(); return createAdminAuthUserService(client, adminClient); } function getAdminAccountsService() { const adminClient = getSupabaseServerAdminClient(); return createAdminAccountsService(adminClient); }