canopycms-auth-dev 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,168 @@
1
+ import { extractHeaders } from 'canopycms/auth';
2
+ import { getDevUserCookieFromHeaders } from './cookie-utils';
3
+ export const DEV_ADMIN_USER_ID = 'dev_admin_3xY6zW1qR5';
4
+ export const DEFAULT_USERS = [
5
+ {
6
+ userId: 'dev_user1_2nK8mP4xL9',
7
+ name: 'User One',
8
+ email: 'user1@localhost.dev',
9
+ externalGroups: ['team-a', 'team-b'],
10
+ },
11
+ {
12
+ userId: 'dev_user2_7qR3tY6wN2',
13
+ name: 'User Two',
14
+ email: 'user2@localhost.dev',
15
+ externalGroups: ['team-b'],
16
+ },
17
+ {
18
+ userId: 'dev_user3_5vS1pM8kJ4',
19
+ name: 'User Three',
20
+ email: 'user3@localhost.dev',
21
+ externalGroups: ['team-c'],
22
+ },
23
+ {
24
+ userId: 'dev_reviewer_9aB4cD2eF7',
25
+ name: 'Reviewer One',
26
+ email: 'reviewer1@localhost.dev',
27
+ externalGroups: ['team-a'],
28
+ // Note: 'Reviewers' membership comes from internal groups file, not auth plugin
29
+ },
30
+ {
31
+ userId: DEV_ADMIN_USER_ID,
32
+ name: 'Admin One',
33
+ email: 'admin1@localhost.dev',
34
+ externalGroups: ['team-a', 'team-b', 'team-c'],
35
+ // Note: Does NOT include 'Admins' - that's applied by bootstrap admin config or auto-bootstrap
36
+ },
37
+ ];
38
+ export const DEFAULT_GROUPS = [
39
+ { id: 'team-a', name: 'Team A', description: 'Team A' },
40
+ { id: 'team-b', name: 'Team B', description: 'Team B' },
41
+ { id: 'team-c', name: 'Team C', description: 'Team C' },
42
+ ];
43
+ /**
44
+ * Dev authentication plugin implementation for CanopyCMS.
45
+ * Supports both cookie-based (UI) and header-based (tests) authentication.
46
+ */
47
+ export class DevAuthPlugin {
48
+ constructor(config = {}) {
49
+ this.users = config.users ?? DEFAULT_USERS;
50
+ this.groups = config.groups ?? DEFAULT_GROUPS;
51
+ this.defaultUserId = config.defaultUserId ?? 'dev_user1_2nK8mP4xL9';
52
+ }
53
+ async authenticate(context) {
54
+ // 1. Extract headers using extractHeaders() helper
55
+ const headers = extractHeaders(context);
56
+ if (!headers) {
57
+ return { success: false, error: 'Invalid context' };
58
+ }
59
+ // 2. Check X-Test-User header (for test-app compatibility) FIRST
60
+ let userId = headers.get('X-Test-User');
61
+ // 3. If no test header, check x-dev-user-id header OR canopy-dev-user cookie
62
+ if (!userId) {
63
+ userId = headers.get('x-dev-user-id') ?? getDevUserCookieFromHeaders(headers);
64
+ }
65
+ // 4. Fall back to default user
66
+ if (!userId) {
67
+ userId = this.defaultUserId;
68
+ }
69
+ // 5. Map test user keys to dev user IDs for test compatibility
70
+ const userIdMapped = this.mapTestUserKey(userId);
71
+ // 6. Find user in config
72
+ const user = this.users.find((u) => u.userId === userIdMapped);
73
+ if (!user) {
74
+ return { success: false, error: `Dev user not found: ${userId}` };
75
+ }
76
+ // 7. Return AuthenticationResult with externalGroups
77
+ return {
78
+ success: true,
79
+ user: {
80
+ userId: user.userId,
81
+ email: user.email,
82
+ name: user.name,
83
+ avatarUrl: user.avatarUrl,
84
+ externalGroups: user.externalGroups,
85
+ },
86
+ };
87
+ }
88
+ /**
89
+ * Map test-app user keys to dev user IDs for backward compatibility
90
+ */
91
+ mapTestUserKey(key) {
92
+ const testUserMap = {
93
+ admin: DEV_ADMIN_USER_ID, // admin1
94
+ editor: 'dev_user1_2nK8mP4xL9', // user1
95
+ viewer: 'dev_user2_7qR3tY6wN2', // user2
96
+ reviewer: 'dev_reviewer_9aB4cD2eF7', // reviewer1
97
+ };
98
+ return testUserMap[key] ?? key;
99
+ }
100
+ async searchUsers(query, limit) {
101
+ const lowerQuery = query.toLowerCase();
102
+ const filtered = this.users.filter((u) => u.name.toLowerCase().includes(lowerQuery) || u.email.toLowerCase().includes(lowerQuery));
103
+ const results = filtered.slice(0, limit);
104
+ return results.map((u) => ({
105
+ id: u.userId,
106
+ name: u.name,
107
+ email: u.email,
108
+ avatarUrl: u.avatarUrl,
109
+ }));
110
+ }
111
+ async getUserMetadata(userId) {
112
+ const user = this.users.find((u) => u.userId === userId);
113
+ if (!user)
114
+ return null;
115
+ return {
116
+ id: user.userId,
117
+ name: user.name,
118
+ email: user.email,
119
+ avatarUrl: user.avatarUrl,
120
+ };
121
+ }
122
+ async getGroupMetadata(groupId) {
123
+ const group = this.groups.find((g) => g.id === groupId);
124
+ if (!group)
125
+ return null;
126
+ return {
127
+ id: group.id,
128
+ name: group.name,
129
+ description: group.description,
130
+ };
131
+ }
132
+ async listGroups(limit) {
133
+ const groups = limit ? this.groups.slice(0, limit) : this.groups;
134
+ return groups.map((g) => ({
135
+ id: g.id,
136
+ name: g.name,
137
+ description: g.description,
138
+ }));
139
+ }
140
+ async searchExternalGroups(query) {
141
+ const lowerQuery = query.toLowerCase();
142
+ return this.groups
143
+ .filter((g) => g.name.toLowerCase().includes(lowerQuery))
144
+ .map((g) => ({
145
+ id: g.id,
146
+ name: g.name,
147
+ }));
148
+ }
149
+ }
150
+ /**
151
+ * Factory function for creating dev auth plugin.
152
+ * By default, auto-sets CANOPY_BOOTSTRAP_ADMIN_IDS to the admin dev user
153
+ * if the env var is not already set. Disable with { autoBootstrapAdmin: false }.
154
+ */
155
+ export function createDevAuthPlugin(config) {
156
+ const shouldAutoBootstrap = config?.autoBootstrapAdmin ?? true;
157
+ if (shouldAutoBootstrap && !process.env.CANOPY_BOOTSTRAP_ADMIN_IDS) {
158
+ const users = config?.users ?? DEFAULT_USERS;
159
+ const adminUser = users.find((u) => u.userId === DEV_ADMIN_USER_ID);
160
+ if (adminUser) {
161
+ process.env.CANOPY_BOOTSTRAP_ADMIN_IDS = adminUser.userId;
162
+ console.info(`CanopyCMS dev-auth: Auto-configured ${adminUser.name} (${adminUser.userId}) as bootstrap admin. ` +
163
+ `Set CANOPY_BOOTSTRAP_ADMIN_IDS env var or pass autoBootstrapAdmin: false to override.`);
164
+ }
165
+ }
166
+ return new DevAuthPlugin(config ?? {});
167
+ }
168
+ //# sourceMappingURL=dev-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-plugin.js","sourceRoot":"","sources":["../src/dev-plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,382 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { DevAuthPlugin, createDevAuthPlugin, DEFAULT_USERS, DEFAULT_GROUPS, DEV_ADMIN_USER_ID, } from './dev-plugin';
3
+ // Type guard to assert successful authentication
4
+ function assertSuccess(result) {
5
+ expect(result.success).toBe(true);
6
+ if (!result.success || !result.user) {
7
+ throw new Error('Authentication failed');
8
+ }
9
+ }
10
+ describe('DevAuthPlugin', () => {
11
+ describe('authenticate', () => {
12
+ it('returns default user when no headers provided', async () => {
13
+ const plugin = new DevAuthPlugin({});
14
+ const result = await plugin.authenticate(new Headers());
15
+ assertSuccess(result);
16
+ expect(result.user.userId).toBe('dev_user1_2nK8mP4xL9'); // user1
17
+ expect(result.user.name).toBe('User One');
18
+ expect(result.user.email).toBe('user1@localhost.dev');
19
+ expect(result.user.externalGroups).toEqual(['team-a', 'team-b']);
20
+ });
21
+ it('authenticates via X-Test-User header', async () => {
22
+ const plugin = new DevAuthPlugin({});
23
+ const headers = new Headers({ 'X-Test-User': 'admin' });
24
+ const result = await plugin.authenticate(headers);
25
+ assertSuccess(result);
26
+ expect(result.user.userId).toBe('dev_admin_3xY6zW1qR5'); // admin1
27
+ expect(result.user.name).toBe('Admin One');
28
+ });
29
+ it('authenticates via x-dev-user-id header', async () => {
30
+ const plugin = new DevAuthPlugin({});
31
+ const headers = new Headers({ 'x-dev-user-id': 'dev_user2_7qR3tY6wN2' });
32
+ const result = await plugin.authenticate(headers);
33
+ assertSuccess(result);
34
+ expect(result.user.userId).toBe('dev_user2_7qR3tY6wN2'); // user2
35
+ expect(result.user.name).toBe('User Two');
36
+ });
37
+ it('authenticates via canopy-dev-user cookie', async () => {
38
+ const plugin = new DevAuthPlugin({});
39
+ const headers = new Headers({
40
+ cookie: 'canopy-dev-user=dev_user3_5vS1pM8kJ4; other=value',
41
+ });
42
+ const result = await plugin.authenticate(headers);
43
+ assertSuccess(result);
44
+ expect(result.user.userId).toBe('dev_user3_5vS1pM8kJ4'); // user3
45
+ expect(result.user.name).toBe('User Three');
46
+ });
47
+ it('prioritizes X-Test-User over cookie', async () => {
48
+ const plugin = new DevAuthPlugin({});
49
+ const headers = new Headers({
50
+ 'X-Test-User': 'admin',
51
+ cookie: 'canopy-dev-user=dev_user1_2nK8mP4xL9',
52
+ });
53
+ const result = await plugin.authenticate(headers);
54
+ assertSuccess(result);
55
+ expect(result.user.userId).toBe('dev_admin_3xY6zW1qR5'); // admin1 from header
56
+ });
57
+ it('maps test user keys to dev user IDs', async () => {
58
+ const plugin = new DevAuthPlugin({});
59
+ const testCases = [
60
+ { key: 'admin', expectedId: 'dev_admin_3xY6zW1qR5' },
61
+ { key: 'editor', expectedId: 'dev_user1_2nK8mP4xL9' },
62
+ { key: 'viewer', expectedId: 'dev_user2_7qR3tY6wN2' },
63
+ { key: 'reviewer', expectedId: 'dev_reviewer_9aB4cD2eF7' },
64
+ ];
65
+ for (const { key, expectedId } of testCases) {
66
+ const headers = new Headers({ 'X-Test-User': key });
67
+ const result = await plugin.authenticate(headers);
68
+ assertSuccess(result);
69
+ expect(result.user.userId).toBe(expectedId);
70
+ }
71
+ });
72
+ it('returns failure for unknown user ID', async () => {
73
+ const plugin = new DevAuthPlugin({});
74
+ const headers = new Headers({ 'x-dev-user-id': 'unknown_user' });
75
+ const result = await plugin.authenticate(headers);
76
+ expect(result.success).toBe(false);
77
+ if (!result.success) {
78
+ expect(result.error).toContain('Dev user not found');
79
+ }
80
+ });
81
+ it('uses custom default user when specified', async () => {
82
+ const plugin = new DevAuthPlugin({
83
+ defaultUserId: 'dev_admin_3xY6zW1qR5', // admin1
84
+ });
85
+ const result = await plugin.authenticate(new Headers());
86
+ assertSuccess(result);
87
+ expect(result.user.userId).toBe('dev_admin_3xY6zW1qR5');
88
+ });
89
+ });
90
+ describe('searchUsers', () => {
91
+ it('returns all users when query is empty', async () => {
92
+ const plugin = new DevAuthPlugin({});
93
+ const results = await plugin.searchUsers('');
94
+ expect(results).toHaveLength(5);
95
+ expect(results[0].id).toBe('dev_user1_2nK8mP4xL9');
96
+ expect(results[0].name).toBe('User One');
97
+ expect(results[0].email).toBe('user1@localhost.dev');
98
+ });
99
+ it('filters users by name', async () => {
100
+ const plugin = new DevAuthPlugin({});
101
+ const results = await plugin.searchUsers('admin');
102
+ expect(results).toHaveLength(1);
103
+ expect(results[0].name).toBe('Admin One');
104
+ });
105
+ it('filters users by email', async () => {
106
+ const plugin = new DevAuthPlugin({});
107
+ const results = await plugin.searchUsers('reviewer1@');
108
+ expect(results).toHaveLength(1);
109
+ expect(results[0].id).toBe('dev_reviewer_9aB4cD2eF7');
110
+ });
111
+ it('is case insensitive', async () => {
112
+ const plugin = new DevAuthPlugin({});
113
+ const results = await plugin.searchUsers('USER');
114
+ expect(results.length).toBeGreaterThan(0);
115
+ expect(results.some((u) => u.name.toLowerCase().includes('user'))).toBe(true);
116
+ });
117
+ it('respects limit parameter', async () => {
118
+ const plugin = new DevAuthPlugin({});
119
+ const results = await plugin.searchUsers('', 2);
120
+ expect(results).toHaveLength(2);
121
+ });
122
+ it('works with custom users', async () => {
123
+ const customUsers = [
124
+ {
125
+ userId: 'custom_1',
126
+ name: 'Custom User',
127
+ email: 'custom@test.com',
128
+ externalGroups: [],
129
+ },
130
+ ];
131
+ const plugin = new DevAuthPlugin({ users: customUsers });
132
+ const results = await plugin.searchUsers('custom');
133
+ expect(results).toHaveLength(1);
134
+ expect(results[0].id).toBe('custom_1');
135
+ });
136
+ });
137
+ describe('getUserMetadata', () => {
138
+ it('returns user metadata for valid user', async () => {
139
+ const plugin = new DevAuthPlugin({});
140
+ const metadata = await plugin.getUserMetadata('dev_user1_2nK8mP4xL9');
141
+ expect(metadata).toEqual({
142
+ id: 'dev_user1_2nK8mP4xL9',
143
+ name: 'User One',
144
+ email: 'user1@localhost.dev',
145
+ avatarUrl: undefined,
146
+ });
147
+ });
148
+ it('returns null for unknown user', async () => {
149
+ const plugin = new DevAuthPlugin({});
150
+ const metadata = await plugin.getUserMetadata('unknown');
151
+ expect(metadata).toBeNull();
152
+ });
153
+ it('includes avatarUrl when present', async () => {
154
+ const customUsers = [
155
+ {
156
+ userId: 'user_1',
157
+ name: 'User',
158
+ email: 'user@test.com',
159
+ avatarUrl: 'https://example.com/avatar.jpg',
160
+ externalGroups: [],
161
+ },
162
+ ];
163
+ const plugin = new DevAuthPlugin({ users: customUsers });
164
+ const metadata = await plugin.getUserMetadata('user_1');
165
+ expect(metadata?.avatarUrl).toBe('https://example.com/avatar.jpg');
166
+ });
167
+ });
168
+ describe('getGroupMetadata', () => {
169
+ it('returns group metadata for valid group', async () => {
170
+ const plugin = new DevAuthPlugin({});
171
+ const metadata = await plugin.getGroupMetadata('team-a');
172
+ expect(metadata).toEqual({
173
+ id: 'team-a',
174
+ name: 'Team A',
175
+ description: 'Team A',
176
+ });
177
+ });
178
+ it('returns null for unknown group', async () => {
179
+ const plugin = new DevAuthPlugin({});
180
+ const metadata = await plugin.getGroupMetadata('unknown');
181
+ expect(metadata).toBeNull();
182
+ });
183
+ it('works with custom groups', async () => {
184
+ const customGroups = [
185
+ { id: 'team-x', name: 'Team X', description: 'Custom team' },
186
+ ];
187
+ const plugin = new DevAuthPlugin({ groups: customGroups });
188
+ const metadata = await plugin.getGroupMetadata('team-x');
189
+ expect(metadata).toEqual({
190
+ id: 'team-x',
191
+ name: 'Team X',
192
+ description: 'Custom team',
193
+ });
194
+ });
195
+ });
196
+ describe('listGroups', () => {
197
+ it('returns all groups by default', async () => {
198
+ const plugin = new DevAuthPlugin({});
199
+ const groups = await plugin.listGroups();
200
+ expect(groups).toHaveLength(3);
201
+ expect(groups.map((g) => g.id)).toEqual(['team-a', 'team-b', 'team-c']);
202
+ });
203
+ it('respects limit parameter', async () => {
204
+ const plugin = new DevAuthPlugin({});
205
+ const groups = await plugin.listGroups(2);
206
+ expect(groups).toHaveLength(2);
207
+ });
208
+ });
209
+ describe('searchExternalGroups', () => {
210
+ it('returns all groups when query is empty', async () => {
211
+ const plugin = new DevAuthPlugin({});
212
+ const results = await plugin.searchExternalGroups('');
213
+ expect(results).toHaveLength(3);
214
+ });
215
+ it('filters groups by name', async () => {
216
+ const plugin = new DevAuthPlugin({});
217
+ const results = await plugin.searchExternalGroups('team a');
218
+ expect(results).toHaveLength(1);
219
+ expect(results[0].id).toBe('team-a');
220
+ expect(results[0].name).toBe('Team A');
221
+ });
222
+ it('is case insensitive', async () => {
223
+ const plugin = new DevAuthPlugin({});
224
+ const results = await plugin.searchExternalGroups('TEAM');
225
+ expect(results.length).toBeGreaterThan(0);
226
+ });
227
+ });
228
+ describe('custom configuration', () => {
229
+ it('accepts custom users and groups', () => {
230
+ const customUsers = [
231
+ {
232
+ userId: 'custom_1',
233
+ name: 'Custom',
234
+ email: 'custom@test.com',
235
+ externalGroups: ['custom-group'],
236
+ },
237
+ ];
238
+ const customGroups = [{ id: 'custom-group', name: 'Custom Group' }];
239
+ const plugin = new DevAuthPlugin({
240
+ users: customUsers,
241
+ groups: customGroups,
242
+ defaultUserId: 'custom_1',
243
+ });
244
+ expect(plugin).toBeInstanceOf(DevAuthPlugin);
245
+ });
246
+ });
247
+ describe('createDevAuthPlugin factory', () => {
248
+ beforeEach(() => {
249
+ vi.spyOn(console, 'info').mockImplementation(() => { });
250
+ });
251
+ afterEach(() => {
252
+ vi.restoreAllMocks();
253
+ });
254
+ it('creates plugin with default config', () => {
255
+ const plugin = createDevAuthPlugin();
256
+ expect(plugin).toBeInstanceOf(DevAuthPlugin);
257
+ });
258
+ it('creates plugin with custom config', () => {
259
+ const plugin = createDevAuthPlugin({
260
+ defaultUserId: 'dev_admin_3xY6zW1qR5',
261
+ });
262
+ expect(plugin).toBeInstanceOf(DevAuthPlugin);
263
+ });
264
+ it('works without any arguments', () => {
265
+ const plugin = createDevAuthPlugin();
266
+ expect(plugin).toBeInstanceOf(DevAuthPlugin);
267
+ });
268
+ });
269
+ describe('DEFAULT_USERS', () => {
270
+ it('exports default users', () => {
271
+ expect(DEFAULT_USERS).toHaveLength(5);
272
+ expect(DEFAULT_USERS[0].userId).toBe('dev_user1_2nK8mP4xL9');
273
+ expect(DEFAULT_USERS[4].userId).toBe('dev_admin_3xY6zW1qR5');
274
+ });
275
+ it('has correct user structure', () => {
276
+ DEFAULT_USERS.forEach((user) => {
277
+ expect(user).toHaveProperty('userId');
278
+ expect(user).toHaveProperty('name');
279
+ expect(user).toHaveProperty('email');
280
+ expect(user).toHaveProperty('externalGroups');
281
+ expect(Array.isArray(user.externalGroups)).toBe(true);
282
+ });
283
+ });
284
+ });
285
+ describe('DEFAULT_GROUPS', () => {
286
+ it('exports default groups', () => {
287
+ expect(DEFAULT_GROUPS).toHaveLength(3);
288
+ expect(DEFAULT_GROUPS.map((g) => g.id)).toEqual(['team-a', 'team-b', 'team-c']);
289
+ });
290
+ it('has correct group structure', () => {
291
+ DEFAULT_GROUPS.forEach((group) => {
292
+ expect(group).toHaveProperty('id');
293
+ expect(group).toHaveProperty('name');
294
+ expect(group).toHaveProperty('description');
295
+ });
296
+ });
297
+ });
298
+ describe('cookie parsing', () => {
299
+ it('extracts cookie from single cookie string', async () => {
300
+ const plugin = new DevAuthPlugin({});
301
+ const headers = new Headers({
302
+ cookie: 'canopy-dev-user=dev_admin_3xY6zW1qR5',
303
+ });
304
+ const result = await plugin.authenticate(headers);
305
+ assertSuccess(result);
306
+ expect(result.user.userId).toBe('dev_admin_3xY6zW1qR5');
307
+ });
308
+ it('extracts cookie from multiple cookies', async () => {
309
+ const plugin = new DevAuthPlugin({});
310
+ const headers = new Headers({
311
+ cookie: 'session=abc123; canopy-dev-user=dev_user2_7qR3tY6wN2; other=value',
312
+ });
313
+ const result = await plugin.authenticate(headers);
314
+ assertSuccess(result);
315
+ expect(result.user.userId).toBe('dev_user2_7qR3tY6wN2');
316
+ });
317
+ it('extracts cookie without semicolon separator', async () => {
318
+ const plugin = new DevAuthPlugin({});
319
+ const headers = new Headers({
320
+ cookie: 'canopy-dev-user=dev_reviewer_9aB4cD2eF7',
321
+ });
322
+ const result = await plugin.authenticate(headers);
323
+ assertSuccess(result);
324
+ expect(result.user.userId).toBe('dev_reviewer_9aB4cD2eF7');
325
+ });
326
+ it('returns default user when cookie not found', async () => {
327
+ const plugin = new DevAuthPlugin({});
328
+ const headers = new Headers({
329
+ cookie: 'session=abc123; other=value',
330
+ });
331
+ const result = await plugin.authenticate(headers);
332
+ assertSuccess(result);
333
+ expect(result.user.userId).toBe('dev_user1_2nK8mP4xL9'); // default
334
+ });
335
+ });
336
+ describe('auto-bootstrap admin', () => {
337
+ let originalEnv;
338
+ beforeEach(() => {
339
+ originalEnv = process.env.CANOPY_BOOTSTRAP_ADMIN_IDS;
340
+ vi.spyOn(console, 'info').mockImplementation(() => { });
341
+ });
342
+ afterEach(() => {
343
+ vi.restoreAllMocks();
344
+ if (originalEnv === undefined) {
345
+ delete process.env.CANOPY_BOOTSTRAP_ADMIN_IDS;
346
+ }
347
+ else {
348
+ process.env.CANOPY_BOOTSTRAP_ADMIN_IDS = originalEnv;
349
+ }
350
+ });
351
+ it('auto-sets CANOPY_BOOTSTRAP_ADMIN_IDS when not already set', () => {
352
+ delete process.env.CANOPY_BOOTSTRAP_ADMIN_IDS;
353
+ createDevAuthPlugin();
354
+ expect(process.env.CANOPY_BOOTSTRAP_ADMIN_IDS).toBe(DEV_ADMIN_USER_ID);
355
+ });
356
+ it('does not override existing CANOPY_BOOTSTRAP_ADMIN_IDS', () => {
357
+ process.env.CANOPY_BOOTSTRAP_ADMIN_IDS = 'custom_user_id';
358
+ createDevAuthPlugin();
359
+ expect(process.env.CANOPY_BOOTSTRAP_ADMIN_IDS).toBe('custom_user_id');
360
+ });
361
+ it('can be disabled via autoBootstrapAdmin: false', () => {
362
+ delete process.env.CANOPY_BOOTSTRAP_ADMIN_IDS;
363
+ createDevAuthPlugin({ autoBootstrapAdmin: false });
364
+ expect(process.env.CANOPY_BOOTSTRAP_ADMIN_IDS).toBeUndefined();
365
+ });
366
+ it('skips auto-bootstrap when custom users do not include admin user', () => {
367
+ delete process.env.CANOPY_BOOTSTRAP_ADMIN_IDS;
368
+ createDevAuthPlugin({
369
+ users: [
370
+ {
371
+ userId: 'custom_1',
372
+ name: 'Custom',
373
+ email: 'custom@test.com',
374
+ externalGroups: [],
375
+ },
376
+ ],
377
+ });
378
+ expect(process.env.CANOPY_BOOTSTRAP_ADMIN_IDS).toBeUndefined();
379
+ });
380
+ });
381
+ });
382
+ //# sourceMappingURL=dev-plugin.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-plugin.test.js","sourceRoot":"","sources":["../src/dev-plugin.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { createDevAuthPlugin, DevAuthPlugin, DEFAULT_USERS, DEFAULT_GROUPS, DEV_ADMIN_USER_ID, } from './dev-plugin';
2
+ export type { DevAuthConfig, DevUser, DevGroup } from './dev-plugin';
3
+ export { createDevTokenVerifier } from './jwt-verifier';
4
+ export { refreshDevCache } from './cache-writer';
5
+ export type { RefreshDevCacheOptions } from './cache-writer';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { createDevAuthPlugin, DevAuthPlugin, DEFAULT_USERS, DEFAULT_GROUPS, DEV_ADMIN_USER_ID, } from './dev-plugin';
2
+ export { createDevTokenVerifier } from './jwt-verifier';
3
+ export { refreshDevCache } from './cache-writer';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,cAAc,EACd,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { TokenVerifier } from 'canopycms/auth';
2
+ /**
3
+ * Creates a token verifier for dev auth.
4
+ * Extracts userId from X-Test-User header, x-dev-user-id header,
5
+ * or canopy-dev-user cookie — same logic as DevAuthPlugin.authenticate().
6
+ *
7
+ * Used with CachingAuthPlugin in prod-sim mode to simulate the prod
8
+ * code path (token verification + cached metadata lookup) using dev users.
9
+ */
10
+ export declare function createDevTokenVerifier(options?: {
11
+ defaultUserId?: string;
12
+ }): TokenVerifier;