Admin Components
User management and moderation tools for administrators
Admin Components
3 production-ready components for building admin dashboards with user management capabilities.
Components
UserManagementTable
Complete admin table for managing users with pagination, search, and bulk actions.
import { UserManagementTable } from '@bettercone/ui';
<UserManagementTable
authClient={authClient}
onSuccess={() => console.log('Action completed')}
onError={(error) => console.error(error)}
/>Features: User list, pagination, search by email/name, ban/unban, delete, impersonate
BanUserDialog
Dialog for banning users with customizable reason and duration.
import { BanUserDialog } from '@bettercone/ui';
<BanUserDialog
open={open}
onOpenChange={setOpen}
user={selectedUser}
onSuccess={() => console.log('User banned')}
/>Features: Ban reason input, duration selector (permanent or custom days), user preview
ImpersonateUserDialog
Dialog for safely impersonating users for support purposes.
import { ImpersonateUserDialog } from '@bettercone/ui';
<ImpersonateUserDialog
open={open}
onOpenChange={setOpen}
user={selectedUser}
onSuccess={() => console.log('Impersonation started')}
/>Features: User preview, safety warning, automatic page reload after impersonation
Quick Start
Setup Admin Plugin
First, add the admin plugin to your Better Auth configuration:
// lib/auth.ts
import { betterAuth } from "better-auth";
import { admin } from "better-auth/plugins";
export const auth = betterAuth({
// ... other config
plugins: [
admin({
// Only these users can access admin features
adminUserIds: ["admin_user_id"],
// Or use role-based access
// accessControl: {
// requireAdmin: true
// }
})
]
});Database Migration
Run the migration to add admin fields:
npx better-auth migrateThis adds the following fields to your user table:
role- User role (admin, moderator, user)banned- Ban statusbanReason- Reason for banbanExpires- Ban expiration date
Admin Dashboard Example
"use client";
import { UserManagementTable } from '@bettercone/ui';
import { authClient } from '@/lib/auth-client';
export default function AdminPage() {
return (
<div className="container mx-auto py-8">
<div className="mb-8">
<h1 className="text-3xl font-bold">User Management</h1>
<p className="text-muted-foreground">
Manage users, ban accounts, and provide support
</p>
</div>
<UserManagementTable
authClient={authClient}
onSuccess={() => {
// Refresh data or show notification
}}
onError={(error) => {
console.error('Admin action failed:', error);
}}
/>
</div>
);
}With Dialogs
"use client";
import { useState } from 'react';
import {
UserManagementTable,
BanUserDialog,
ImpersonateUserDialog
} from '@bettercone/ui';
import { authClient } from '@/lib/auth-client';
export default function AdminPage() {
const [banDialogOpen, setBanDialogOpen] = useState(false);
const [impersonateDialogOpen, setImpersonateDialogOpen] = useState(false);
const [selectedUser, setSelectedUser] = useState(null);
return (
<div className="container mx-auto py-8">
<UserManagementTable authClient={authClient} />
<BanUserDialog
open={banDialogOpen}
onOpenChange={setBanDialogOpen}
user={selectedUser}
onSuccess={() => {
setBanDialogOpen(false);
// Refresh table
}}
/>
<ImpersonateUserDialog
open={impersonateDialogOpen}
onOpenChange={setImpersonateDialogOpen}
user={selectedUser}
onSuccess={() => {
// Page will reload automatically
}}
/>
</div>
);
}Features
UserManagementTable
- Pagination - Offset-based pagination with page controls
- Search - Search by email or name with contains operator
- Sort - Sort by creation date (descending)
- Actions - Ban, unban, delete, impersonate per user
- Status Badges - Active/banned, verified/unverified indicators
- Role Display - Shows user roles (admin, moderator, user)
- Responsive - Works on all screen sizes
- Localization - Full i18n support
BanUserDialog
- Reason Input - Text area for ban reason
- Duration Options - Permanent, 1/3/7/30 days, or custom
- Custom Duration - Input field for custom day count
- User Preview - Shows user info before banning
- Validation - Ensures valid duration input
- Localization - Customizable text labels
ImpersonateUserDialog
- Safety Warning - Clear warning about impersonation risks
- User Preview - Shows user avatar and details
- Auto Reload - Reloads page after impersonation starts
- Error Handling - Proper error feedback
- Localization - Customizable text labels
Security
Access Control
Always verify admin permissions on the server:
// app/api/admin/route.ts
import { auth } from '@/lib/auth';
export async function GET(req: Request) {
const session = await auth.api.getSession({
headers: req.headers
});
if (!session?.user) {
return new Response('Unauthorized', { status: 401 });
}
// Check if user is admin
if (session.user.role !== 'admin') {
return new Response('Forbidden', { status: 403 });
}
// Admin action logic...
}Audit Logging
Log all admin actions for compliance:
// After admin action
await db.adminLog.create({
data: {
adminId: session.user.id,
action: 'BAN_USER',
targetUserId: userId,
reason: banReason,
timestamp: new Date()
}
});Customization
Localization
All components support full localization:
<UserManagementTable
authClient={authClient}
localization={{
title: "Gerenciar Usuários",
searchPlaceholder: "Buscar por email ou nome...",
banUser: "Banir Usuário",
// ... 50+ customizable strings
}}
/>Styling
Apply custom classes:
<UserManagementTable
authClient={authClient}
className="border-2 border-primary"
/>API Reference
UserManagementTable Props
| Prop | Type | Description |
|---|---|---|
authClient | AnyAuthClient | Better Auth client instance |
onSuccess | () => void | Called after successful actions |
onError | (error: Error) => void | Called on errors |
className | string | Custom CSS classes |
localization | Partial<UserManagementLocalization> | Text overrides |
BanUserDialog Props
| Prop | Type | Description |
|---|---|---|
open | boolean | Dialog open state |
onOpenChange | (open: boolean) => void | Open state change handler |
user | { id, name?, email } | User to ban |
onSuccess | () => void | Called after successful ban |
onError | (error: Error) => void | Called on errors |
className | string | Custom CSS classes |
localization | Partial<BanUserDialogLocalization> | Text overrides |
ImpersonateUserDialog Props
| Prop | Type | Description |
|---|---|---|
open | boolean | Dialog open state |
onOpenChange | (open: boolean) => void | Open state change handler |
user | { id, name?, email, image? } | User to impersonate |
onSuccess | () => void | Called before page reload |
onError | (error: Error) => void | Called on errors |
className | string | Custom CSS classes |
localization | Partial<ImpersonateUserDialogLocalization> | Text overrides |
Related Components
- User Components - User profile and avatar components
- Security Components - Session and password management
- Developer Components - API key management