better-auth-studio 1.0.5 → 1.0.7
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.
- package/package.json +8 -1
- package/frontend/index.html +0 -13
- package/frontend/package-lock.json +0 -4675
- package/frontend/package.json +0 -52
- package/frontend/pnpm-lock.yaml +0 -4020
- package/frontend/postcss.config.js +0 -6
- package/frontend/src/App.tsx +0 -36
- package/frontend/src/components/CommandPalette.tsx +0 -219
- package/frontend/src/components/Layout.tsx +0 -159
- package/frontend/src/components/ui/badge.tsx +0 -40
- package/frontend/src/components/ui/button.tsx +0 -53
- package/frontend/src/components/ui/card.tsx +0 -78
- package/frontend/src/components/ui/input.tsx +0 -20
- package/frontend/src/components/ui/label.tsx +0 -19
- package/frontend/src/components/ui/select.tsx +0 -71
- package/frontend/src/index.css +0 -130
- package/frontend/src/lib/utils.ts +0 -6
- package/frontend/src/main.tsx +0 -10
- package/frontend/src/pages/Dashboard.tsx +0 -231
- package/frontend/src/pages/OrganizationDetails.tsx +0 -1281
- package/frontend/src/pages/Organizations.tsx +0 -874
- package/frontend/src/pages/Sessions.tsx +0 -623
- package/frontend/src/pages/Settings.tsx +0 -1019
- package/frontend/src/pages/TeamDetails.tsx +0 -666
- package/frontend/src/pages/Users.tsx +0 -728
- package/frontend/tailwind.config.js +0 -75
- package/frontend/tsconfig.json +0 -31
- package/frontend/tsconfig.node.json +0 -10
- package/frontend/vite.config.ts +0 -31
- package/src/auth-adapter.ts +0 -473
- package/src/cli.ts +0 -51
- package/src/config.ts +0 -320
- package/src/data.ts +0 -351
- package/src/routes.ts +0 -1585
- package/src/studio.ts +0 -86
- package/test-project/README.md +0 -0
- package/test-project/better-auth.db +0 -0
- package/test-project/better-auth_migrations/2025-08-27T15-55-04.099Z.sql +0 -7
- package/test-project/better-auth_migrations/2025-09-04T02-33-19.422Z.sql +0 -7
- package/test-project/package.json +0 -29
- package/test-project/pnpm-lock.yaml +0 -1728
- package/test-project/src/auth.ts +0 -47
- package/test-project/src/index.ts +0 -40
- package/tsconfig.json +0 -21
package/src/routes.ts
DELETED
|
@@ -1,1585 +0,0 @@
|
|
|
1
|
-
import { Router, Request, Response } from 'express';
|
|
2
|
-
import { getAuthData } from './data';
|
|
3
|
-
import { AuthConfig } from './config';
|
|
4
|
-
import { getAuthAdapter, createMockUser, createMockSession, createMockAccount, createMockVerification } from './auth-adapter';
|
|
5
|
-
|
|
6
|
-
async function findAuthConfigPath(): Promise<string | null> {
|
|
7
|
-
const { join, dirname } = await import('path');
|
|
8
|
-
const { existsSync } = await import('fs');
|
|
9
|
-
|
|
10
|
-
const possiblePaths = [
|
|
11
|
-
'src/auth.ts',
|
|
12
|
-
'src/auth.js',
|
|
13
|
-
'lib/auth.ts',
|
|
14
|
-
'lib/auth.js',
|
|
15
|
-
'auth.ts',
|
|
16
|
-
'auth.js'
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
for (const path of possiblePaths) {
|
|
20
|
-
if (existsSync(path)) {
|
|
21
|
-
return join(process.cwd(), path);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function createRoutes(authConfig: AuthConfig) {
|
|
29
|
-
const router = Router();
|
|
30
|
-
|
|
31
|
-
router.get('/api/health', (req: Request, res: Response) => {
|
|
32
|
-
const uptime = process.uptime();
|
|
33
|
-
const hours = Math.floor(uptime / 3600);
|
|
34
|
-
const minutes = Math.floor((uptime % 3600) / 60);
|
|
35
|
-
const seconds = Math.floor(uptime % 60);
|
|
36
|
-
|
|
37
|
-
res.json({
|
|
38
|
-
status: 'ok',
|
|
39
|
-
timestamp: new Date().toISOString(),
|
|
40
|
-
system: {
|
|
41
|
-
studioVersion: '1.0.0',
|
|
42
|
-
nodeVersion: process.version,
|
|
43
|
-
platform: process.platform,
|
|
44
|
-
arch: process.arch,
|
|
45
|
-
uptime: `${hours}h ${minutes}m ${seconds}s`,
|
|
46
|
-
memory: {
|
|
47
|
-
used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
|
|
48
|
-
total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
|
|
49
|
-
external: Math.round(process.memoryUsage().external / 1024 / 1024)
|
|
50
|
-
},
|
|
51
|
-
pid: process.pid,
|
|
52
|
-
cwd: process.cwd()
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
router.get('/api/config', (req: Request, res: Response) => {
|
|
58
|
-
console.log('Raw authConfig:', JSON.stringify(authConfig, null, 2));
|
|
59
|
-
|
|
60
|
-
const config = {
|
|
61
|
-
appName: authConfig.appName || 'Better Auth',
|
|
62
|
-
baseURL: authConfig.baseURL || process.env.BETTER_AUTH_URL,
|
|
63
|
-
basePath: authConfig.basePath || '/api/auth',
|
|
64
|
-
secret: authConfig.secret ? 'Configured' : 'Not set',
|
|
65
|
-
|
|
66
|
-
database: {
|
|
67
|
-
type: authConfig.database?.type || 'unknown',
|
|
68
|
-
dialect: authConfig.database?.dialect,
|
|
69
|
-
casing: authConfig.database?.casing || 'camel',
|
|
70
|
-
debugLogs: authConfig.database?.debugLogs || false,
|
|
71
|
-
url: authConfig.database?.url
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
emailVerification: {
|
|
75
|
-
sendOnSignUp: authConfig.emailVerification?.sendOnSignUp || false,
|
|
76
|
-
sendOnSignIn: authConfig.emailVerification?.sendOnSignIn || false,
|
|
77
|
-
autoSignInAfterVerification: authConfig.emailVerification?.autoSignInAfterVerification || false,
|
|
78
|
-
expiresIn: authConfig.emailVerification?.expiresIn || 3600
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
emailAndPassword: {
|
|
82
|
-
enabled: authConfig.emailAndPassword?.enabled ?? false,
|
|
83
|
-
disableSignUp: authConfig.emailAndPassword?.disableSignUp ?? false,
|
|
84
|
-
requireEmailVerification: authConfig.emailAndPassword?.requireEmailVerification ?? false,
|
|
85
|
-
maxPasswordLength: authConfig.emailAndPassword?.maxPasswordLength ?? 128,
|
|
86
|
-
minPasswordLength: authConfig.emailAndPassword?.minPasswordLength ?? 8,
|
|
87
|
-
resetPasswordTokenExpiresIn: authConfig.emailAndPassword?.resetPasswordTokenExpiresIn ?? 3600,
|
|
88
|
-
autoSignIn: authConfig.emailAndPassword?.autoSignIn ?? true, // defaults to true
|
|
89
|
-
revokeSessionsOnPasswordReset: authConfig.emailAndPassword?.revokeSessionsOnPasswordReset ?? false
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
socialProviders: authConfig.socialProviders ?
|
|
93
|
-
Object.entries(authConfig.socialProviders).map(([provider, config]: [string, any]) => ({
|
|
94
|
-
type: provider,
|
|
95
|
-
clientId: config.clientId,
|
|
96
|
-
clientSecret: config.clientSecret,
|
|
97
|
-
redirectUri: config.redirectUri,
|
|
98
|
-
...config
|
|
99
|
-
})) :
|
|
100
|
-
(authConfig.providers || []),
|
|
101
|
-
|
|
102
|
-
user: {
|
|
103
|
-
modelName: authConfig.user?.modelName || 'user',
|
|
104
|
-
changeEmail: {
|
|
105
|
-
enabled: authConfig.user?.changeEmail?.enabled || false
|
|
106
|
-
},
|
|
107
|
-
deleteUser: {
|
|
108
|
-
enabled: authConfig.user?.deleteUser?.enabled || false,
|
|
109
|
-
deleteTokenExpiresIn: authConfig.user?.deleteUser?.deleteTokenExpiresIn || 86400
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
session: {
|
|
114
|
-
modelName: authConfig.session?.modelName || 'session',
|
|
115
|
-
expiresIn: authConfig.session?.expiresIn || 604800, // 7 days
|
|
116
|
-
updateAge: authConfig.session?.updateAge || 86400, // 1 day
|
|
117
|
-
disableSessionRefresh: authConfig.session?.disableSessionRefresh || false,
|
|
118
|
-
storeSessionInDatabase: authConfig.session?.storeSessionInDatabase || false,
|
|
119
|
-
preserveSessionInDatabase: authConfig.session?.preserveSessionInDatabase || false,
|
|
120
|
-
cookieCache: {
|
|
121
|
-
enabled: authConfig.session?.cookieCache?.enabled || false,
|
|
122
|
-
maxAge: authConfig.session?.cookieCache?.maxAge || 300
|
|
123
|
-
},
|
|
124
|
-
freshAge: authConfig.session?.freshAge || 86400
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
account: {
|
|
128
|
-
modelName: authConfig.account?.modelName || 'account',
|
|
129
|
-
updateAccountOnSignIn: authConfig.account?.updateAccountOnSignIn !== false, // defaults to true
|
|
130
|
-
accountLinking: {
|
|
131
|
-
enabled: authConfig.account?.accountLinking?.enabled !== false, // defaults to true
|
|
132
|
-
trustedProviders: authConfig.account?.accountLinking?.trustedProviders || [],
|
|
133
|
-
allowDifferentEmails: authConfig.account?.accountLinking?.allowDifferentEmails || false,
|
|
134
|
-
allowUnlinkingAll: authConfig.account?.accountLinking?.allowUnlinkingAll || false,
|
|
135
|
-
updateUserInfoOnLink: authConfig.account?.accountLinking?.updateUserInfoOnLink || false
|
|
136
|
-
},
|
|
137
|
-
encryptOAuthTokens: authConfig.account?.encryptOAuthTokens || false
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
verification: {
|
|
141
|
-
modelName: authConfig.verification?.modelName || 'verification',
|
|
142
|
-
disableCleanup: authConfig.verification?.disableCleanup || false
|
|
143
|
-
},
|
|
144
|
-
|
|
145
|
-
trustedOrigins: Array.isArray(authConfig.trustedOrigins) ? authConfig.trustedOrigins : [],
|
|
146
|
-
|
|
147
|
-
rateLimit: {
|
|
148
|
-
enabled: authConfig.rateLimit?.enabled ?? false,
|
|
149
|
-
window: authConfig.rateLimit?.window || 10,
|
|
150
|
-
max: authConfig.rateLimit?.max || 100,
|
|
151
|
-
storage: authConfig.rateLimit?.storage || 'memory',
|
|
152
|
-
modelName: authConfig.rateLimit?.modelName || 'rateLimit'
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
advanced: {
|
|
156
|
-
ipAddress: {
|
|
157
|
-
ipAddressHeaders: authConfig.advanced?.ipAddress?.ipAddressHeaders || [],
|
|
158
|
-
disableIpTracking: authConfig.advanced?.ipAddress?.disableIpTracking || false
|
|
159
|
-
},
|
|
160
|
-
useSecureCookies: authConfig.advanced?.useSecureCookies || false,
|
|
161
|
-
disableCSRFCheck: authConfig.advanced?.disableCSRFCheck || false,
|
|
162
|
-
crossSubDomainCookies: {
|
|
163
|
-
enabled: authConfig.advanced?.crossSubDomainCookies?.enabled || false,
|
|
164
|
-
additionalCookies: authConfig.advanced?.crossSubDomainCookies?.additionalCookies || [],
|
|
165
|
-
domain: authConfig.advanced?.crossSubDomainCookies?.domain
|
|
166
|
-
},
|
|
167
|
-
cookies: authConfig.advanced?.cookies || {},
|
|
168
|
-
defaultCookieAttributes: authConfig.advanced?.defaultCookieAttributes || {},
|
|
169
|
-
cookiePrefix: authConfig.advanced?.cookiePrefix,
|
|
170
|
-
database: {
|
|
171
|
-
defaultFindManyLimit: authConfig.advanced?.database?.defaultFindManyLimit || 100,
|
|
172
|
-
useNumberId: authConfig.advanced?.database?.useNumberId || false
|
|
173
|
-
}
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
disabledPaths: authConfig.disabledPaths || [],
|
|
177
|
-
|
|
178
|
-
telemetry: {
|
|
179
|
-
enabled: authConfig.telemetry?.enabled ?? false,
|
|
180
|
-
debug: authConfig.telemetry?.debug || false
|
|
181
|
-
},
|
|
182
|
-
|
|
183
|
-
studio: {
|
|
184
|
-
version: '1.0.0',
|
|
185
|
-
nodeVersion: process.version,
|
|
186
|
-
platform: process.platform,
|
|
187
|
-
uptime: process.uptime()
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
console.log('Processed config:', JSON.stringify(config, null, 2));
|
|
192
|
-
res.json(config);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
router.get('/api/stats', async (req: Request, res: Response) => {
|
|
196
|
-
try {
|
|
197
|
-
const stats = await getAuthData(authConfig, 'stats');
|
|
198
|
-
res.json(stats);
|
|
199
|
-
} catch (error) {
|
|
200
|
-
console.error('Error fetching stats:', error);
|
|
201
|
-
res.status(500).json({ error: 'Failed to fetch statistics' });
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
router.get('/api/counts', async (req: Request, res: Response) => {
|
|
206
|
-
try {
|
|
207
|
-
const adapter = await getAuthAdapter();
|
|
208
|
-
let userCount = 0;
|
|
209
|
-
let sessionCount = 0;
|
|
210
|
-
let organizationCount = 0;
|
|
211
|
-
|
|
212
|
-
if (adapter) {
|
|
213
|
-
try {
|
|
214
|
-
if (typeof adapter.findMany === 'function') {
|
|
215
|
-
const users = await adapter.findMany({ model: 'user', limit: 10000 });
|
|
216
|
-
userCount = users?.length || 0;
|
|
217
|
-
}
|
|
218
|
-
} catch (error) {
|
|
219
|
-
console.error('Error fetching user count:', error);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
try {
|
|
223
|
-
if (typeof adapter.findMany === 'function') {
|
|
224
|
-
const sessions = await adapter.findMany({ model: 'session', limit: 10000 });
|
|
225
|
-
sessionCount = sessions?.length || 0;
|
|
226
|
-
}
|
|
227
|
-
} catch (error) {
|
|
228
|
-
console.error('Error fetching session count:', error);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
if (typeof adapter.findMany === 'function') {
|
|
233
|
-
const organizations = await adapter.findMany({ model: 'organization', limit: 10000 });
|
|
234
|
-
organizationCount = organizations?.length || 0;
|
|
235
|
-
}
|
|
236
|
-
} catch (error) {
|
|
237
|
-
console.error('Error fetching organization count:', error);
|
|
238
|
-
organizationCount = 0;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
res.json({
|
|
243
|
-
users: userCount,
|
|
244
|
-
sessions: sessionCount,
|
|
245
|
-
organizations: organizationCount
|
|
246
|
-
});
|
|
247
|
-
} catch (error) {
|
|
248
|
-
console.error('Error fetching counts:', error);
|
|
249
|
-
res.status(500).json({ error: 'Failed to fetch counts' });
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
router.get('/api/users', async (req: Request, res: Response) => {
|
|
253
|
-
try {
|
|
254
|
-
const page = parseInt(req.query.page as string) || 1;
|
|
255
|
-
const limit = parseInt(req.query.limit as string) || 20;
|
|
256
|
-
const search = req.query.search as string;
|
|
257
|
-
try {
|
|
258
|
-
const adapter = await getAuthAdapter();
|
|
259
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
260
|
-
const allUsers = await adapter.findMany({ model: 'user', limit: limit });
|
|
261
|
-
console.log('Found users via findMany:', allUsers?.length || 0);
|
|
262
|
-
|
|
263
|
-
let filteredUsers = allUsers || [];
|
|
264
|
-
if (search) {
|
|
265
|
-
filteredUsers = filteredUsers.filter((user: any) =>
|
|
266
|
-
user.email?.toLowerCase().includes(search.toLowerCase()) ||
|
|
267
|
-
user.name?.toLowerCase().includes(search.toLowerCase())
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const startIndex = (page - 1) * limit;
|
|
272
|
-
const endIndex = startIndex + limit;
|
|
273
|
-
const paginatedUsers = filteredUsers.slice(startIndex, endIndex);
|
|
274
|
-
|
|
275
|
-
const transformedUsers = paginatedUsers.map((user: any) => ({
|
|
276
|
-
id: user.id,
|
|
277
|
-
email: user.email,
|
|
278
|
-
name: user.name,
|
|
279
|
-
image: user.image,
|
|
280
|
-
emailVerified: user.emailVerified,
|
|
281
|
-
createdAt: user.createdAt,
|
|
282
|
-
updatedAt: user.updatedAt,
|
|
283
|
-
}));
|
|
284
|
-
|
|
285
|
-
res.json({ users: transformedUsers });
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
} catch (adapterError) {
|
|
289
|
-
console.error('Error fetching users from adapter:', adapterError);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const result = await getAuthData(authConfig, 'users', { page, limit, search });
|
|
293
|
-
|
|
294
|
-
const transformedUsers = (result.data || []).map((user: any) => ({
|
|
295
|
-
id: user.id,
|
|
296
|
-
email: user.email,
|
|
297
|
-
name: user.name,
|
|
298
|
-
image: user.image,
|
|
299
|
-
emailVerified: user.emailVerified,
|
|
300
|
-
createdAt: user.createdAt,
|
|
301
|
-
updatedAt: user.updatedAt,
|
|
302
|
-
}));
|
|
303
|
-
|
|
304
|
-
res.json({ users: transformedUsers });
|
|
305
|
-
} catch (error) {
|
|
306
|
-
console.error('Error fetching users:', error);
|
|
307
|
-
res.status(500).json({ error: 'Failed to fetch users' });
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
router.get('/api/sessions', async (req: Request, res: Response) => {
|
|
312
|
-
try {
|
|
313
|
-
const page = parseInt(req.query.page as string) || 1;
|
|
314
|
-
const limit = parseInt(req.query.limit as string) || 20;
|
|
315
|
-
|
|
316
|
-
const sessions = await getAuthData(authConfig, 'sessions', { page, limit });
|
|
317
|
-
res.json(sessions);
|
|
318
|
-
} catch (error) {
|
|
319
|
-
console.error('Error fetching sessions:', error);
|
|
320
|
-
res.status(500).json({ error: 'Failed to fetch sessions' });
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
router.get('/api/providers', async (req: Request, res: Response) => {
|
|
325
|
-
try {
|
|
326
|
-
const providers = await getAuthData(authConfig, 'providers');
|
|
327
|
-
res.json(providers);
|
|
328
|
-
} catch (error) {
|
|
329
|
-
console.error('Error fetching providers:', error);
|
|
330
|
-
res.status(500).json({ error: 'Failed to fetch providers' });
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
router.delete('/api/users/:id', async (req: Request, res: Response) => {
|
|
335
|
-
try {
|
|
336
|
-
const { id } = req.params;
|
|
337
|
-
await getAuthData(authConfig, 'deleteUser', { id });
|
|
338
|
-
res.json({ success: true });
|
|
339
|
-
} catch (error) {
|
|
340
|
-
console.error('Error deleting user:', error);
|
|
341
|
-
res.status(500).json({ error: 'Failed to delete user' });
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
router.get('/api/plugins', async (req: Request, res: Response) => {
|
|
346
|
-
try {
|
|
347
|
-
const authConfigPath = await findAuthConfigPath();
|
|
348
|
-
if (!authConfigPath) {
|
|
349
|
-
return res.json({
|
|
350
|
-
plugins: [],
|
|
351
|
-
error: 'No auth config found',
|
|
352
|
-
configPath: null
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
try {
|
|
357
|
-
const authModule = await import(authConfigPath);
|
|
358
|
-
const auth = authModule.auth || authModule.default;
|
|
359
|
-
|
|
360
|
-
if (!auth) {
|
|
361
|
-
return res.json({
|
|
362
|
-
plugins: [],
|
|
363
|
-
error: 'No auth export found',
|
|
364
|
-
configPath: authConfigPath
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const plugins = auth.options?.plugins || [];
|
|
369
|
-
const pluginInfo = plugins.map((plugin: any) => ({
|
|
370
|
-
id: plugin.id,
|
|
371
|
-
name: plugin.name || plugin.id,
|
|
372
|
-
version: plugin.version || 'unknown',
|
|
373
|
-
description: plugin.description || `${plugin.id} plugin for Better Auth`,
|
|
374
|
-
enabled: true
|
|
375
|
-
}));
|
|
376
|
-
|
|
377
|
-
res.json({
|
|
378
|
-
plugins: pluginInfo,
|
|
379
|
-
configPath: authConfigPath,
|
|
380
|
-
totalPlugins: pluginInfo.length
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
} catch (error) {
|
|
384
|
-
console.error('Error getting plugins:', error);
|
|
385
|
-
res.json({
|
|
386
|
-
plugins: [],
|
|
387
|
-
error: 'Failed to load auth config',
|
|
388
|
-
configPath: authConfigPath
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
} catch (error) {
|
|
392
|
-
console.error('Error fetching plugins:', error);
|
|
393
|
-
res.status(500).json({ error: 'Failed to fetch plugins' });
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
router.get('/api/plugins/teams/status', async (req: Request, res: Response) => {
|
|
398
|
-
try {
|
|
399
|
-
const authConfigPath = await findAuthConfigPath();
|
|
400
|
-
if (!authConfigPath) {
|
|
401
|
-
return res.json({
|
|
402
|
-
enabled: false,
|
|
403
|
-
error: 'No auth config found',
|
|
404
|
-
configPath: null
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
try {
|
|
409
|
-
const authModule = await import(authConfigPath);
|
|
410
|
-
const auth = authModule.auth || authModule.default;
|
|
411
|
-
|
|
412
|
-
if (!auth) {
|
|
413
|
-
return res.json({
|
|
414
|
-
enabled: false,
|
|
415
|
-
error: 'No auth export found',
|
|
416
|
-
configPath: authConfigPath
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const organizationPlugin = auth.options?.plugins?.find((plugin: any) =>
|
|
421
|
-
plugin.id === "organization"
|
|
422
|
-
);
|
|
423
|
-
|
|
424
|
-
const teamsEnabled = organizationPlugin?.teams?.enabled === true;
|
|
425
|
-
|
|
426
|
-
res.json({
|
|
427
|
-
enabled: teamsEnabled,
|
|
428
|
-
configPath: authConfigPath,
|
|
429
|
-
organizationPlugin: organizationPlugin || null
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
} catch (error) {
|
|
433
|
-
console.error('Error checking teams plugin:', error);
|
|
434
|
-
res.json({
|
|
435
|
-
enabled: false,
|
|
436
|
-
error: 'Failed to load auth config',
|
|
437
|
-
configPath: authConfigPath
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
} catch (error) {
|
|
441
|
-
console.error('Error checking teams status:', error);
|
|
442
|
-
res.status(500).json({ error: 'Failed to check teams status' });
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
router.get('/api/organizations/:orgId/invitations', async (req: Request, res: Response) => {
|
|
447
|
-
try {
|
|
448
|
-
console.log('fetching invitations' , req.params)
|
|
449
|
-
const { orgId } = req.params;
|
|
450
|
-
const adapter = await getAuthAdapter();
|
|
451
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
452
|
-
try {
|
|
453
|
-
const invitations = await adapter.findMany({
|
|
454
|
-
model: 'invitation',
|
|
455
|
-
where: [
|
|
456
|
-
{ field: 'organizationId', value: orgId },
|
|
457
|
-
{ field: 'status', value: 'pending' }
|
|
458
|
-
],
|
|
459
|
-
});
|
|
460
|
-
const transformedInvitations = (invitations || []).map((invitation: any) => ({
|
|
461
|
-
id: invitation.id,
|
|
462
|
-
email: invitation.email,
|
|
463
|
-
role: invitation.role || 'member',
|
|
464
|
-
status: invitation.status || 'pending',
|
|
465
|
-
organizationId: invitation.organizationId,
|
|
466
|
-
teamId: invitation.teamId,
|
|
467
|
-
inviterId: invitation.inviterId,
|
|
468
|
-
expiresAt: invitation.expiresAt,
|
|
469
|
-
createdAt: invitation.createdAt
|
|
470
|
-
}));
|
|
471
|
-
res.json({ success: true, invitations: transformedInvitations });
|
|
472
|
-
return;
|
|
473
|
-
} catch (error) {
|
|
474
|
-
console.error('Error fetching invitations from adapter:', error);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
res.json({ success: true, invitations: [] });
|
|
479
|
-
} catch (error) {
|
|
480
|
-
console.error('Error fetching invitations:', error);
|
|
481
|
-
res.status(500).json({ error: 'Failed to fetch invitations' });
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
router.get('/api/organizations/:orgId/members', async (req: Request, res: Response) => {
|
|
486
|
-
try {
|
|
487
|
-
const { orgId } = req.params;
|
|
488
|
-
const adapter = await getAuthAdapter();
|
|
489
|
-
|
|
490
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
491
|
-
try {
|
|
492
|
-
const members = await adapter.findMany({
|
|
493
|
-
model: 'member',
|
|
494
|
-
where: [{ field: 'organizationId', value: orgId }],
|
|
495
|
-
limit: 10000
|
|
496
|
-
});
|
|
497
|
-
const membersWithUsers = await Promise.all((members || []).map(async (member: any) => {
|
|
498
|
-
try {
|
|
499
|
-
if (adapter.findMany) {
|
|
500
|
-
const users = await adapter.findMany({
|
|
501
|
-
model: 'user',
|
|
502
|
-
where: [{ field: 'id', value: member.userId }],
|
|
503
|
-
limit: 1
|
|
504
|
-
});
|
|
505
|
-
const user = users?.[0];
|
|
506
|
-
return {
|
|
507
|
-
id: member.id,
|
|
508
|
-
userId: member.userId,
|
|
509
|
-
organizationId: member.organizationId,
|
|
510
|
-
role: member.role || 'member',
|
|
511
|
-
joinedAt: member.joinedAt || member.createdAt,
|
|
512
|
-
user: user ? {
|
|
513
|
-
id: user.id,
|
|
514
|
-
name: user.name,
|
|
515
|
-
email: user.email,
|
|
516
|
-
image: user.image,
|
|
517
|
-
emailVerified: user.emailVerified
|
|
518
|
-
} : null
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
return null;
|
|
522
|
-
} catch (error) {
|
|
523
|
-
console.error('Error fetching user for member:', error);
|
|
524
|
-
return null;
|
|
525
|
-
}
|
|
526
|
-
}));
|
|
527
|
-
|
|
528
|
-
const validMembers = membersWithUsers.filter(member => member && member.user);
|
|
529
|
-
|
|
530
|
-
res.json({ success: true, members: validMembers });
|
|
531
|
-
return;
|
|
532
|
-
} catch (error) {
|
|
533
|
-
console.error('Error fetching members from adapter:', error);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
res.json({ success: true, members: [] });
|
|
538
|
-
} catch (error) {
|
|
539
|
-
console.error('Error fetching members:', error);
|
|
540
|
-
res.status(500).json({ error: 'Failed to fetch members' });
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
router.post('/api/organizations/:orgId/seed-members', async (req: Request, res: Response) => {
|
|
545
|
-
try {
|
|
546
|
-
const { orgId } = req.params;
|
|
547
|
-
const { count = 5 } = req.body;
|
|
548
|
-
const adapter = await getAuthAdapter();
|
|
549
|
-
|
|
550
|
-
if (!adapter) {
|
|
551
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (!adapter.findMany || !adapter.create) {
|
|
555
|
-
return res.status(500).json({ error: 'Adapter findMany method not available' });
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
const generateRandomString = (length: number) => {
|
|
559
|
-
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
560
|
-
let result = '';
|
|
561
|
-
for (let i = 0; i < length; i++) {
|
|
562
|
-
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
563
|
-
}
|
|
564
|
-
return result;
|
|
565
|
-
};
|
|
566
|
-
|
|
567
|
-
const results = [];
|
|
568
|
-
|
|
569
|
-
for (let i = 0; i < count; i++) {
|
|
570
|
-
try {
|
|
571
|
-
const randomString = generateRandomString(8);
|
|
572
|
-
const email = `user${randomString}@example.com`;
|
|
573
|
-
const name = `User ${randomString}`;
|
|
574
|
-
|
|
575
|
-
const userData = {
|
|
576
|
-
name,
|
|
577
|
-
email,
|
|
578
|
-
emailVerified: false,
|
|
579
|
-
createdAt: new Date(),
|
|
580
|
-
updatedAt: new Date()
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
const user = await adapter.create({
|
|
584
|
-
model: 'user',
|
|
585
|
-
data: userData
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
const memberData = {
|
|
589
|
-
organizationId: orgId,
|
|
590
|
-
userId: user.id,
|
|
591
|
-
role: 'member',
|
|
592
|
-
createdAt: new Date()
|
|
593
|
-
};
|
|
594
|
-
|
|
595
|
-
await adapter.create({
|
|
596
|
-
model: 'member',
|
|
597
|
-
data: memberData
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
results.push({
|
|
601
|
-
success: true,
|
|
602
|
-
member: {
|
|
603
|
-
userId: user.id,
|
|
604
|
-
user: {
|
|
605
|
-
name,
|
|
606
|
-
email
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
});
|
|
610
|
-
} catch (error) {
|
|
611
|
-
results.push({
|
|
612
|
-
success: false,
|
|
613
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
614
|
-
});
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
res.json({
|
|
619
|
-
success: true,
|
|
620
|
-
message: `Added ${results.filter(r => r.success).length} members`,
|
|
621
|
-
results
|
|
622
|
-
});
|
|
623
|
-
} catch (error) {
|
|
624
|
-
console.error('Error seeding members:', error);
|
|
625
|
-
res.status(500).json({ error: 'Failed to seed members' });
|
|
626
|
-
}
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
router.delete('/api/members/:id', async (req: Request, res: Response) => {
|
|
630
|
-
try {
|
|
631
|
-
const { id } = req.params;
|
|
632
|
-
const adapter = await getAuthAdapter();
|
|
633
|
-
|
|
634
|
-
if (!adapter) {
|
|
635
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
if (!adapter.delete) {
|
|
639
|
-
return res.status(500).json({ error: 'Adapter delete method not available' });
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
await adapter.delete({
|
|
643
|
-
model: 'member',
|
|
644
|
-
where: [{ field: 'id', value: id }]
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
res.json({ success: true });
|
|
648
|
-
} catch (error) {
|
|
649
|
-
console.error('Error removing member:', error);
|
|
650
|
-
res.status(500).json({ error: 'Failed to remove member' });
|
|
651
|
-
}
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
router.post('/api/invitations/:id/resend', async (req: Request, res: Response) => {
|
|
655
|
-
try {
|
|
656
|
-
const { id } = req.params;
|
|
657
|
-
const adapter = await getAuthAdapter();
|
|
658
|
-
|
|
659
|
-
if (!adapter) {
|
|
660
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
if (!adapter.update) {
|
|
664
|
-
return res.status(500).json({ error: 'Adapter update method not available' });
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
await adapter.update({
|
|
668
|
-
model: 'invitation',
|
|
669
|
-
where: [{ field: 'id', value: id }],
|
|
670
|
-
update: {
|
|
671
|
-
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days from now
|
|
672
|
-
updatedAt: new Date().toISOString()
|
|
673
|
-
}
|
|
674
|
-
});
|
|
675
|
-
|
|
676
|
-
res.json({ success: true });
|
|
677
|
-
} catch (error) {
|
|
678
|
-
console.error('Error resending invitation:', error);
|
|
679
|
-
res.status(500).json({ error: 'Failed to resend invitation' });
|
|
680
|
-
}
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
router.delete('/api/invitations/:id', async (req: Request, res: Response) => {
|
|
684
|
-
try {
|
|
685
|
-
const { id } = req.params;
|
|
686
|
-
const adapter = await getAuthAdapter();
|
|
687
|
-
|
|
688
|
-
if (!adapter) {
|
|
689
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
if (!adapter.update) {
|
|
693
|
-
return res.status(500).json({ error: 'Adapter update method not available' });
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
await adapter.update({
|
|
697
|
-
model: 'invitation',
|
|
698
|
-
where: [{ field: 'id', value: id }],
|
|
699
|
-
update: {
|
|
700
|
-
status: 'cancelled',
|
|
701
|
-
updatedAt: new Date().toISOString()
|
|
702
|
-
}
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
res.json({ success: true });
|
|
706
|
-
} catch (error) {
|
|
707
|
-
console.error('Error cancelling invitation:', error);
|
|
708
|
-
res.status(500).json({ error: 'Failed to cancel invitation' });
|
|
709
|
-
}
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
router.post('/api/organizations/:orgId/invitations', async (req: Request, res: Response) => {
|
|
713
|
-
try {
|
|
714
|
-
const { orgId } = req.params;
|
|
715
|
-
const { email, role = 'member' } = req.body;
|
|
716
|
-
|
|
717
|
-
const adapter = await getAuthAdapter();
|
|
718
|
-
if (!adapter) {
|
|
719
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
const invitationData = {
|
|
723
|
-
email,
|
|
724
|
-
role,
|
|
725
|
-
organizationId: orgId,
|
|
726
|
-
status: 'pending',
|
|
727
|
-
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
|
|
728
|
-
createdAt: new Date(),
|
|
729
|
-
inviterId: 'admin' // In real app, get from session
|
|
730
|
-
};
|
|
731
|
-
|
|
732
|
-
const invitation = {
|
|
733
|
-
id: `inv_${Date.now()}`,
|
|
734
|
-
...invitationData
|
|
735
|
-
};
|
|
736
|
-
if(!adapter.create) {
|
|
737
|
-
return res.status(500).json({ error: 'Adapter create method not available' });
|
|
738
|
-
}
|
|
739
|
-
const adminId = "dQ2aAFgMwmRKvoqLiM1MCbjbka5g1Nzc"
|
|
740
|
-
await adapter.create({
|
|
741
|
-
model: 'invitation',
|
|
742
|
-
data: {
|
|
743
|
-
organizationId: invitationData.organizationId,
|
|
744
|
-
email: invitationData.email,
|
|
745
|
-
role: invitationData.role,
|
|
746
|
-
status: invitationData.status,
|
|
747
|
-
inviterId: adminId,
|
|
748
|
-
expiresAt: invitationData.expiresAt,
|
|
749
|
-
createdAt: invitationData.createdAt,
|
|
750
|
-
}
|
|
751
|
-
});
|
|
752
|
-
|
|
753
|
-
res.json({ success: true, invitation });
|
|
754
|
-
} catch (error) {
|
|
755
|
-
console.error('Error creating invitation:', error);
|
|
756
|
-
res.status(500).json({ error: 'Failed to create invitation' });
|
|
757
|
-
}
|
|
758
|
-
});
|
|
759
|
-
|
|
760
|
-
router.get('/api/organizations/:orgId/teams', async (req: Request, res: Response) => {
|
|
761
|
-
try {
|
|
762
|
-
const { orgId } = req.params;
|
|
763
|
-
const adapter = await getAuthAdapter();
|
|
764
|
-
|
|
765
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
766
|
-
try {
|
|
767
|
-
const teams = await adapter.findMany({
|
|
768
|
-
model: 'team',
|
|
769
|
-
where: [{ field: 'organizationId', value: orgId }],
|
|
770
|
-
limit: 10000
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
const transformedTeams = await Promise.all((teams || []).map(async (team: any) => {
|
|
774
|
-
if(!adapter.findMany) {
|
|
775
|
-
return null
|
|
776
|
-
}
|
|
777
|
-
const teamMembers = await adapter.findMany({
|
|
778
|
-
model: 'teamMember',
|
|
779
|
-
where: [{ field: 'teamId', value: team.id }],
|
|
780
|
-
limit: 10000
|
|
781
|
-
});
|
|
782
|
-
|
|
783
|
-
return {
|
|
784
|
-
id: team.id,
|
|
785
|
-
name: team.name,
|
|
786
|
-
organizationId: team.organizationId,
|
|
787
|
-
metadata: team.metadata,
|
|
788
|
-
createdAt: team.createdAt,
|
|
789
|
-
updatedAt: team.updatedAt,
|
|
790
|
-
memberCount: teamMembers ? teamMembers.length : 0
|
|
791
|
-
};
|
|
792
|
-
}));
|
|
793
|
-
|
|
794
|
-
res.json({ success: true, teams: transformedTeams });
|
|
795
|
-
return;
|
|
796
|
-
} catch (error) {
|
|
797
|
-
console.error('Error fetching teams from adapter:', error);
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
res.json({ success: true, teams: [] });
|
|
802
|
-
} catch (error) {
|
|
803
|
-
console.error('Error fetching teams:', error);
|
|
804
|
-
res.status(500).json({ error: 'Failed to fetch teams' });
|
|
805
|
-
}
|
|
806
|
-
});
|
|
807
|
-
|
|
808
|
-
router.post('/api/organizations/:orgId/teams', async (req: Request, res: Response) => {
|
|
809
|
-
try {
|
|
810
|
-
const { orgId } = req.params;
|
|
811
|
-
const { name } = req.body;
|
|
812
|
-
|
|
813
|
-
const adapter = await getAuthAdapter();
|
|
814
|
-
if (!adapter) {
|
|
815
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
const teamData = {
|
|
819
|
-
name,
|
|
820
|
-
organizationId: orgId,
|
|
821
|
-
createdAt: new Date(),
|
|
822
|
-
updatedAt: new Date(),
|
|
823
|
-
memberCount: 0
|
|
824
|
-
};
|
|
825
|
-
|
|
826
|
-
const team = {
|
|
827
|
-
id: `team_${Date.now()}`,
|
|
828
|
-
...teamData
|
|
829
|
-
};
|
|
830
|
-
if(!adapter.create) {
|
|
831
|
-
return res.status(500).json({ error: 'Adapter create method not available' });
|
|
832
|
-
}
|
|
833
|
-
await adapter.create({
|
|
834
|
-
model: 'team',
|
|
835
|
-
data: {
|
|
836
|
-
name: teamData.name,
|
|
837
|
-
organizationId: teamData.organizationId,
|
|
838
|
-
createdAt: teamData.createdAt,
|
|
839
|
-
updatedAt: teamData.updatedAt,
|
|
840
|
-
}
|
|
841
|
-
});
|
|
842
|
-
res.json({ success: true, team });
|
|
843
|
-
} catch (error) {
|
|
844
|
-
console.error('Error creating team:', error);
|
|
845
|
-
res.status(500).json({ error: 'Failed to create team' });
|
|
846
|
-
}
|
|
847
|
-
});
|
|
848
|
-
|
|
849
|
-
router.get('/api/teams/:id', async (req: Request, res: Response) => {
|
|
850
|
-
try {
|
|
851
|
-
const { id } = req.params;
|
|
852
|
-
const adapter = await getAuthAdapter();
|
|
853
|
-
|
|
854
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
855
|
-
try {
|
|
856
|
-
const teams = await adapter.findMany({
|
|
857
|
-
model: 'team',
|
|
858
|
-
where: [{ field: 'id', value: id }],
|
|
859
|
-
limit: 1
|
|
860
|
-
});
|
|
861
|
-
|
|
862
|
-
const team = teams?.[0];
|
|
863
|
-
if (team) {
|
|
864
|
-
let organization = null;
|
|
865
|
-
try {
|
|
866
|
-
const orgs = await adapter.findMany({
|
|
867
|
-
model: 'organization',
|
|
868
|
-
where: [{ field: 'id', value: team.organizationId }],
|
|
869
|
-
limit: 1
|
|
870
|
-
});
|
|
871
|
-
organization = orgs?.[0];
|
|
872
|
-
} catch (error) {
|
|
873
|
-
console.error('Error fetching organization for team:', error);
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
const transformedTeam = {
|
|
877
|
-
id: team.id,
|
|
878
|
-
name: team.name,
|
|
879
|
-
organizationId: team.organizationId,
|
|
880
|
-
metadata: team.metadata,
|
|
881
|
-
createdAt: team.createdAt,
|
|
882
|
-
updatedAt: team.updatedAt,
|
|
883
|
-
memberCount: team.memberCount || 0,
|
|
884
|
-
organization: organization ? {
|
|
885
|
-
id: organization.id,
|
|
886
|
-
name: organization.name
|
|
887
|
-
} : null
|
|
888
|
-
};
|
|
889
|
-
|
|
890
|
-
res.json({ success: true, team: transformedTeam });
|
|
891
|
-
return;
|
|
892
|
-
}
|
|
893
|
-
} catch (error) {
|
|
894
|
-
console.error('Error fetching team from adapter:', error);
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
res.status(404).json({ success: false, error: 'Team not found' });
|
|
899
|
-
} catch (error) {
|
|
900
|
-
console.error('Error fetching team:', error);
|
|
901
|
-
res.status(500).json({ error: 'Failed to fetch team' });
|
|
902
|
-
}
|
|
903
|
-
});
|
|
904
|
-
|
|
905
|
-
router.get('/api/teams/:teamId/members', async (req: Request, res: Response) => {
|
|
906
|
-
try {
|
|
907
|
-
const { teamId } = req.params;
|
|
908
|
-
const adapter = await getAuthAdapter();
|
|
909
|
-
|
|
910
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
911
|
-
try {
|
|
912
|
-
const teamMembers = await adapter.findMany({
|
|
913
|
-
model: 'teamMember',
|
|
914
|
-
where: [{ field: 'teamId', value: teamId }],
|
|
915
|
-
limit: 10000
|
|
916
|
-
});
|
|
917
|
-
|
|
918
|
-
const membersWithUsers = await Promise.all((teamMembers || []).map(async (member: any) => {
|
|
919
|
-
try {
|
|
920
|
-
if (adapter.findMany) {
|
|
921
|
-
const users = await adapter.findMany({
|
|
922
|
-
model: 'user',
|
|
923
|
-
where: [{ field: 'id', value: member.userId }],
|
|
924
|
-
limit: 1
|
|
925
|
-
});
|
|
926
|
-
const user = users?.[0];
|
|
927
|
-
|
|
928
|
-
return {
|
|
929
|
-
id: member.id,
|
|
930
|
-
userId: member.userId,
|
|
931
|
-
teamId: member.teamId,
|
|
932
|
-
role: member.role || 'member',
|
|
933
|
-
joinedAt: member.joinedAt || member.createdAt,
|
|
934
|
-
user: user ? {
|
|
935
|
-
id: user.id,
|
|
936
|
-
name: user.name,
|
|
937
|
-
email: user.email,
|
|
938
|
-
image: user.image,
|
|
939
|
-
emailVerified: user.emailVerified
|
|
940
|
-
} : null
|
|
941
|
-
};
|
|
942
|
-
}
|
|
943
|
-
return null;
|
|
944
|
-
} catch (error) {
|
|
945
|
-
console.error('Error fetching user for team member:', error);
|
|
946
|
-
return null;
|
|
947
|
-
}
|
|
948
|
-
}));
|
|
949
|
-
|
|
950
|
-
const validMembers = membersWithUsers.filter(member => member && member.user);
|
|
951
|
-
|
|
952
|
-
res.json({ success: true, members: validMembers });
|
|
953
|
-
return;
|
|
954
|
-
} catch (error) {
|
|
955
|
-
console.error('Error fetching team members from adapter:', error);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
res.json({ success: true, members: [] });
|
|
960
|
-
} catch (error) {
|
|
961
|
-
console.error('Error fetching team members:', error);
|
|
962
|
-
res.status(500).json({ error: 'Failed to fetch team members' });
|
|
963
|
-
}
|
|
964
|
-
});
|
|
965
|
-
|
|
966
|
-
router.post('/api/teams/:teamId/members', async (req: Request, res: Response) => {
|
|
967
|
-
try {
|
|
968
|
-
const { teamId } = req.params;
|
|
969
|
-
const { userIds } = req.body;
|
|
970
|
-
|
|
971
|
-
if (!Array.isArray(userIds) || userIds.length === 0) {
|
|
972
|
-
return res.status(400).json({ error: 'userIds array is required' });
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
const adapter = await getAuthAdapter();
|
|
976
|
-
if (!adapter || !adapter.create) {
|
|
977
|
-
return res.status(500).json({ error: 'Adapter not available' });
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
const results = [];
|
|
981
|
-
for (const userId of userIds) {
|
|
982
|
-
try {
|
|
983
|
-
await adapter.create({
|
|
984
|
-
model: 'teamMember',
|
|
985
|
-
data: {
|
|
986
|
-
teamId,
|
|
987
|
-
userId,
|
|
988
|
-
role: 'member',
|
|
989
|
-
createdAt: new Date()
|
|
990
|
-
}
|
|
991
|
-
});
|
|
992
|
-
|
|
993
|
-
results.push({ success: true, userId });
|
|
994
|
-
} catch (error) {
|
|
995
|
-
results.push({
|
|
996
|
-
success: false,
|
|
997
|
-
userId,
|
|
998
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
999
|
-
});
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
res.json({
|
|
1004
|
-
success: true,
|
|
1005
|
-
message: `Added ${results.filter(r => r.success).length} members`,
|
|
1006
|
-
results
|
|
1007
|
-
});
|
|
1008
|
-
} catch (error) {
|
|
1009
|
-
console.error('Error adding team members:', error);
|
|
1010
|
-
res.status(500).json({ error: 'Failed to add team members' });
|
|
1011
|
-
}
|
|
1012
|
-
});
|
|
1013
|
-
|
|
1014
|
-
router.delete('/api/team-members/:id', async (req: Request, res: Response) => {
|
|
1015
|
-
try {
|
|
1016
|
-
const { id } = req.params;
|
|
1017
|
-
const adapter = await getAuthAdapter();
|
|
1018
|
-
|
|
1019
|
-
if (!adapter || !adapter.delete) {
|
|
1020
|
-
return res.status(500).json({ error: 'Adapter not available' });
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
await adapter.delete({
|
|
1024
|
-
model: 'teamMember',
|
|
1025
|
-
where: [{ field: 'id', value: id }]
|
|
1026
|
-
});
|
|
1027
|
-
|
|
1028
|
-
res.json({ success: true });
|
|
1029
|
-
} catch (error) {
|
|
1030
|
-
console.error('Error removing team member:', error);
|
|
1031
|
-
res.status(500).json({ error: 'Failed to remove team member' });
|
|
1032
|
-
}
|
|
1033
|
-
});
|
|
1034
|
-
|
|
1035
|
-
router.put('/api/teams/:id', async (req: Request, res: Response) => {
|
|
1036
|
-
try {
|
|
1037
|
-
const { id } = req.params;
|
|
1038
|
-
const { name } = req.body;
|
|
1039
|
-
const adapter = await getAuthAdapter();
|
|
1040
|
-
if(!adapter) {
|
|
1041
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1042
|
-
}
|
|
1043
|
-
const updatedTeam = {
|
|
1044
|
-
id,
|
|
1045
|
-
name,
|
|
1046
|
-
updatedAt: new Date().toISOString()
|
|
1047
|
-
};
|
|
1048
|
-
if(!adapter.update) {
|
|
1049
|
-
return res.status(500).json({ error: 'Adapter update method not available' });
|
|
1050
|
-
}
|
|
1051
|
-
await adapter.update({
|
|
1052
|
-
model: 'team',
|
|
1053
|
-
where: [{ field: 'id', value: id }],
|
|
1054
|
-
update: {
|
|
1055
|
-
name: updatedTeam.name,
|
|
1056
|
-
updatedAt: updatedTeam.updatedAt
|
|
1057
|
-
}
|
|
1058
|
-
});
|
|
1059
|
-
res.json({ success: true, team: updatedTeam });
|
|
1060
|
-
} catch (error) {
|
|
1061
|
-
console.error('Error updating team:', error);
|
|
1062
|
-
res.status(500).json({ error: 'Failed to update team' });
|
|
1063
|
-
}
|
|
1064
|
-
});
|
|
1065
|
-
|
|
1066
|
-
router.delete('/api/teams/:id', async (req: Request, res: Response) => {
|
|
1067
|
-
try {
|
|
1068
|
-
const { id } = req.params;
|
|
1069
|
-
const adapter = await getAuthAdapter();
|
|
1070
|
-
if(!adapter) {
|
|
1071
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1072
|
-
}
|
|
1073
|
-
if(!adapter.delete) {
|
|
1074
|
-
return res.status(500).json({ error: 'Adapter delete method not available' });
|
|
1075
|
-
}
|
|
1076
|
-
await adapter.delete({
|
|
1077
|
-
model: 'team',
|
|
1078
|
-
where: [{ field: 'id', value: id }],
|
|
1079
|
-
});
|
|
1080
|
-
res.json({ success: true });
|
|
1081
|
-
} catch (error) {
|
|
1082
|
-
console.error('Error deleting team:', error);
|
|
1083
|
-
res.status(500).json({ error: 'Failed to delete team' });
|
|
1084
|
-
}
|
|
1085
|
-
});
|
|
1086
|
-
|
|
1087
|
-
router.get('/api/plugins/organization/status', async (req: Request, res: Response) => {
|
|
1088
|
-
try {
|
|
1089
|
-
const authConfigPath = await findAuthConfigPath();
|
|
1090
|
-
if (!authConfigPath) {
|
|
1091
|
-
return res.json({
|
|
1092
|
-
enabled: false,
|
|
1093
|
-
error: 'No auth config found',
|
|
1094
|
-
configPath: null
|
|
1095
|
-
});
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
try {
|
|
1099
|
-
const authModule = await import(authConfigPath);
|
|
1100
|
-
const auth = authModule.auth || authModule.default;
|
|
1101
|
-
console.log({ auth })
|
|
1102
|
-
if (!auth) {
|
|
1103
|
-
return res.json({
|
|
1104
|
-
enabled: false,
|
|
1105
|
-
error: 'No auth export found',
|
|
1106
|
-
configPath: authConfigPath
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
const hasOrganizationPlugin = auth.options?.plugins?.find((plugin: any) =>
|
|
1111
|
-
plugin.id === "organization"
|
|
1112
|
-
);
|
|
1113
|
-
console.log({ hasOrganizationPlugin })
|
|
1114
|
-
|
|
1115
|
-
res.json({
|
|
1116
|
-
enabled: !!hasOrganizationPlugin,
|
|
1117
|
-
configPath: authConfigPath,
|
|
1118
|
-
availablePlugins: auth.options?.plugins?.map((p: any) => p.id) || [],
|
|
1119
|
-
organizationPlugin: hasOrganizationPlugin || null
|
|
1120
|
-
});
|
|
1121
|
-
|
|
1122
|
-
} catch (error) {
|
|
1123
|
-
console.error('Error checking organization plugin:', error);
|
|
1124
|
-
res.json({
|
|
1125
|
-
enabled: false,
|
|
1126
|
-
error: 'Failed to load auth config',
|
|
1127
|
-
configPath: authConfigPath
|
|
1128
|
-
});
|
|
1129
|
-
}
|
|
1130
|
-
} catch (error) {
|
|
1131
|
-
console.error('Error checking plugin status:', error);
|
|
1132
|
-
res.status(500).json({ error: 'Failed to check plugin status' });
|
|
1133
|
-
}
|
|
1134
|
-
});
|
|
1135
|
-
|
|
1136
|
-
router.get('/api/organizations', async (req: Request, res: Response) => {
|
|
1137
|
-
try {
|
|
1138
|
-
const page = parseInt(req.query.page as string) || 1;
|
|
1139
|
-
const limit = parseInt(req.query.limit as string) || 20;
|
|
1140
|
-
const search = req.query.search as string;
|
|
1141
|
-
|
|
1142
|
-
try {
|
|
1143
|
-
const adapter = await getAuthAdapter();
|
|
1144
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
1145
|
-
const allOrganizations = await adapter.findMany({ model: 'organization' });
|
|
1146
|
-
console.log('Found organizations via findMany:', allOrganizations?.length || 0);
|
|
1147
|
-
|
|
1148
|
-
let filteredOrganizations = allOrganizations || [];
|
|
1149
|
-
if (search) {
|
|
1150
|
-
filteredOrganizations = filteredOrganizations.filter((org: any) =>
|
|
1151
|
-
org.name?.toLowerCase().includes(search.toLowerCase()) ||
|
|
1152
|
-
org.slug?.toLowerCase().includes(search.toLowerCase())
|
|
1153
|
-
);
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
const startIndex = (page - 1) * limit;
|
|
1157
|
-
const endIndex = startIndex + limit;
|
|
1158
|
-
const paginatedOrganizations = filteredOrganizations.slice(startIndex, endIndex);
|
|
1159
|
-
|
|
1160
|
-
const transformedOrganizations = paginatedOrganizations.map((org: any) => ({
|
|
1161
|
-
id: org.id,
|
|
1162
|
-
name: org.name,
|
|
1163
|
-
slug: org.slug,
|
|
1164
|
-
metadata: org.metadata,
|
|
1165
|
-
createdAt: org.createdAt,
|
|
1166
|
-
updatedAt: org.updatedAt,
|
|
1167
|
-
}));
|
|
1168
|
-
|
|
1169
|
-
res.json({ organizations: transformedOrganizations });
|
|
1170
|
-
return;
|
|
1171
|
-
}
|
|
1172
|
-
} catch (adapterError) {
|
|
1173
|
-
console.error('Error fetching organizations from adapter:', adapterError);
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
const mockOrganizations = [
|
|
1177
|
-
{
|
|
1178
|
-
id: 'org_1',
|
|
1179
|
-
name: 'Acme Corp',
|
|
1180
|
-
slug: 'acme-corp',
|
|
1181
|
-
metadata: { status: 'active' },
|
|
1182
|
-
createdAt: new Date().toISOString(),
|
|
1183
|
-
updatedAt: new Date().toISOString()
|
|
1184
|
-
},
|
|
1185
|
-
{
|
|
1186
|
-
id: 'org_2',
|
|
1187
|
-
name: 'Tech Solutions',
|
|
1188
|
-
slug: 'tech-solutions',
|
|
1189
|
-
metadata: { status: 'active' },
|
|
1190
|
-
createdAt: new Date().toISOString(),
|
|
1191
|
-
updatedAt: new Date().toISOString()
|
|
1192
|
-
}
|
|
1193
|
-
];
|
|
1194
|
-
|
|
1195
|
-
res.json({ organizations: mockOrganizations });
|
|
1196
|
-
} catch (error) {
|
|
1197
|
-
console.error('Error fetching organizations:', error);
|
|
1198
|
-
res.status(500).json({ error: 'Failed to fetch organizations' });
|
|
1199
|
-
}
|
|
1200
|
-
});
|
|
1201
|
-
|
|
1202
|
-
router.post('/api/organizations', async (req: Request, res: Response) => {
|
|
1203
|
-
try {
|
|
1204
|
-
const adapter = await getAuthAdapter();
|
|
1205
|
-
if (!adapter) {
|
|
1206
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
const orgData = req.body;
|
|
1210
|
-
|
|
1211
|
-
if (!orgData.slug && orgData.name) {
|
|
1212
|
-
orgData.slug = orgData.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
const organization = await adapter.createOrganization(orgData);
|
|
1216
|
-
res.json({ success: true, organization });
|
|
1217
|
-
} catch (error) {
|
|
1218
|
-
console.error('Error creating organization:', error);
|
|
1219
|
-
res.status(500).json({ error: 'Failed to create organization' });
|
|
1220
|
-
}
|
|
1221
|
-
});
|
|
1222
|
-
|
|
1223
|
-
router.put('/api/organizations/:id', async (req: Request, res: Response) => {
|
|
1224
|
-
try {
|
|
1225
|
-
const { id } = req.params;
|
|
1226
|
-
const orgData = req.body;
|
|
1227
|
-
const adapter: any = await getAuthAdapter();
|
|
1228
|
-
if (!adapter) {
|
|
1229
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1230
|
-
}
|
|
1231
|
-
if (orgData.name && !orgData.slug) {
|
|
1232
|
-
orgData.slug = orgData.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
const updatedOrganization = {
|
|
1236
|
-
id,
|
|
1237
|
-
...orgData,
|
|
1238
|
-
updatedAt: new Date().toISOString()
|
|
1239
|
-
};
|
|
1240
|
-
const updatedOrg = await adapter.update({
|
|
1241
|
-
model: 'organization',
|
|
1242
|
-
where: [
|
|
1243
|
-
{ field: 'id', value: id }
|
|
1244
|
-
],
|
|
1245
|
-
update: updatedOrganization
|
|
1246
|
-
});
|
|
1247
|
-
res.json({ success: true, organization: updatedOrg });
|
|
1248
|
-
} catch (error) {
|
|
1249
|
-
console.error('Error updating organization:', error);
|
|
1250
|
-
res.status(500).json({ error: 'Failed to update organization' });
|
|
1251
|
-
}
|
|
1252
|
-
});
|
|
1253
|
-
|
|
1254
|
-
router.get('/api/organizations/:id', async (req: Request, res: Response) => {
|
|
1255
|
-
try {
|
|
1256
|
-
const { id } = req.params;
|
|
1257
|
-
const adapter = await getAuthAdapter();
|
|
1258
|
-
|
|
1259
|
-
if (adapter && typeof adapter.findMany === 'function') {
|
|
1260
|
-
const organizations = await adapter.findMany({ model: 'organization', limit: 10000 });
|
|
1261
|
-
const organization = organizations?.find((org: any) => org.id === id);
|
|
1262
|
-
|
|
1263
|
-
if (organization) {
|
|
1264
|
-
const transformedOrganization = {
|
|
1265
|
-
id: organization.id,
|
|
1266
|
-
name: organization.name,
|
|
1267
|
-
slug: organization.slug,
|
|
1268
|
-
metadata: organization.metadata,
|
|
1269
|
-
createdAt: organization.createdAt,
|
|
1270
|
-
updatedAt: organization.updatedAt,
|
|
1271
|
-
};
|
|
1272
|
-
|
|
1273
|
-
res.json({ success: true, organization: transformedOrganization });
|
|
1274
|
-
return;
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
res.status(404).json({ success: false, error: 'Organization not found' });
|
|
1279
|
-
} catch (error) {
|
|
1280
|
-
console.error('Error fetching organization:', error);
|
|
1281
|
-
res.status(500).json({ error: 'Failed to fetch organization' });
|
|
1282
|
-
}
|
|
1283
|
-
});
|
|
1284
|
-
|
|
1285
|
-
router.delete('/api/organizations/:id', async (req: Request, res: Response) => {
|
|
1286
|
-
try {
|
|
1287
|
-
const { id } = req.params;
|
|
1288
|
-
const adapter: any = await getAuthAdapter();
|
|
1289
|
-
if (!adapter) {
|
|
1290
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1291
|
-
}
|
|
1292
|
-
const deletedOrg = await adapter.delete({
|
|
1293
|
-
model: 'organization',
|
|
1294
|
-
where: [
|
|
1295
|
-
{ field: 'id', value: id }
|
|
1296
|
-
]
|
|
1297
|
-
});
|
|
1298
|
-
res.json({ success: true, organization: deletedOrg });
|
|
1299
|
-
} catch (error) {
|
|
1300
|
-
console.error('Error deleting organization:', error);
|
|
1301
|
-
res.status(500).json({ error: 'Failed to delete organization' });
|
|
1302
|
-
}
|
|
1303
|
-
});
|
|
1304
|
-
|
|
1305
|
-
router.post('/api/users', async (req: Request, res: Response) => {
|
|
1306
|
-
try {
|
|
1307
|
-
const adapter = await getAuthAdapter();
|
|
1308
|
-
if (!adapter) {
|
|
1309
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
const userData = req.body;
|
|
1313
|
-
const user = await adapter.createUser(userData);
|
|
1314
|
-
res.json({ success: true, user });
|
|
1315
|
-
} catch (error) {
|
|
1316
|
-
console.error('Error creating user:', error);
|
|
1317
|
-
res.status(500).json({ error: 'Failed to create user' });
|
|
1318
|
-
}
|
|
1319
|
-
});
|
|
1320
|
-
|
|
1321
|
-
router.put('/api/users/:id', async (req: Request, res: Response) => {
|
|
1322
|
-
try {
|
|
1323
|
-
const { id } = req.params;
|
|
1324
|
-
const userData = req.body;
|
|
1325
|
-
|
|
1326
|
-
const updatedUser = await getAuthData(authConfig, 'updateUser', { id, userData });
|
|
1327
|
-
res.json({ success: true, user: updatedUser });
|
|
1328
|
-
} catch (error) {
|
|
1329
|
-
console.error('Error updating user:', error);
|
|
1330
|
-
res.status(500).json({ error: 'Failed to update user' });
|
|
1331
|
-
}
|
|
1332
|
-
});
|
|
1333
|
-
|
|
1334
|
-
router.post('/api/seed/users', async (req: Request, res: Response) => {
|
|
1335
|
-
try {
|
|
1336
|
-
const { count = 1 } = req.body;
|
|
1337
|
-
const adapter = await getAuthAdapter();
|
|
1338
|
-
console.log({ adapter })
|
|
1339
|
-
if (!adapter) {
|
|
1340
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
const results = [];
|
|
1344
|
-
for (let i = 0; i < count; i++) {
|
|
1345
|
-
try {
|
|
1346
|
-
if (typeof adapter.createUser !== 'function') {
|
|
1347
|
-
throw new Error('createUser method not available on adapter');
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
const user = await createMockUser(adapter, i + 1);
|
|
1351
|
-
results.push({
|
|
1352
|
-
success: true,
|
|
1353
|
-
user: {
|
|
1354
|
-
id: user.id,
|
|
1355
|
-
email: user.email,
|
|
1356
|
-
name: user.name,
|
|
1357
|
-
emailVerified: user.emailVerified,
|
|
1358
|
-
image: user.image,
|
|
1359
|
-
createdAt: user.createdAt
|
|
1360
|
-
}
|
|
1361
|
-
});
|
|
1362
|
-
} catch (error) {
|
|
1363
|
-
results.push({
|
|
1364
|
-
success: false,
|
|
1365
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
1366
|
-
});
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
res.json({
|
|
1371
|
-
success: true,
|
|
1372
|
-
message: `Seeded ${results.filter(r => r.success).length} users`,
|
|
1373
|
-
results
|
|
1374
|
-
});
|
|
1375
|
-
} catch (error) {
|
|
1376
|
-
console.error('Error seeding users:', error);
|
|
1377
|
-
res.status(500).json({ error: 'Failed to seed users' });
|
|
1378
|
-
}
|
|
1379
|
-
});
|
|
1380
|
-
|
|
1381
|
-
router.post('/api/seed/sessions', async (req: Request, res: Response) => {
|
|
1382
|
-
try {
|
|
1383
|
-
const { count = 1 } = req.body;
|
|
1384
|
-
const adapter = await getAuthAdapter();
|
|
1385
|
-
|
|
1386
|
-
if (!adapter) {
|
|
1387
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
let user;
|
|
1391
|
-
try {
|
|
1392
|
-
user = await createMockUser(adapter, 1);
|
|
1393
|
-
} catch (error) {
|
|
1394
|
-
return res.status(500).json({ error: 'Failed to create user for session' });
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
const results = [];
|
|
1398
|
-
for (let i = 0; i < count; i++) {
|
|
1399
|
-
try {
|
|
1400
|
-
if (typeof adapter.createSession !== 'function') {
|
|
1401
|
-
throw new Error('createSession method not available on adapter');
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
const session = await createMockSession(adapter, user.id, i + 1);
|
|
1405
|
-
results.push({
|
|
1406
|
-
success: true,
|
|
1407
|
-
session: {
|
|
1408
|
-
id: session.id,
|
|
1409
|
-
userId: session.userId,
|
|
1410
|
-
expires: session.expires,
|
|
1411
|
-
sessionToken: session.sessionToken,
|
|
1412
|
-
createdAt: session.createdAt
|
|
1413
|
-
}
|
|
1414
|
-
});
|
|
1415
|
-
} catch (error) {
|
|
1416
|
-
results.push({
|
|
1417
|
-
success: false,
|
|
1418
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
res.json({
|
|
1424
|
-
success: true,
|
|
1425
|
-
message: `Seeded ${results.filter(r => r.success).length} sessions`,
|
|
1426
|
-
results
|
|
1427
|
-
});
|
|
1428
|
-
} catch (error) {
|
|
1429
|
-
console.error('Error seeding sessions:', error);
|
|
1430
|
-
res.status(500).json({ error: 'Failed to seed sessions' });
|
|
1431
|
-
}
|
|
1432
|
-
});
|
|
1433
|
-
|
|
1434
|
-
router.post('/api/seed/accounts', async (req: Request, res: Response) => {
|
|
1435
|
-
try {
|
|
1436
|
-
const { count = 1 } = req.body;
|
|
1437
|
-
const adapter = await getAuthAdapter();
|
|
1438
|
-
|
|
1439
|
-
if (!adapter) {
|
|
1440
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1441
|
-
}
|
|
1442
|
-
|
|
1443
|
-
let user;
|
|
1444
|
-
try {
|
|
1445
|
-
user = await createMockUser(adapter, 1);
|
|
1446
|
-
} catch (error) {
|
|
1447
|
-
return res.status(500).json({ error: 'Failed to create user for account' });
|
|
1448
|
-
}
|
|
1449
|
-
|
|
1450
|
-
const results = [];
|
|
1451
|
-
for (let i = 0; i < count; i++) {
|
|
1452
|
-
try {
|
|
1453
|
-
if (typeof adapter.createAccount !== 'function') {
|
|
1454
|
-
throw new Error('createAccount method not available on adapter');
|
|
1455
|
-
}
|
|
1456
|
-
|
|
1457
|
-
const account = await createMockAccount(adapter, user.id, i + 1);
|
|
1458
|
-
results.push({
|
|
1459
|
-
success: true,
|
|
1460
|
-
account: {
|
|
1461
|
-
id: account.id,
|
|
1462
|
-
userId: account.userId,
|
|
1463
|
-
type: account.type,
|
|
1464
|
-
provider: account.provider,
|
|
1465
|
-
providerAccountId: account.providerAccountId,
|
|
1466
|
-
createdAt: account.createdAt
|
|
1467
|
-
}
|
|
1468
|
-
});
|
|
1469
|
-
} catch (error) {
|
|
1470
|
-
results.push({
|
|
1471
|
-
success: false,
|
|
1472
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
1473
|
-
});
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
|
|
1477
|
-
res.json({
|
|
1478
|
-
success: true,
|
|
1479
|
-
message: `Seeded ${results.filter(r => r.success).length} accounts`,
|
|
1480
|
-
results
|
|
1481
|
-
});
|
|
1482
|
-
} catch (error) {
|
|
1483
|
-
console.error('Error seeding accounts:', error);
|
|
1484
|
-
res.status(500).json({ error: 'Failed to seed accounts' });
|
|
1485
|
-
}
|
|
1486
|
-
});
|
|
1487
|
-
|
|
1488
|
-
router.post('/api/seed/verifications', async (req: Request, res: Response) => {
|
|
1489
|
-
try {
|
|
1490
|
-
const { count = 1 } = req.body;
|
|
1491
|
-
const adapter = await getAuthAdapter();
|
|
1492
|
-
|
|
1493
|
-
if (!adapter) {
|
|
1494
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
const results = [];
|
|
1498
|
-
for (let i = 0; i < count; i++) {
|
|
1499
|
-
try {
|
|
1500
|
-
if (typeof adapter.createVerification !== 'function') {
|
|
1501
|
-
throw new Error('createVerification method not available on adapter');
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
|
-
const verification = await createMockVerification(adapter, `user${i + 1}@example.com`, i + 1);
|
|
1505
|
-
results.push({
|
|
1506
|
-
success: true,
|
|
1507
|
-
verification: {
|
|
1508
|
-
id: verification.id,
|
|
1509
|
-
identifier: verification.identifier,
|
|
1510
|
-
token: verification.token,
|
|
1511
|
-
expires: verification.expires,
|
|
1512
|
-
createdAt: verification.createdAt
|
|
1513
|
-
}
|
|
1514
|
-
});
|
|
1515
|
-
} catch (error) {
|
|
1516
|
-
results.push({
|
|
1517
|
-
success: false,
|
|
1518
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
1519
|
-
});
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
res.json({
|
|
1524
|
-
success: true,
|
|
1525
|
-
message: `Seeded ${results.filter(r => r.success).length} verifications`,
|
|
1526
|
-
results
|
|
1527
|
-
});
|
|
1528
|
-
} catch (error) {
|
|
1529
|
-
console.error('Error seeding verifications:', error);
|
|
1530
|
-
res.status(500).json({ error: 'Failed to seed verifications' });
|
|
1531
|
-
}
|
|
1532
|
-
});
|
|
1533
|
-
|
|
1534
|
-
router.post('/api/seed/organizations', async (req: Request, res: Response) => {
|
|
1535
|
-
try {
|
|
1536
|
-
const { count = 1 } = req.body;
|
|
1537
|
-
const adapter = await getAuthAdapter();
|
|
1538
|
-
|
|
1539
|
-
if (!adapter) {
|
|
1540
|
-
return res.status(500).json({ error: 'Auth adapter not available' });
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
const results = [];
|
|
1544
|
-
for (let i = 0; i < count; i++) {
|
|
1545
|
-
try {
|
|
1546
|
-
const organizationData = {
|
|
1547
|
-
name: `Organization ${i + 1}`,
|
|
1548
|
-
slug: `org-${i + 1}`,
|
|
1549
|
-
image: `https://api.dicebear.com/7.x/identicon/svg?seed=org${i + 1}`,
|
|
1550
|
-
createdAt: new Date(),
|
|
1551
|
-
updatedAt: new Date()
|
|
1552
|
-
};
|
|
1553
|
-
|
|
1554
|
-
const organization = await adapter.createOrganization(organizationData);
|
|
1555
|
-
results.push({
|
|
1556
|
-
success: true,
|
|
1557
|
-
organization: {
|
|
1558
|
-
id: organization.id,
|
|
1559
|
-
name: organization.name,
|
|
1560
|
-
slug: organization.slug,
|
|
1561
|
-
image: organization.image,
|
|
1562
|
-
createdAt: organization.createdAt
|
|
1563
|
-
}
|
|
1564
|
-
});
|
|
1565
|
-
} catch (error) {
|
|
1566
|
-
results.push({
|
|
1567
|
-
success: false,
|
|
1568
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
1569
|
-
});
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
res.json({
|
|
1574
|
-
success: true,
|
|
1575
|
-
message: `Seeded ${results.filter(r => r.success).length} organizations`,
|
|
1576
|
-
results
|
|
1577
|
-
});
|
|
1578
|
-
} catch (error) {
|
|
1579
|
-
console.error('Error seeding organizations:', error);
|
|
1580
|
-
res.status(500).json({ error: 'Failed to seed organizations' });
|
|
1581
|
-
}
|
|
1582
|
-
});
|
|
1583
|
-
|
|
1584
|
-
return router;
|
|
1585
|
-
}
|