Overview
The Users API provides authentication helpers, user profile management, and account settings for both organizers and attendees on the EventPalour platform.
Get Current User
Retrieve the currently authenticated user.
import { getCurrentUser } from '@/app/actions/auth' ;
const result = await getCurrentUser ();
if ( result ) {
console . log ( 'User:' , result . user . email );
console . log ( 'Session:' , result . session . id );
} else {
console . log ( 'Not authenticated' );
}
Response
User object containing:
id - User identifier
email - Email address
username - Display name
avatar - Avatar URL
platform_role - Role: organizer or attendee
email_verified - Email verification status
registered_2fa - 2FA enabled status
created_at - Account creation date
Session object with session ID and metadata
Returns null if user is not authenticated.
Require Authentication
Enforce authentication or redirect to sign-in.
import { requireAuth } from '@/app/actions/auth' ;
const { user , session } = await requireAuth ();
// User is guaranteed to be authenticated here
If user is not authenticated, automatically redirects to /auth/sign-in.
Usage in Server Components
export default async function DashboardPage () {
const { user } = await requireAuth ();
return (
< div >
< h1 > Welcome , { user . username } </ h1 >
</ div >
);
}
EventPalour has two primary user roles:
Event Organizers Organizers can:
Create and manage workspaces
Create events (free and paid)
Invite team members
View analytics and revenue
Manage ticket sales
Access organizer dashboard
platform_role : PlatformRole . ORGANIZER
KYC Required: Organizers must complete KYC verification to create paid events.
Event Attendees Attendees can:
Browse and search events
Register for free events
Purchase tickets for paid events
View their tickets and QR codes
Receive event updates
Access attendee dashboard
platform_role : PlatformRole . ATTENDEE
Enforce specific platform role or redirect.
import { requireRole } from '@/app/actions/auth' ;
import { PlatformRole } from '@/lib/db/schema/enums' ;
const { user } = await requireRole ( PlatformRole . ORGANIZER );
// User is guaranteed to be an organizer
Role Redirection Logic
Check Authentication
If not authenticated, redirect to /auth/sign-in
Check Platform Role
If no role set, redirect to /auth/onboarding
Check Admin Status
If user is platform admin, redirect to /admin
Validate Role Match
If role doesn’t match required:
Attendees → /dashboard
Organizers → /workspace/{workspaceId}
if ( user . platform_role !== requiredRole ) {
if ( user . platform_role === PlatformRole . ATTENDEE ) {
redirect ( '/dashboard' );
} else if ( user . platform_role === PlatformRole . ORGANIZER ) {
const workspace = await getUserWorkspace ( user . id );
redirect ( `/workspace/ ${ workspace . id } ` );
}
}
Get User Workspaces
Retrieve all workspaces a user belongs to.
import { getUserWorkspaces } from '@/app/actions/auth' ;
const workspaces = await getUserWorkspaces ( userId );
workspaces . forEach (({ workspace , role , isOwner }) => {
console . log ( ` ${ workspace . name } - ${ role } ${ isOwner ? '(Owner)' : '' } ` );
});
Response
Array of workspace memberships:
Workspace details:
id - Workspace ID
name - Workspace name
image_url - Logo URL
invite_code - Invite code
created_at - Creation date
User’s role: admin, moderator, or member
True if user owns the workspace
Validate Workspace Access
Check if user has access to a workspace.
import { validateWorkspaceAccess } from '@/app/actions/auth' ;
const { user , workspace , workspaceRole } =
await validateWorkspaceAccess ( 'wks_abc123' );
console . log ( `Access granted as ${ workspaceRole } ` );
Access Validation Rules
If user is the workspace owner:
Automatically granted admin role
Full access to all features
if ( workspace . user_id === user . id ) {
return { workspaceRole: 'admin' };
}
If user is a workspace member:
Role determined by membership record
Access based on role permissions
If user is not a member:
Redirected to first available workspace
Or to /workspace/unauthorized if no workspaces
Require Workspace Role
Enforce minimum workspace role.
import { requireWorkspaceRole } from '@/app/actions/auth' ;
import { WorkspaceRole } from '@/lib/db/schema/enums' ;
const { user , workspace , workspaceRole } =
await requireWorkspaceRole ( 'wks_abc123' , WorkspaceRole . MODERATOR );
// User has at least moderator role
Role Hierarchy
const roleHierarchy = {
member: 1 , // View-only access
moderator: 2 , // Can create events
admin: 3 // Full management
};
// Check if user has required role or higher
if ( roleHierarchy [ userRole ] < roleHierarchy [ requiredRole ]) {
redirect ( '/workspace/unauthorized' );
}
Check Workspace Role
Check role without redirecting (for conditional rendering).
import { checkWorkspaceRole } from '@/app/actions/auth' ;
import { WorkspaceRole } from '@/lib/db/schema/enums' ;
const result = await checkWorkspaceRole (
'wks_abc123' ,
WorkspaceRole . ADMIN
);
if ( result . hasAccess ) {
// Show admin-only features
}
Response
True if user has required role or higher
User object (if access granted)
Workspace object (if access granted)
User’s actual role (if access granted)
Account Settings
Update user account settings.
Update Username
import { updateUsername } from '@/app/actions/workspace' ;
const result = await updateUsername ( 'johndoe' );
if ( result . success ) {
console . log ( 'Username updated' );
}
Validation:
Minimum 3 characters
Maximum 255 characters
Only letters, numbers, underscores, and hyphens
Must be unique
const schema = z . string ()
. min ( 3 , "Username must be at least 3 characters" )
. max ( 255 )
. regex (
/ ^ [ a-zA-Z0-9_- ] + $ / ,
"Username can only contain letters, numbers, underscores, and hyphens"
);
Change Email
Update user email address.
import { changeEmail } from '@/app/actions/workspace' ;
const result = await changeEmail (
'[email protected] ' ,
'2fa_token' // Required if 2FA enabled
);
if ( result . success ) {
console . log ( 'Email updated - verification required' );
}
Email Verification Required: After changing email, the account is marked as unverified. User must verify the new email address.
Security:
Requires 2FA verification if enabled
New email must not be in use
Email is normalized (trimmed, lowercased)
Change Password
Update user password.
import { changePassword } from '@/app/actions/workspace' ;
const result = await changePassword (
'currentPassword123' ,
'newSecurePassword456' ,
'2fa_token' // Required if 2FA enabled
);
if ( result . success ) {
console . log ( 'Password changed successfully' );
}
Validation:
Current password must be correct
New password must meet strength requirements
Requires 2FA if enabled
Not available for OAuth-only accounts
if ( ! currentPasswordHash ) {
return { error: "Password change not available for OAuth accounts" };
}
Delete Account
Permanently delete user account.
import { deleteUserAccount } from '@/app/actions/workspace' ;
const result = await deleteUserAccount (
'delete my account' , // Must type exactly
'2fa_token' // Required if 2FA enabled
);
if ( result . success ) {
// User deleted, redirected to sign-in
}
Deletion Requirements
Confirmation
User must type exactly “DELETE MY ACCOUNT” to confirm.
2FA Verification
If 2FA is enabled, valid token required.
Workspace Check
User must not own any workspaces: const ownedWorkspaces = await db . query . workspace . findMany ({
where: eq ( tables . workspace . user_id , user . id )
});
if ( ownedWorkspaces . length > 0 ) {
return { error: "Must transfer or delete workspaces first" };
}
Data Cleanup
System deletes:
All workspace memberships
All user sessions
User account record
Irreversible Action: Account deletion cannot be undone. All data is permanently removed.
Sign Out
Sign out the current user.
import { signOut } from '@/app/actions/auth' ;
const result = await signOut ();
if ( result . success ) {
// Session invalidated
// Redirect to home page
}
Sign out process:
Invalidates current session in database
Deletes session cookie
User is logged out
await invalidateSession ( session . id );
await deleteSessionTokenCookie ();
User Schema
The complete user object structure:
interface User {
id : string ;
email : string ;
username : string | null ;
avatar : string | null ;
platform_role : PlatformRole | null ;
email_verified : boolean ;
registered_2fa : boolean ;
created_at : Date ;
updated_at : Date ;
}
enum PlatformRole {
ORGANIZER = "organizer" ,
ATTENDEE = "attendee"
}
OAuth Accounts
Check if user has OAuth authentication.
import { checkUserHasOAuth } from '@/app/actions/workspace' ;
const result = await checkUserHasOAuth ( userId );
if ( result . hasOAuth ) {
console . log ( `User signed in via ${ result . provider } ` );
// Some features may not be available (e.g., password change)
}
OAuth Providers:
Google
GitHub
(More providers coming soon)
Password Management: Users who sign in exclusively via OAuth cannot change their password through the API.
2FA Verification
Sensitive operations require 2FA verification when enabled:
if ( user . registered_2fa ) {
if ( ! verificationToken ) {
return { error: "2FA verification required" , requires2FA: true };
}
const { verify2FAToken } = await import (
'@/lib/server/two-factor-verification'
);
const verification = await verify2FAToken ( verificationToken );
if ( ! verification . valid ) {
return { error: "2FA verification failed" };
}
}
Operations requiring 2FA:
Change email
Change password
Transfer workspace ownership
Delete workspace
Delete account
Error Handling
Common user API errors:
Error Cause Solution "Authentication required"User not signed in Call requireAuth() or sign in "Username is already taken"Duplicate username Choose different username "Email is already in use"Duplicate email Use different email "Current password is incorrect"Wrong password provided Verify current password "2FA verification required"2FA enabled but no token Provide valid 2FA token "Password change not available for OAuth accounts"OAuth-only account Cannot set password "Must transfer or delete workspaces first"User owns workspaces Transfer or delete workspaces
Complete Example
Complete user profile management:
import {
requireAuth ,
updateUsername ,
changeEmail ,
getUserWorkspaces
} from '@/app/actions/auth' ;
import { WorkspaceRole } from '@/lib/db/schema/enums' ;
async function updateUserProfile () {
// 1. Ensure user is authenticated
const { user } = await requireAuth ();
console . log ( 'Current user:' , user . email );
// 2. Update username
const usernameResult = await updateUsername ( 'johndoe2024' );
if ( ! usernameResult . success ) {
console . error ( 'Username update failed:' , usernameResult . error );
return ;
}
console . log ( 'Username updated' );
// 3. Update email (requires 2FA if enabled)
let emailResult ;
if ( user . registered_2fa ) {
// Prompt user for 2FA token
const token = await prompt2FA ();
emailResult = await changeEmail ( '[email protected] ' , token );
} else {
emailResult = await changeEmail ( '[email protected] ' );
}
if ( ! emailResult . success ) {
console . error ( 'Email update failed:' , emailResult . error );
return ;
}
console . log ( 'Email updated - please verify new email' );
// 4. Get user workspaces
const workspaces = await getUserWorkspaces ( user . id );
console . log ( 'User workspaces:' );
workspaces . forEach (({ workspace , role , isOwner }) => {
console . log (
`- ${ workspace . name } : ${ role }${ isOwner ? ' (Owner)' : '' } `
);
});
console . log ( 'Profile update complete' );
}
Next Steps
Workspaces API Manage workspace memberships
Authentication Learn about auth features
Authentication Learn about authentication and 2FA
Events API Create and manage events