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:
giancarlo
2024-04-09 19:08:40 +08:00
parent d275d993bd
commit 37f1db6b2b
9 changed files with 67 additions and 42 deletions

View File

@@ -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 = {

View File

@@ -1,5 +1,5 @@
import { getOrder, getVariant } from '@lemonsqueezy/lemonsqueezy.js';
import { createHmac, timingSafeEqual } from 'crypto';
import { createHmac, timingSafeEqual } from 'node:crypto';
import {
BillingConfig,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
})}

View File

@@ -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

View File

@@ -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();

View File

@@ -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,