@bettercone/ui
Components

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 migrate

This adds the following fields to your user table:

  • role - User role (admin, moderator, user)
  • banned - Ban status
  • banReason - Reason for ban
  • banExpires - 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

PropTypeDescription
authClientAnyAuthClientBetter Auth client instance
onSuccess() => voidCalled after successful actions
onError(error: Error) => voidCalled on errors
classNamestringCustom CSS classes
localizationPartial<UserManagementLocalization>Text overrides

BanUserDialog Props

PropTypeDescription
openbooleanDialog open state
onOpenChange(open: boolean) => voidOpen state change handler
user{ id, name?, email }User to ban
onSuccess() => voidCalled after successful ban
onError(error: Error) => voidCalled on errors
classNamestringCustom CSS classes
localizationPartial<BanUserDialogLocalization>Text overrides

ImpersonateUserDialog Props

PropTypeDescription
openbooleanDialog open state
onOpenChange(open: boolean) => voidOpen state change handler
user{ id, name?, email, image? }User to impersonate
onSuccess() => voidCalled before page reload
onError(error: Error) => voidCalled on errors
classNamestringCustom CSS classes
localizationPartial<ImpersonateUserDialogLocalization>Text overrides