# Admin Overview

> Overview of the admin panel features including user management, organization oversight, and platform analytics.

*Canonical: https://makerkit.dev/docs/nextjs-drizzle/admin/overview*

---

The Admin Panel provides system administrators with tools to manage users, organizations, and monitor platform activity. Access it at `/admin` when signed in with an admin account.

This documentation covers the admin system built on [Better Auth's admin plugin](../authentication/overview) with MakerKit's RBAC layer.

## Getting Started

### Creating Your First Admin

After running `pnpm seed`, use these test credentials:

- **Email**: `admin1@makerkit.dev`
- **Password**: `testingpassword`

To promote an existing user to admin:

1. Run Drizzle Studio: `pnpm --filter "@kit/database" run drizzle:studio`
2. Open the `users` table
3. Set the `role` column to `admin` for your user
4. Sign out and back in to refresh the session

Alternatively, use the Better Auth CLI or API to update roles programmatically.

### Admin Role Verification

When a user accesses `/admin/*` routes, the system verifies admin status through multiple layers:

1. **Middleware** (`proxy.ts`) checks if the user has an admin role
2. **Server Components** use `requireAdmin()` to validate and redirect if unauthorized
3. **Server Actions** use `adminActionClient` which verifies the user's role before executing

## Dashboard Metrics

The admin dashboard at `/admin` displays four key metrics:

| Metric | Description |
|--------|-------------|
| **Total Users** | All registered user accounts |
| **Active Sessions** | Sessions created in the last 24 hours |
| **Banned Users** | Accounts with restricted access |
| **New This Week** | Sign-ups from the past 7 days |

These metrics are loaded server-side using React's `cache()` function to prevent duplicate queries within the same request.

## Architecture

The admin system is organized across several packages:

```
packages/admin/                     # Admin UI components and logic
├── src/
│   ├── dashboard/                  # Dashboard page and metrics
│   │   ├── lib/
│   │   │   ├── actions/            # Server actions
│   │   │   ├── loaders/            # Data loaders
│   │   │   ├── schemas/            # Zod schemas
│   │   │   └── services/           # Business logic
│   │   └── page.tsx                # Dashboard component
│   ├── users/                      # User management
│   ├── organizations/              # Organization management
│   └── hooks/                      # Client-side hooks

packages/rbac/                      # Role-based access control
├── src/
│   ├── admin/                      # Admin RBAC utilities
│   │   ├── factory.ts              # Config factory
│   │   ├── defaults.ts             # Default resources/actions
│   │   └── client.ts               # Permission checking
│   └── admin-rbac.config.ts        # Your customization file

packages/auth/                      # Authentication utilities
├── src/utils/
│   ├── require-admin.ts            # Server-side admin check
│   └── is-admin-role.ts            # Role validation

packages/action-middleware/         # Server action utilities
├── src/
│   ├── require-admin-action-middleware.ts      # Admin action client
│   └── require-admin-permission-middleware.ts  # Permission middleware
```

## Core Features

### User Management

The Users section (`/admin/users`) provides full control over user accounts:

- **Search**: Find users by name or email
- **Filter**: By role (user/admin) and status (active/banned)
- **Sort**: By name, email, creation date, role, or status
- **Paginated results**: 25 users per page

Available actions per user:

| Action | Description |
|--------|-------------|
| View Details | Full user profile with sessions and subscriptions |
| Change Role | Promote to admin or demote to user |
| Impersonate | Sign in as the user for debugging (restrictions apply) |
| Ban/Unban | Restrict or restore account access |
| Remove | Permanently delete the account |
| View Sessions | See all active sessions |
| Revoke Sessions | End specific or all sessions |

{% img src="/images/docs/admin-users-table.webp" width="2844" height="1938" alt="Admin Users Table" /%}

See [User Management](./user-management) for detailed documentation.

### Organization Management

The Organizations section (`/admin/organizations`) lets you oversee all teams:

- **Search**: Find organizations by name
- **View Details**: See organization info, members, and subscriptions
- **Member Access**: Click through to any member's user details

{% img src="/images/docs/admin-organizations-table.webp" width="2844" height="1938" alt="Admin Organizations Table" /%}

See [Organization Management](./organization-management) for detailed documentation.

### Role-Based Access Control

Admin permissions are configured via RBAC in `packages/rbac/src/admin-rbac.config.ts`. The default configuration provides a single `admin` role with full permissions. You can add custom roles with restricted access:

```typescript
import { defineAdminRBACConfig } from './admin/factory';

export default defineAdminRBACConfig({
  // Add custom roles with limited permissions
  roles: {
    support: 50,    // Can help users but not delete
    moderator: 30,  // Can ban but limited access
  },
  permissions: {
    support: {
      user: ['list', 'get', 'ban'],
      session: ['list', 'revoke'],
      organizations: ['list', 'view'],
      dashboard: ['view'],
    },
  },
});
```

See [RBAC Permissions](./rbac-permissions) for detailed documentation on customizing admin roles.

## Navigation

The admin sidebar includes:

- **Dashboard** (`/admin`) - Overview and statistics
- **Users** (`/admin/users`) - User management
- **Organizations** (`/admin/organizations`) - Organization oversight

Click "Back to Dashboard" in the sidebar header to return to your regular account.

## Security Layers

The admin panel includes multiple security layers:

### 1. Route Protection (Middleware)

The middleware in `apps/web/proxy.ts` blocks non-admin access to `/admin/*` routes:

```typescript
// Simplified from apps/web/proxy.ts
if (pathname.startsWith('/admin')) {
  const isAdmin = await isUserAdmin();
  if (!isAdmin) {
    return NextResponse.redirect(new URL('/auth/sign-in', request.url));
  }
}
```

### 2. Server-Side Checks

`requireAdmin()` verifies admin status in server components and redirects to a 403 page if unauthorized:

```typescript
import { requireAdmin } from '@kit/auth/require-admin';

export default async function AdminPage() {
  await requireAdmin(); // Redirects if not admin
  // ... render admin content
}
```

### 3. Action Protection

`adminActionClient` protects all server actions:

```typescript
import { adminActionClient } from '@kit/action-middleware';

export const myAdminAction = adminActionClient
  .inputSchema(schema)
  .action(async ({ ctx }) => {
    // ctx.user is guaranteed to be admin
  });
```

### 4. Permission Checks

`withAdminPermission()` enforces granular RBAC permissions:

```typescript
import { adminActionClient, withAdminPermission } from '@kit/action-middleware';

export const banUserAction = adminActionClient
  .use(withAdminPermission({ user: ['ban'] }))
  .inputSchema(schema)
  .action(async ({ ctx }) => {
    // Only admins with 'user:ban' permission reach here
  });
```

### 5. Impersonation Safeguards

The impersonation feature includes restrictions:

- Cannot impersonate admin users
- Cannot impersonate banned accounts
- A banner appears during impersonation showing the original admin

## Key Imports

| Import | Package | Purpose |
|--------|---------|---------|
| `requireAdmin` | `@kit/auth/require-admin` | Server-side admin check with redirect |
| `isUserAdmin` | `@kit/auth/require-admin` | Server-side check without redirect |
| `isAdminRole` | `@kit/auth/is-admin-role` | Client-safe role validation |
| `adminActionClient` | `@kit/action-middleware` | Protected action client |
| `withAdminPermission` | `@kit/action-middleware` | Permission middleware |
| `useAdminPermissions` | `@kit/admin/hooks/use-admin-permissions` | Client permission hook |

For implementation details on adding custom features, see [Extending Admin](./extending-admin).

{% faq
   title="Frequently Asked Questions"
   items=[
     {"question": "How do I create my first admin user?", "answer": "Run pnpm seed to create test admin credentials, or manually set the role column to 'admin' in the users table using Drizzle Studio. Sign out and back in to refresh the session after changing roles."},
     {"question": "What's the difference between requireAdmin and adminActionClient?", "answer": "requireAdmin() is for server components and data loaders - it redirects unauthorized users to a 403 page. adminActionClient is for server actions - it returns an error response instead of redirecting, which is appropriate for API-style calls."},
     {"question": "Can I have multiple admin roles with different permissions?", "answer": "Yes. Configure custom roles in packages/rbac/src/admin-rbac.config.ts using defineAdminRBACConfig(). Each role gets a hierarchy level (number) and explicit permissions. The built-in 'admin' role always has full permissions."},
     {"question": "How do I protect a custom admin page?", "answer": "Three layers: 1) Routes under /admin/* are automatically protected by middleware, 2) Call requireAdmin() in your server component, 3) Use adminActionClient for any server actions. See Extending Admin for complete examples."},
     {"question": "Can admins impersonate other admin users?", "answer": "No. The impersonation feature has built-in safeguards that prevent impersonating admin users or banned accounts. This is enforced at the Better Auth level."}
   ]
/%}

This admin panel is part of the [Next.js Drizzle SaaS Kit](/drizzle).

---

**Next:** [User Management](./user-management)
