File size: 2,582 Bytes
74bfb65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import { clerkClient } from '@clerk/express';
import { logger } from './logger';

/**
 * Owner-configured bootstrap runs independently in each Clerk environment.
 * The completion marker prevents a restart from restoring a revoked role.
 * Passwords are read only from Secrets and never logged or reset on restart.
 */
export async function bootstrapAdmin() {
  const email = process.env.ADMIN_EMAIL?.trim().toLowerCase();
  if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    throw new Error('Set a valid ADMIN_EMAIL before starting admin authentication.');
  }
  try {
    const client = clerkClient;
    const { data: users } = await client.users.getUserList({ emailAddress: [email], limit: 2 });
    if (users.length > 1) throw new Error('Admin bootstrap found multiple matching accounts.');
    const existing = users[0];
    if (existing?.privateMetadata.ecomAdminBootstrapComplete) {
      logger.info('Admin account bootstrap already completed; existing permissions preserved.');
      return;
    }
    if (existing) {
      const verified = existing.emailAddresses.some(address =>
        address.emailAddress.toLowerCase() === email && address.verification?.status === 'verified',
      );
      if (!verified) throw new Error('Verify ownership of the configured admin email before granting access.');
      await client.users.updateUserMetadata(existing.id, {
        publicMetadata: { ...existing.publicMetadata, role: 'admin' },
        privateMetadata: { ...existing.privateMetadata, ecomAdminBootstrapComplete: true },
      });
    } else {
      const password = process.env.ADMIN_INITIAL_PASSWORD;
      if (!password) throw new Error('Set ADMIN_INITIAL_PASSWORD in Secrets to create the initial admin account.');
      await client.users.createUser({
        emailAddress: [email],
        password,
        firstName: 'Admin',
        publicMetadata: { role: 'admin' },
        privateMetadata: { ecomAdminBootstrapComplete: true },
      });
    }
    logger.info('Owner-configured admin account is ready.');
  } catch (error) {
    // Do not log SDK request/response objects: they can contain credentials.
    if (error && typeof error === 'object' && 'errors' in error) {
      const errors = error.errors as { code?: string }[];
      const codes = errors.map(item => item.code?.replace(/[^a-zA-Z0-9_]/g, '')).filter(Boolean).join(', ');
      throw new Error(`Admin account setup was rejected by the login provider (${codes || 'request_failed'}). Check the admin settings and use a strong ADMIN_INITIAL_PASSWORD.`);
    }
    throw error;
  }
}