Admin SDK
The Admin SDK provides programmatic access to Fluxbase instance management, including user management, authentication, and system configuration.
Overview
Section titled “Overview”The Admin SDK is designed for:
- Building admin dashboards
- Automating user management
- Managing Fluxbase instances programmatically
- Server-side administration tasks
Key Features:
- Admin authentication (setup, login, logout)
- User management (CRUD operations)
- Role management
- Password resets
- User invitations
Installation
Section titled “Installation”The Admin SDK is included in the main Fluxbase SDK:
npm install @fluxbase/sdkQuick Start
Section titled “Quick Start”Initialize Admin Client
Section titled “Initialize Admin Client”import { createClient } from '@fluxbase/sdk'
const client = createClient( 'http://localhost:8080', 'your-service-role-key' // Use service role key for admin operations)
// Access admin moduleconst admin = client.adminInitial Setup
Section titled “Initial Setup”Perform the initial admin setup (first-time only):
// Check if setup is neededconst status = await client.admin.getSetupStatus()
if (status.needs_setup) { // Perform initial setup const response = await client.admin.setup({ email: 'admin@example.com', password: 'SecurePassword123!', name: 'Admin User' })
console.log('Setup complete:', response.user.email) console.log('Access token:', response.access_token)
// Token is automatically set in the client}Admin Login
Section titled “Admin Login”const response = await client.admin.login({ email: 'admin@example.com', password: 'password123'})
console.log('Logged in as:', response.user.email)console.log('Token expires in:', response.expires_in, 'seconds')
// Token is automatically set for subsequent requestsAdmin Authentication
Section titled “Admin Authentication”Check Setup Status
Section titled “Check Setup Status”Check if initial admin setup is required:
const status = await client.admin.getSetupStatus()
if (status.needs_setup) { console.log('Initial setup required')} else { console.log('Admin user already exists')}Response:
{ needs_setup: boolean has_admin: boolean}Initial Setup
Section titled “Initial Setup”Create the first admin user (can only be called once):
const response = await client.admin.setup({ email: 'admin@example.com', password: 'SecurePassword123!', name: 'Admin User'})
console.log('Admin created:', response.user)Requirements:
- Password must be at least 12 characters
- Valid email address
- Can only be called when
needs_setupistrue
Response:
{ user: { id: string email: string name: string role: 'dashboard_admin' email_verified: boolean created_at: string updated_at: string } access_token: string refresh_token: string expires_in: number}Authenticate as an admin user:
const response = await client.admin.login({ email: 'admin@example.com', password: 'password123'})
// Access token is automatically setconsole.log('Access token:', response.access_token)
// Store refresh token for laterlocalStorage.setItem('admin_refresh_token', response.refresh_token)Refresh Token
Section titled “Refresh Token”Refresh an expired access token:
const refreshToken = localStorage.getItem('admin_refresh_token')
const response = await client.admin.refreshToken({ refresh_token: refreshToken})
// New tokensconsole.log('New access token:', response.access_token)localStorage.setItem('admin_refresh_token', response.refresh_token)Logout
Section titled “Logout”Invalidate the current admin session:
await client.admin.logout()
// Clear stored tokenslocalStorage.removeItem('admin_access_token')localStorage.removeItem('admin_refresh_token')
console.log('Logged out successfully')Get Current Admin
Section titled “Get Current Admin”Get the currently authenticated admin user:
const { user } = await client.admin.me()
console.log('Current admin:', user.email)console.log('Role:', user.role)Response:
{ user: { id: string email: string role: string }}User Management
Section titled “User Management”List Users
Section titled “List Users”List all users with optional filters:
// List all usersconst { users, total } = await client.admin.listUsers()console.log(`Total users: ${total}`)
// List with filtersconst result = await client.admin.listUsers({ exclude_admins: true, // Exclude admin users search: 'john', // Search by email limit: 50, // Limit results type: 'app' // User type: 'app' or 'dashboard'})
result.users.forEach(user => { console.log(`${user.email} - ${user.role} - Last login: ${user.last_login_at}`)})Options:
interface ListUsersOptions { exclude_admins?: boolean // Exclude admin users search?: string // Search by email limit?: number // Maximum results type?: 'app' | 'dashboard' // User type}Response:
{ users: Array<{ id: string email: string role?: string created_at: string updated_at?: string email_verified?: boolean last_login_at?: string session_count?: number is_anonymous?: boolean metadata?: Record<string, any> }> total: number}Invite User
Section titled “Invite User”Create a new user and send an invitation email:
const response = await client.admin.inviteUser({ email: 'newuser@example.com', role: 'user', send_email: true})
console.log('User invited:', response.user.email)console.log('Invitation link:', response.invitation_link)Request:
interface InviteUserRequest { email: string role?: string send_email?: boolean}Response:
{ user: EnrichedUser invitation_link?: string message: string}Delete User
Section titled “Delete User”Permanently delete a user:
const response = await client.admin.deleteUser('user-uuid')console.log(response.message) // "User deleted successfully"Warning: This permanently deletes the user and all associated data.
Update User Role
Section titled “Update User Role”Change a user’s role:
const user = await client.admin.updateUserRole( 'user-uuid', 'admin')
console.log('User role updated:', user.role)Common Roles:
user- Regular useradmin- Admin userdashboard_admin- Dashboard administrator- Custom roles as defined in your application
Reset User Password
Section titled “Reset User Password”Generate a new password for a user:
const response = await client.admin.resetUserPassword('user-uuid')console.log(response.message) // "Password reset email sent"This sends a password reset email to the user or returns the new password.
Complete Examples
Section titled “Complete Examples”Admin Dashboard
Section titled “Admin Dashboard”import { createClient } from '@fluxbase/sdk'
// Initialize clientconst client = createClient( 'http://localhost:8080', 'your-service-role-key')
// Admin loginasync function adminLogin(email: string, password: string) { try { const response = await client.admin.login({ email, password })
// Store tokens localStorage.setItem('admin_access_token', response.access_token) localStorage.setItem('admin_refresh_token', response.refresh_token)
return response.user } catch (error) { console.error('Login failed:', error) throw error }}
// Load users with paginationasync function loadUsers(page: number = 1, pageSize: number = 50) { const { users, total } = await client.admin.listUsers({ exclude_admins: false, limit: pageSize, type: 'app' })
return { users, total, pages: Math.ceil(total / pageSize), currentPage: page }}
// Search usersasync function searchUsers(query: string) { const { users } = await client.admin.listUsers({ search: query, limit: 20 })
return users}
// Create new userasync function createUser(email: string, role: string = 'user') { const response = await client.admin.inviteUser({ email, role, send_email: true })
console.log('Invitation sent to:', email) return response.user}
// Make user adminasync function promoteToAdmin(userId: string) { const user = await client.admin.updateUserRole(userId, 'admin') console.log(`${user.email} is now an admin`) return user}
// Remove userasync function removeUser(userId: string) { if (!confirm('Are you sure you want to delete this user?')) { return }
await client.admin.deleteUser(userId) console.log('User deleted')}
// Usageasync function main() { // Login const admin = await adminLogin('admin@example.com', 'password123') console.log('Logged in as:', admin.email)
// Load users const { users, total, pages } = await loadUsers(1, 50) console.log(`Showing ${users.length} of ${total} users (${pages} pages)`)
// Search const results = await searchUsers('john') console.log(`Found ${results.length} users matching "john"`)
// Create user const newUser = await createUser('newuser@example.com', 'user') console.log('Created user:', newUser.id)
// Promote to admin await promoteToAdmin(newUser.id)
// Cleanup // await removeUser(newUser.id)}
main().catch(console.error)React Admin Hook
Section titled “React Admin Hook”import { useState, useEffect } from 'react'import { createClient } from '@fluxbase/sdk'
const client = createClient( 'http://localhost:8080', 'your-service-role-key')
export function useAdmin() { const [isAuthenticated, setIsAuthenticated] = useState(false) const [admin, setAdmin] = useState(null) const [loading, setLoading] = useState(true)
useEffect(() => { checkAuth() }, [])
async function checkAuth() { const token = localStorage.getItem('admin_access_token')
if (!token) { setLoading(false) return }
try { client.admin.setToken(token) const { user } = await client.admin.me() setAdmin(user) setIsAuthenticated(true) } catch (error) { // Token invalid or expired localStorage.removeItem('admin_access_token') localStorage.removeItem('admin_refresh_token') } finally { setLoading(false) } }
async function login(email: string, password: string) { const response = await client.admin.login({ email, password })
localStorage.setItem('admin_access_token', response.access_token) localStorage.setItem('admin_refresh_token', response.refresh_token)
setAdmin(response.user) setIsAuthenticated(true)
return response }
async function logout() { await client.admin.logout()
localStorage.removeItem('admin_access_token') localStorage.removeItem('admin_refresh_token')
setAdmin(null) setIsAuthenticated(false) }
return { isAuthenticated, admin, loading, login, logout }}
// Usage in componentfunction AdminDashboard() { const { isAuthenticated, admin, loading, login, logout } = useAdmin()
if (loading) return <div>Loading...</div>
if (!isAuthenticated) { return <LoginForm onLogin={login} /> }
return ( <div> <h1>Welcome, {admin.email}</h1> <button onClick={logout}>Logout</button> <UserManagement /> </div> )}Bulk Operations
Section titled “Bulk Operations”import { createClient } from '@fluxbase/sdk'
const client = createClient( 'http://localhost:8080', 'your-service-role-key')
// Bulk invite usersasync function bulkInviteUsers(emails: string[], role: string = 'user') { const results = { success: [], failed: [] }
for (const email of emails) { try { const response = await client.admin.inviteUser({ email, role, send_email: true })
results.success.push({ email, userId: response.user.id }) } catch (error) { results.failed.push({ email, error: error.message }) } }
return results}
// Bulk delete inactive usersasync function deleteInactiveUsers(daysSinceLastLogin: number = 90) { const { users } = await client.admin.listUsers({ type: 'app' })
const cutoffDate = new Date() cutoffDate.setDate(cutoffDate.getDate() - daysSinceLastLogin)
const inactiveUsers = users.filter(user => { if (!user.last_login_at) return true const lastLogin = new Date(user.last_login_at) return lastLogin < cutoffDate })
console.log(`Found ${inactiveUsers.length} inactive users`)
for (const user of inactiveUsers) { try { await client.admin.deleteUser(user.id) console.log(`Deleted: ${user.email}`) } catch (error) { console.error(`Failed to delete ${user.email}:`, error) } }
return inactiveUsers.length}
// Usageconst emails = [ 'user1@example.com', 'user2@example.com', 'user3@example.com']
const results = await bulkInviteUsers(emails, 'user')console.log(`Invited: ${results.success.length}`)console.log(`Failed: ${results.failed.length}`)
// Delete inactive users (with confirmation)if (confirm('Delete all users inactive for 90+ days?')) { const deleted = await deleteInactiveUsers(90) console.log(`Deleted ${deleted} inactive users`)}Error Handling
Section titled “Error Handling”import { createClient } from '@fluxbase/sdk'
const client = createClient( 'http://localhost:8080', 'your-service-role-key')
try { await client.admin.login({ email: 'admin@example.com', password: 'wrong-password' })} catch (error) { if (error.status === 401) { console.error('Invalid credentials') } else if (error.status === 429) { console.error('Too many login attempts. Please try again later.') } else { console.error('Login failed:', error.message) }}
// Retry logic with exponential backoffasync function loginWithRetry(email: string, password: string, maxRetries: number = 3) { let lastError
for (let i = 0; i < maxRetries; i++) { try { return await client.admin.login({ email, password }) } catch (error) { lastError = error
if (error.status === 401) { // Don't retry on invalid credentials throw error }
if (i < maxRetries - 1) { // Exponential backoff: 1s, 2s, 4s const delay = Math.pow(2, i) * 1000 await new Promise(resolve => setTimeout(resolve, delay)) } } }
throw lastError}Security Best Practices
Section titled “Security Best Practices”1. Secure Token Storage
Section titled “1. Secure Token Storage”// DO NOT store in localStorage for production (XSS vulnerable)// Use secure, httpOnly cookies instead
// Bad (development only)localStorage.setItem('admin_token', token)
// Good (production)// Let your backend set httpOnly cookies// The SDK will send them automatically2. Token Refresh
Section titled “2. Token Refresh”// Implement automatic token refreshasync function refreshTokenIfNeeded() { const expiresAt = localStorage.getItem('admin_token_expires_at')
if (!expiresAt || Date.now() >= parseInt(expiresAt)) { const refreshToken = localStorage.getItem('admin_refresh_token')
const response = await client.admin.refreshToken({ refresh_token: refreshToken })
localStorage.setItem('admin_access_token', response.access_token) localStorage.setItem('admin_refresh_token', response.refresh_token) localStorage.setItem('admin_token_expires_at', String(Date.now() + response.expires_in * 1000))
client.admin.setToken(response.access_token) }}
// Call before admin operationsawait refreshTokenIfNeeded()await client.admin.listUsers()3. Role Verification
Section titled “3. Role Verification”async function requireAdminRole() { const { user } = await client.admin.me()
if (user.role !== 'admin' && user.role !== 'dashboard_admin') { throw new Error('Admin role required') }
return user}
// Use in operationsawait requireAdminRole()await client.admin.deleteUser('user-id')4. Audit Logging
Section titled “4. Audit Logging”async function deleteUserWithAudit(userId: string, reason: string) { const admin = await client.admin.me()
// Log the action console.log(`[AUDIT] ${admin.user.email} deleted user ${userId}. Reason: ${reason}`)
// Or send to audit service await fetch('/api/audit', { method: 'POST', body: JSON.stringify({ action: 'DELETE_USER', admin_id: admin.user.id, target_user_id: userId, reason, timestamp: new Date().toISOString() }) })
// Perform deletion await client.admin.deleteUser(userId)}TypeScript Types
Section titled “TypeScript Types”import type { // Admin Auth AdminSetupStatusResponse, AdminSetupRequest, AdminUser, AdminAuthResponse, AdminLoginRequest, AdminRefreshRequest, AdminRefreshResponse, AdminMeResponse,
// User Management EnrichedUser, ListUsersResponse, ListUsersOptions, InviteUserRequest, InviteUserResponse, UpdateUserRoleRequest, ResetUserPasswordResponse, DeleteUserResponse,} from '@fluxbase/sdk'Next Steps
Section titled “Next Steps”- Authentication Guide - User authentication methods
- Database Guide - Query and manipulate data
- Storage Guide - File upload and management
- Realtime Guide - WebSocket subscriptions