Refactor admin action naming and move user assertions
Renamed the admin actions to have a more uniform approach with "Action" suffixed. This makes the action function's purpose clear in the codebase. Also, moved the `assertUserIsNotCurrentSuperAdmin` method to a more suitable place in the code, arranging it in a private scope. This helps in maintaining clean code architecture and enhances readibility.
This commit is contained in:
@@ -42,10 +42,13 @@ function getClassName() {
|
||||
const theme = themeCookie ?? appConfig.theme;
|
||||
const dark = theme === 'dark';
|
||||
|
||||
return cn('min-h-screen bg-background antialiased', {
|
||||
dark,
|
||||
[sans.className]: true,
|
||||
});
|
||||
return cn(
|
||||
'min-h-screen bg-background antialiased',
|
||||
{
|
||||
dark,
|
||||
},
|
||||
sans.className,
|
||||
);
|
||||
}
|
||||
|
||||
export const metadata = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getOrder, getVariant } from '@lemonsqueezy/lemonsqueezy.js';
|
||||
import { createHmac, timingSafeEqual } from 'crypto';
|
||||
import { createHmac, timingSafeEqual } from 'node:crypto';
|
||||
|
||||
import {
|
||||
BillingConfig,
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
} from '@kit/ui/form';
|
||||
import { Input } from '@kit/ui/input';
|
||||
|
||||
import { banUser } from '../lib/server/admin-server-actions';
|
||||
import { banUserAction } from '../lib/server/admin-server-actions';
|
||||
import { BanUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminBanUserDialog(
|
||||
@@ -58,7 +58,7 @@ export function AdminBanUserDialog(
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return banUser(data);
|
||||
return banUserAction(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
} from '@kit/ui/form';
|
||||
import { Input } from '@kit/ui/input';
|
||||
|
||||
import { deleteAccount } from '../lib/server/admin-server-actions';
|
||||
import { deleteAccountAction } from '../lib/server/admin-server-actions';
|
||||
import { DeleteAccountSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminDeleteAccountDialog(
|
||||
@@ -59,7 +59,7 @@ export function AdminDeleteAccountDialog(
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return deleteAccount(data);
|
||||
return deleteAccountAction(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
} from '@kit/ui/form';
|
||||
import { Input } from '@kit/ui/input';
|
||||
|
||||
import { deleteUser } from '../lib/server/admin-server-actions';
|
||||
import { deleteUserAction } from '../lib/server/admin-server-actions';
|
||||
import { DeleteUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminDeleteUserDialog(
|
||||
@@ -60,7 +60,7 @@ export function AdminDeleteUserDialog(
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return deleteUser(data);
|
||||
return deleteUserAction(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
import { Input } from '@kit/ui/input';
|
||||
import { LoadingOverlay } from '@kit/ui/loading-overlay';
|
||||
|
||||
import { impersonateUser } from '../lib/server/admin-server-actions';
|
||||
import { impersonateUserAction } from '../lib/server/admin-server-actions';
|
||||
import { ImpersonateUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminImpersonateUserDialog(
|
||||
@@ -81,7 +81,7 @@ export function AdminImpersonateUserDialog(
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit(async (data) => {
|
||||
const tokens = await impersonateUser(data);
|
||||
const tokens = await impersonateUserAction(data);
|
||||
|
||||
setTokens(tokens);
|
||||
})}
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
} from '@kit/ui/form';
|
||||
import { Input } from '@kit/ui/input';
|
||||
|
||||
import { reactivateUser } from '../lib/server/admin-server-actions';
|
||||
import { reactivateUserAction } from '../lib/server/admin-server-actions';
|
||||
import { ReactivateUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminReactivateUserDialog(
|
||||
@@ -58,7 +58,7 @@ export function AdminReactivateUserDialog(
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return reactivateUser(data);
|
||||
return reactivateUserAction(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
|
||||
@@ -18,10 +18,10 @@ import { AdminAccountsService } from './services/admin-accounts.service';
|
||||
import { AdminAuthUserService } from './services/admin-auth-user.service';
|
||||
|
||||
/**
|
||||
* @name banUser
|
||||
* @name banUserAction
|
||||
* @description Ban a user from the system.
|
||||
*/
|
||||
export const banUser = enhanceAdminAction(
|
||||
export const banUserAction = enhanceAdminAction(
|
||||
enhanceAction(
|
||||
async ({ userId }) => {
|
||||
const service = getAdminAuthService();
|
||||
@@ -41,10 +41,10 @@ export const banUser = enhanceAdminAction(
|
||||
);
|
||||
|
||||
/**
|
||||
* @name reactivateUser
|
||||
* @name reactivateUserAction
|
||||
* @description Reactivate a user in the system.
|
||||
*/
|
||||
export const reactivateUser = enhanceAdminAction(
|
||||
export const reactivateUserAction = enhanceAdminAction(
|
||||
enhanceAction(
|
||||
async ({ userId }) => {
|
||||
const service = getAdminAuthService();
|
||||
@@ -64,10 +64,10 @@ export const reactivateUser = enhanceAdminAction(
|
||||
);
|
||||
|
||||
/**
|
||||
* @name impersonateUser
|
||||
* @name impersonateUserAction
|
||||
* @description Impersonate a user in the system.
|
||||
*/
|
||||
export const impersonateUser = enhanceAdminAction(
|
||||
export const impersonateUserAction = enhanceAdminAction(
|
||||
enhanceAction(
|
||||
async ({ userId }) => {
|
||||
const service = getAdminAuthService();
|
||||
@@ -81,10 +81,10 @@ export const impersonateUser = enhanceAdminAction(
|
||||
);
|
||||
|
||||
/**
|
||||
* @name deleteUser
|
||||
* @name deleteUserAction
|
||||
* @description Delete a user from the system.
|
||||
*/
|
||||
export const deleteUser = enhanceAdminAction(
|
||||
export const deleteUserAction = enhanceAdminAction(
|
||||
enhanceAction(
|
||||
async ({ userId }) => {
|
||||
const service = getAdminAuthService();
|
||||
@@ -102,10 +102,10 @@ export const deleteUser = enhanceAdminAction(
|
||||
);
|
||||
|
||||
/**
|
||||
* @name deleteAccount
|
||||
* @name deleteAccountAction
|
||||
* @description Delete an account from the system.
|
||||
*/
|
||||
export const deleteAccount = enhanceAdminAction(
|
||||
export const deleteAccountAction = enhanceAdminAction(
|
||||
enhanceAction(
|
||||
async ({ accountId }) => {
|
||||
const service = getAdminAccountsService();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'server-only';
|
||||
|
||||
import { SupabaseClient } from '@supabase/supabase-js';
|
||||
|
||||
import 'server-only';
|
||||
|
||||
import { Database } from '@kit/supabase/database';
|
||||
|
||||
/**
|
||||
@@ -15,21 +15,10 @@ export class AdminAuthUserService {
|
||||
private readonly adminClient: SupabaseClient<Database>,
|
||||
) {}
|
||||
|
||||
async assertUserIsNotCurrentSuperAdmin(targetUserId: string) {
|
||||
const { data: user } = await this.client.auth.getUser();
|
||||
const currentUserId = user.user?.id;
|
||||
|
||||
if (!currentUserId) {
|
||||
throw new Error(`Error fetching user`);
|
||||
}
|
||||
|
||||
if (currentUserId === targetUserId) {
|
||||
throw new Error(
|
||||
`You cannot perform a destructive action on your own account as a Super Admin`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user by deleting the user record and auth record.
|
||||
* @param userId
|
||||
*/
|
||||
async deleteUser(userId: string) {
|
||||
await this.assertUserIsNotCurrentSuperAdmin(userId);
|
||||
|
||||
@@ -41,19 +30,33 @@ export class AdminAuthUserService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban a user by setting the ban duration to `876600h` (100 years).
|
||||
* @param userId
|
||||
*/
|
||||
async banUser(userId: string) {
|
||||
await this.assertUserIsNotCurrentSuperAdmin(userId);
|
||||
|
||||
return this.setBanDuration(userId, `876600h`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reactivate a user by setting the ban duration to `none`.
|
||||
* @param userId
|
||||
*/
|
||||
async reactivateUser(userId: string) {
|
||||
await this.assertUserIsNotCurrentSuperAdmin(userId);
|
||||
|
||||
return this.setBanDuration(userId, `none`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Impersonate a user by generating a magic link and returning the access and refresh tokens.
|
||||
* @param userId
|
||||
*/
|
||||
async impersonateUser(userId: string) {
|
||||
await this.assertUserIsNotCurrentSuperAdmin(userId);
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
error,
|
||||
@@ -110,6 +113,25 @@ export class AdminAuthUserService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the target user is not the current user.
|
||||
* @param targetUserId
|
||||
*/
|
||||
private async assertUserIsNotCurrentSuperAdmin(targetUserId: string) {
|
||||
const { data: user } = await this.client.auth.getUser();
|
||||
const currentUserId = user.user?.id;
|
||||
|
||||
if (!currentUserId) {
|
||||
throw new Error(`Error fetching user`);
|
||||
}
|
||||
|
||||
if (currentUserId === targetUserId) {
|
||||
throw new Error(
|
||||
`You cannot perform a destructive action on your own account as a Super Admin`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async setBanDuration(userId: string, banDuration: string) {
|
||||
await this.adminClient.auth.admin.updateUserById(userId, {
|
||||
ban_duration: banDuration,
|
||||
|
||||
Reference in New Issue
Block a user