Skip to content

User Lifecycle

HoneyGrid uses OpenAuth for authentication, implemented through the @openauthjs/openauth package.

export const subjects = createSubjects({
user: z.object({
id: z.string(),
email: z.string().email(),
first_name: z.string().optional(),
last_name: z.string().optional(),
created_date: z.string(),
}),
})

The authentication flow consists of:

  1. Password-based authentication
  2. Email verification code
  3. User creation/retrieval in the database
  4. Session token management

Sessions are managed using refresh and access tokens:

async function refreshTokens() {
const refresh = localStorage.getItem('refresh')
if (!refresh) return
const next = await client.refresh(refresh, {
access: token.current,
})
if (next.err) return
if (!next.tokens) return token.current
localStorage.setItem('refresh', next.tokens.refresh)
token.current = next.tokens.access
return next.tokens.access
}
export const Users = table('Users', {
id: text().primaryKey().notNull(),
first_name: text('first_name'),
last_name: text('last_name'),
email: text().notNull().unique(),
created_date: text('created_date'),
})

Three distinct roles exist in the system:

  • Owner: Full administrative access
  • Editor: Can modify workspace content
  • Viewer: Read-only access
type UserRole = 'owner' | 'editor' | 'viewer'

Permissions are managed through the WorkspacePermissions table:

export const WorkspacePermissions = table('WorkspacePermissions', {
id: integer('id').primaryKey({ autoIncrement: true }),
workspace_id: text()
.notNull()
.references(() => Workspaces.id),
user_id: text(),
email: text(),
role: text().notNull(),
created_at: text('created_at')
.notNull()
.default(sql`(current_timestamp)`),
})

Permission checks are handled by the Workspace Durable Object:

async canEdit(userId: string) {
await this.ensureInitialized();
const permission = await this.checkWorkspacePermission(userId);
return permission === "owner" || permission === "editor";
}
async canView(userId: string) {
await this.ensureInitialized();
const permission = await this.checkWorkspacePermission(userId);
return Boolean(permission);
}

Users can be invited to workspaces with specific roles:

async inviteUser(inviterId: string, email: string, role: Role) {
// Permission check
const canEdit = await this.canEdit(inviterId);
if (!canEdit) {
throw new Error(`User ${inviterId} does not have permission to invite users`);
}
// Create workspace permission
// ... implementation details
}

Users can be removed from workspaces:

async removeUser(removerId: string, removeeId: string) {
const canEdit = await this.canEdit(removerId);
if (!canEdit) {
throw new Error(`User ${removerId} does not have permission to remove users`);
}
// Remove user from workspace
// ... implementation details
}

TODO: Implement complete user deletion flow

  • Need to handle removal from all workspaces
  • Clean up user data
  • Handle workspace ownership transfer
  • Delete authentication records

SUGGESTION: Implement a soft delete mechanism first, then add hard delete capability

TODO: Implement comprehensive profile management

  • Add ability to update user details
  • Add profile picture support
  • Add user preferences

SUGGESTION: Create a dedicated user settings page with sections for:

  • Profile Information
  • Notification Preferences
  • Security Settings
  • Connected Accounts

TODO: Implement proper email verification flow

  • Currently using console.log for verification codes
  • Need to implement proper email service

SUGGESTION: Integrate with a proper email service provider (e.g., Resend, SendGrid)

TODO: Complete role management implementation

  • Role change functionality is currently stubbed
  • Need to implement role hierarchy rules
  • Add role transition validation
// TODO: Implement role change
console.log('Change role to editor', user)

SUGGESTION: Implement role transitions with proper validation and audit logging

  1. Rate Limiting
// Rate limiter is currently commented out but should be implemented
authRoutes.use((c, next) =>
rateLimiter<{ Bindings: Env }>({
windowMs: 15 * 60 * 1000,
limit: 500,
// ... configuration
})
)
  1. Permission Validation
  • All workspace operations validate user permissions
  • Durable Objects maintain permission state
  • Role-based access control is enforced at the API level