Skip to content

Admin Panel Admin Only

Overview

The admin panel provides site administrators with a dashboard for managing users, viewing analytics, configuring application settings, and auditing admin actions. It is accessible at /admin and requires an entry in the admin_users database table.

Roles

RoleCapabilities
adminView dashboard stats, manage users (ban/unban), view activity log
superadminAll admin capabilities + manage other admins, edit app settings

Authentication Flow

Admin access is enforced by three numbered server middlewares that run in order:

  1. 01.steam-auth.ts — Handles Steam OpenID authentication
  2. 02.auth.ts — Validates JWT tokens, sets event.context.auth with the user's steamId
  3. 03.admin-auth.ts — Intercepts /api/admin/* routes, checks the admin_users table for the authenticated Steam ID, and sets event.context.admin

The admin context interface:

typescript
interface AdminContext {
    steamId: string;
    role: 'admin' | 'superadmin';
    permissions: string[];
}

Error responses:

  • 401 Unauthorized — User is not authenticated (no JWT or missing Steam ID)
  • 403 Forbidden — User is authenticated but not in the admin_users table

Database Tables

Defined in server/database/schema/admin.ts using Drizzle ORM.

admin_users

Stores designated administrators.

ColumnTypeDescription
idINT PKAuto-increment
steamidVARCHAR(64)Steam ID (unique)
roleVARCHAR(20)'admin' or 'superadmin'
permissionsJSONArray of permission strings
created_byVARCHAR(64)Steam ID of the admin who added this entry
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update (auto-updates)

banned_users

Tracks user bans. Users with active bans are prevented from accessing the application.

ColumnTypeDescription
idINT PKAuto-increment
steamidVARCHAR(64)Banned user's Steam ID (unique)
reasonTEXTBan reason
banned_byVARCHAR(64)Admin who issued the ban
banned_atTIMESTAMPBan time
expires_atTIMESTAMPExpiration (null = permanent)
activeTINYINT1 = active, 0 = lifted

app_settings

Application configuration key-value store.

ColumnTypeDescription
idINT PKAuto-increment
keyVARCHAR(64)Setting key (unique)
valueTEXTSetting value
typeVARCHAR(20)'string', 'boolean', 'number', or 'json'
descriptionTEXTHuman-readable description
updated_byVARCHAR(64)Last editor's Steam ID
updated_atTIMESTAMPLast update (auto-updates)

admin_activity_log

Audit trail for admin actions.

ColumnTypeDescription
idINT PKAuto-increment
admin_steamidVARCHAR(64)Admin who performed the action
actionVARCHAR(64)Action type (see below)
target_steamidVARCHAR(64)Affected user (if applicable)
detailsJSONAdditional action details
created_atTIMESTAMPAction time

Logged actions: ban_user, unban_user, delete_user_data, update_setting, add_admin, remove_admin


Pages

Dashboard (/admin)

Overview page with:

  • Stats cards (total users, active users, loadouts, items, banned users)
  • Activity line chart with time range selection (7d / 30d / 90d)
  • Top users leaderboard
  • Item distribution pie chart

User Management (/admin/users)

Paginated user table with:

  • Search by Steam ID
  • Ban/unban quick actions
  • Filter for banned users only
  • Click through to user detail page

User Detail (/admin/users/[steamId])

Individual user view with:

  • User info card (Steam ID, activity dates, ban status)
  • Ban/unban/delete actions
  • Loadout table showing all user loadouts with item counts

Settings (/admin/settings) Superadmin

Application settings editor:

  • Type-aware inline editing (string, boolean, number, JSON)
  • Last updated timestamp and editor info

Activity Log (/admin/activity)

Admin action audit log:

  • Paginated list of all admin actions
  • Filter by action type
  • Shows admin, action, target, timestamp

Admin Management (/admin/admins) Superadmin

Manage admin users:

  • List current admins with roles
  • Add new admins (requires Steam ID and role selection)
  • Remove admin privileges

Components

All admin components are in components/admin/.

Layout & Display

ComponentPurpose
AdminLayout.vueMain layout with responsive sidebar navigation. Shows admin management link for superadmins only.
AdminStatsCard.vueDashboard stat card with icon, value, and optional trend indicator (up/down).
AdminUserCard.vueDetailed user info card with ban/unban/delete action buttons and date formatting.

Tables

ComponentPurpose
AdminUserTable.vuePaginated user list with search, ban/unban actions. Debounced search (300ms).
AdminLoadoutTable.vueUser's loadouts with rename, delete, share, clear, and import actions.

Charts

ComponentPurpose
AdminActivityChart.vueLine chart (Chart.js) showing activity over time with selectable time ranges.
AdminHeatmapChart.vueGitHub-style calendar heatmap for daily activity patterns.
AdminLeaderboardChart.vueBar chart showing top users by activity/loadouts.
AdminPieChart.vueDoughnut chart showing item distribution by category with custom legend.

Modals

ComponentPurpose
AdminAddModal.vueAdd new admin user. Validates Steam ID format (17-digit). Role selection (admin/superadmin).
AdminBanModal.vueBan a user. Requires reason (min 5 chars), optional duration in hours.
AdminDeleteModal.vueDelete user data. Safety confirmation: requires typing the exact Steam ID.

Settings

ComponentPurpose
AdminSettingItem.vueInline setting editor. Type-aware: toggle for boolean, number input for number, textarea for JSON.

Composables

useAdminAuth

Location: composables/useAdminAuth.ts

Admin authentication and authorization with role-based access control.

typescript
const {
  isAdmin,        // ComputedRef<boolean>
  isSuperAdmin,   // ComputedRef<boolean>
  adminRole,      // ComputedRef<'admin' | 'superadmin' | null>
  isChecking,     // ComputedRef<boolean>
  checkAdminStatus,   // () => Promise<void>
  requireAdmin,       // () => throws if not admin
  requireSuperAdmin,  // () => throws if not superadmin
  hasPermission,      // (permission: string) => boolean
} = useAdminAuth()

Route guards for navigation:

  • adminNavigationGuard() — Redirects non-admins
  • superAdminNavigationGuard() — Redirects non-superadmins

useAdminStats

Location: composables/useAdminStats.ts

Statistics fetching with caching and auto-refresh.

typescript
const {
  overviewStats,    // ComputedRef<AdminOverviewStats | null>
  activityData,     // ComputedRef<AdminActivityData | null>
  topUsers,         // ComputedRef<AdminTopUser[]>
  timeRange,        // Ref<'7d' | '30d' | '90d'>
  isLoading,        // ComputedRef<boolean>
  error,            // ComputedRef<string | null>
  fetchStats,       // (forceRefresh?) => Promise<void>
  fetchActivity,    // (range?, force?) => Promise<void>
  fetchTopUsers,    // (limit?) => Promise<void>
  refreshAll,       // (force?) => Promise<void>
  setTimeRange,     // (range) => Promise<void>
} = useAdminStats({
  fetchOnMount: true,          // default: true
  autoRefreshInterval: 0,      // ms, 0 = disabled
  defaultTimeRange: '30d',     // '7d' | '30d' | '90d'
})

Utility exports: formatNumber(), calculatePercentChange(), formatPercent(), getTimeRangeLabel(), getDaysFromRange()


Store

The admin store (stores/adminStore.ts) provides centralized state management for all admin data. See the Pinia Stores Reference for full documentation.


Validation Schemas

All admin API requests are validated with Zod schemas defined in server/utils/validation/adminSchemas.ts:

SchemaPurpose
adminBanUserSchemaBan request: reason (1-500 chars, required), duration (optional positive int, hours)
adminUserSearchSchemaUser search: search (string), page (default 1), limit (1-100, default 20), bannedOnly (bool)
adminUpdateSettingSchemaSetting update: key (1-64 chars), value (string, number, or boolean)
adminAddAdminSchemaAdd admin: steamId (1-64 chars), role ('admin' or 'superadmin')
adminActivityLogQuerySchemaActivity log query: page (default 1), limit (1-100, default 50), action (optional string)
adminActivityRangeSchemaActivity range: range ('7d', '30d', '90d', default '7d')
adminTopUsersSchemaTop users: limit (1-100, default 10)

Initial Setup

To add the first admin user, insert a record directly into the database:

sql
INSERT INTO admin_users (steamid, role, created_by)
VALUES ('76561198012345678', 'superadmin', '76561198012345678');

Replace the Steam ID with your own 17-digit Steam ID. After this, you can manage additional admins through the admin panel UI.


Built with ❤️ by the CS2Inspect community