better-auth-studio 1.0.23-beta.4 → 1.0.24-beta.1
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/README.md +2 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +634 -1
- package/dist/routes.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/main-Ba9FD9p1.css +1 -0
- package/public/assets/main-D7saZxpB.js +405 -0
- package/public/index.html +2 -2
- package/public/assets/main-DBAg_Mbk.css +0 -1
- package/public/assets/main-jcB2p8Xw.js +0 -363
package/README.md
CHANGED
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAY9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA+C9C,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA4J/E;AAwBD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAY9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA+C9C,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA4J/E;AAwBD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAk2FR"}
|
package/dist/routes.js
CHANGED
|
@@ -1030,6 +1030,638 @@ export function createRoutes(authConfig, configPath, geoDbPath) {
|
|
|
1030
1030
|
res.status(500).json({ error: 'Failed to fetch database info' });
|
|
1031
1031
|
}
|
|
1032
1032
|
});
|
|
1033
|
+
// Database Schema Visualization endpoint
|
|
1034
|
+
// Schema definitions for different Better Auth plugins
|
|
1035
|
+
const BASE_SCHEMA = {
|
|
1036
|
+
user: {
|
|
1037
|
+
name: 'user',
|
|
1038
|
+
displayName: 'User',
|
|
1039
|
+
fields: [
|
|
1040
|
+
{
|
|
1041
|
+
name: 'id',
|
|
1042
|
+
type: 'string',
|
|
1043
|
+
required: true,
|
|
1044
|
+
primaryKey: true,
|
|
1045
|
+
description: 'Unique user identifier',
|
|
1046
|
+
},
|
|
1047
|
+
{ name: 'name', type: 'string', required: true, description: 'User display name' },
|
|
1048
|
+
{
|
|
1049
|
+
name: 'email',
|
|
1050
|
+
type: 'string',
|
|
1051
|
+
required: true,
|
|
1052
|
+
unique: true,
|
|
1053
|
+
description: 'User email address',
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
name: 'emailVerified',
|
|
1057
|
+
type: 'boolean',
|
|
1058
|
+
required: true,
|
|
1059
|
+
defaultValue: false,
|
|
1060
|
+
description: 'Email verification status',
|
|
1061
|
+
},
|
|
1062
|
+
{ name: 'image', type: 'string', required: false, description: 'User profile image URL' },
|
|
1063
|
+
{
|
|
1064
|
+
name: 'createdAt',
|
|
1065
|
+
type: 'date',
|
|
1066
|
+
required: true,
|
|
1067
|
+
description: 'Account creation timestamp',
|
|
1068
|
+
},
|
|
1069
|
+
{ name: 'updatedAt', type: 'date', required: true, description: 'Last update timestamp' },
|
|
1070
|
+
],
|
|
1071
|
+
relationships: [
|
|
1072
|
+
{ type: 'one-to-many', target: 'session', field: 'userId' },
|
|
1073
|
+
{ type: 'one-to-many', target: 'account', field: 'userId' },
|
|
1074
|
+
],
|
|
1075
|
+
},
|
|
1076
|
+
session: {
|
|
1077
|
+
name: 'session',
|
|
1078
|
+
displayName: 'Session',
|
|
1079
|
+
fields: [
|
|
1080
|
+
{
|
|
1081
|
+
name: 'id',
|
|
1082
|
+
type: 'string',
|
|
1083
|
+
required: true,
|
|
1084
|
+
primaryKey: true,
|
|
1085
|
+
description: 'Unique session identifier',
|
|
1086
|
+
},
|
|
1087
|
+
{
|
|
1088
|
+
name: 'expiresAt',
|
|
1089
|
+
type: 'date',
|
|
1090
|
+
required: true,
|
|
1091
|
+
description: 'Session expiration timestamp',
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
name: 'token',
|
|
1095
|
+
type: 'string',
|
|
1096
|
+
required: true,
|
|
1097
|
+
unique: true,
|
|
1098
|
+
description: 'Session token',
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
name: 'createdAt',
|
|
1102
|
+
type: 'date',
|
|
1103
|
+
required: true,
|
|
1104
|
+
description: 'Session creation timestamp',
|
|
1105
|
+
},
|
|
1106
|
+
{ name: 'updatedAt', type: 'date', required: true, description: 'Last update timestamp' },
|
|
1107
|
+
{ name: 'ipAddress', type: 'string', required: false, description: 'Client IP address' },
|
|
1108
|
+
{ name: 'userAgent', type: 'string', required: false, description: 'Client user agent' },
|
|
1109
|
+
{ name: 'userId', type: 'string', required: true, description: 'Associated user ID' },
|
|
1110
|
+
],
|
|
1111
|
+
relationships: [{ type: 'many-to-one', target: 'user', field: 'userId' }],
|
|
1112
|
+
},
|
|
1113
|
+
account: {
|
|
1114
|
+
name: 'account',
|
|
1115
|
+
displayName: 'Account',
|
|
1116
|
+
fields: [
|
|
1117
|
+
{
|
|
1118
|
+
name: 'id',
|
|
1119
|
+
type: 'string',
|
|
1120
|
+
required: true,
|
|
1121
|
+
primaryKey: true,
|
|
1122
|
+
description: 'Unique account identifier',
|
|
1123
|
+
},
|
|
1124
|
+
{ name: 'accountId', type: 'string', required: true, description: 'Provider account ID' },
|
|
1125
|
+
{
|
|
1126
|
+
name: 'providerId',
|
|
1127
|
+
type: 'string',
|
|
1128
|
+
required: true,
|
|
1129
|
+
description: 'Authentication provider',
|
|
1130
|
+
},
|
|
1131
|
+
{ name: 'userId', type: 'string', required: true, description: 'Associated user ID' },
|
|
1132
|
+
{ name: 'accessToken', type: 'string', required: false, description: 'OAuth access token' },
|
|
1133
|
+
{
|
|
1134
|
+
name: 'refreshToken',
|
|
1135
|
+
type: 'string',
|
|
1136
|
+
required: false,
|
|
1137
|
+
description: 'OAuth refresh token',
|
|
1138
|
+
},
|
|
1139
|
+
{ name: 'idToken', type: 'string', required: false, description: 'OAuth ID token' },
|
|
1140
|
+
{
|
|
1141
|
+
name: 'accessTokenExpiresAt',
|
|
1142
|
+
type: 'date',
|
|
1143
|
+
required: false,
|
|
1144
|
+
description: 'Access token expiration',
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
name: 'refreshTokenExpiresAt',
|
|
1148
|
+
type: 'date',
|
|
1149
|
+
required: false,
|
|
1150
|
+
description: 'Refresh token expiration',
|
|
1151
|
+
},
|
|
1152
|
+
{ name: 'scope', type: 'string', required: false, description: 'OAuth scope' },
|
|
1153
|
+
{
|
|
1154
|
+
name: 'password',
|
|
1155
|
+
type: 'string',
|
|
1156
|
+
required: false,
|
|
1157
|
+
description: 'Hashed password (if applicable)',
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
name: 'createdAt',
|
|
1161
|
+
type: 'date',
|
|
1162
|
+
required: true,
|
|
1163
|
+
description: 'Account creation timestamp',
|
|
1164
|
+
},
|
|
1165
|
+
{ name: 'updatedAt', type: 'date', required: true, description: 'Last update timestamp' },
|
|
1166
|
+
],
|
|
1167
|
+
relationships: [{ type: 'many-to-one', target: 'user', field: 'userId' }],
|
|
1168
|
+
},
|
|
1169
|
+
verification: {
|
|
1170
|
+
name: 'verification',
|
|
1171
|
+
displayName: 'Verification',
|
|
1172
|
+
fields: [
|
|
1173
|
+
{
|
|
1174
|
+
name: 'id',
|
|
1175
|
+
type: 'string',
|
|
1176
|
+
required: true,
|
|
1177
|
+
primaryKey: true,
|
|
1178
|
+
description: 'Unique verification identifier',
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
name: 'identifier',
|
|
1182
|
+
type: 'string',
|
|
1183
|
+
required: true,
|
|
1184
|
+
description: 'Email or phone being verified',
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
name: 'value',
|
|
1188
|
+
type: 'string',
|
|
1189
|
+
required: true,
|
|
1190
|
+
description: 'Verification code or token',
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
name: 'expiresAt',
|
|
1194
|
+
type: 'date',
|
|
1195
|
+
required: true,
|
|
1196
|
+
description: 'Verification expiration timestamp',
|
|
1197
|
+
},
|
|
1198
|
+
{
|
|
1199
|
+
name: 'createdAt',
|
|
1200
|
+
type: 'date',
|
|
1201
|
+
required: true,
|
|
1202
|
+
description: 'Verification creation timestamp',
|
|
1203
|
+
},
|
|
1204
|
+
{ name: 'updatedAt', type: 'date', required: true, description: 'Last update timestamp' },
|
|
1205
|
+
],
|
|
1206
|
+
relationships: [],
|
|
1207
|
+
},
|
|
1208
|
+
};
|
|
1209
|
+
// Plugin schemas that extend the base schema
|
|
1210
|
+
const PLUGIN_SCHEMAS = {
|
|
1211
|
+
organization: {
|
|
1212
|
+
tables: {
|
|
1213
|
+
organization: {
|
|
1214
|
+
name: 'organization',
|
|
1215
|
+
displayName: 'Organization',
|
|
1216
|
+
fields: [
|
|
1217
|
+
{
|
|
1218
|
+
name: 'id',
|
|
1219
|
+
type: 'string',
|
|
1220
|
+
required: true,
|
|
1221
|
+
primaryKey: true,
|
|
1222
|
+
description: 'Unique organization identifier',
|
|
1223
|
+
},
|
|
1224
|
+
{ name: 'name', type: 'string', required: true, description: 'Organization name' },
|
|
1225
|
+
{
|
|
1226
|
+
name: 'slug',
|
|
1227
|
+
type: 'string',
|
|
1228
|
+
required: false,
|
|
1229
|
+
unique: true,
|
|
1230
|
+
description: 'Organization URL slug',
|
|
1231
|
+
},
|
|
1232
|
+
{ name: 'logo', type: 'string', required: false, description: 'Organization logo URL' },
|
|
1233
|
+
{
|
|
1234
|
+
name: 'createdAt',
|
|
1235
|
+
type: 'date',
|
|
1236
|
+
required: true,
|
|
1237
|
+
description: 'Organization creation timestamp',
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
name: 'metadata',
|
|
1241
|
+
type: 'json',
|
|
1242
|
+
required: false,
|
|
1243
|
+
description: 'Additional organization metadata',
|
|
1244
|
+
},
|
|
1245
|
+
],
|
|
1246
|
+
relationships: [
|
|
1247
|
+
{ type: 'one-to-many', target: 'member', field: 'organizationId' },
|
|
1248
|
+
{ type: 'one-to-many', target: 'invitation', field: 'organizationId' },
|
|
1249
|
+
],
|
|
1250
|
+
},
|
|
1251
|
+
member: {
|
|
1252
|
+
name: 'member',
|
|
1253
|
+
displayName: 'Member',
|
|
1254
|
+
fields: [
|
|
1255
|
+
{
|
|
1256
|
+
name: 'id',
|
|
1257
|
+
type: 'string',
|
|
1258
|
+
required: true,
|
|
1259
|
+
primaryKey: true,
|
|
1260
|
+
description: 'Unique member identifier',
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
name: 'organizationId',
|
|
1264
|
+
type: 'string',
|
|
1265
|
+
required: true,
|
|
1266
|
+
description: 'Organization ID',
|
|
1267
|
+
},
|
|
1268
|
+
{ name: 'userId', type: 'string', required: true, description: 'User ID' },
|
|
1269
|
+
{
|
|
1270
|
+
name: 'role',
|
|
1271
|
+
type: 'string',
|
|
1272
|
+
required: true,
|
|
1273
|
+
defaultValue: 'member',
|
|
1274
|
+
description: 'Member role in organization',
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
name: 'createdAt',
|
|
1278
|
+
type: 'date',
|
|
1279
|
+
required: true,
|
|
1280
|
+
description: 'Membership creation timestamp',
|
|
1281
|
+
},
|
|
1282
|
+
],
|
|
1283
|
+
relationships: [
|
|
1284
|
+
{ type: 'many-to-one', target: 'organization', field: 'organizationId' },
|
|
1285
|
+
{ type: 'many-to-one', target: 'user', field: 'userId' },
|
|
1286
|
+
],
|
|
1287
|
+
},
|
|
1288
|
+
invitation: {
|
|
1289
|
+
name: 'invitation',
|
|
1290
|
+
displayName: 'Invitation',
|
|
1291
|
+
fields: [
|
|
1292
|
+
{
|
|
1293
|
+
name: 'id',
|
|
1294
|
+
type: 'string',
|
|
1295
|
+
required: true,
|
|
1296
|
+
primaryKey: true,
|
|
1297
|
+
description: 'Unique invitation identifier',
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
name: 'organizationId',
|
|
1301
|
+
type: 'string',
|
|
1302
|
+
required: true,
|
|
1303
|
+
description: 'Organization ID',
|
|
1304
|
+
},
|
|
1305
|
+
{ name: 'email', type: 'string', required: true, description: 'Invited email address' },
|
|
1306
|
+
{ name: 'role', type: 'string', required: false, description: 'Invited role' },
|
|
1307
|
+
{
|
|
1308
|
+
name: 'status',
|
|
1309
|
+
type: 'string',
|
|
1310
|
+
required: true,
|
|
1311
|
+
defaultValue: 'pending',
|
|
1312
|
+
description: 'Invitation status',
|
|
1313
|
+
},
|
|
1314
|
+
{
|
|
1315
|
+
name: 'expiresAt',
|
|
1316
|
+
type: 'date',
|
|
1317
|
+
required: true,
|
|
1318
|
+
description: 'Invitation expiration timestamp',
|
|
1319
|
+
},
|
|
1320
|
+
{
|
|
1321
|
+
name: 'inviterId',
|
|
1322
|
+
type: 'string',
|
|
1323
|
+
required: true,
|
|
1324
|
+
description: 'User who sent the invitation',
|
|
1325
|
+
},
|
|
1326
|
+
],
|
|
1327
|
+
relationships: [
|
|
1328
|
+
{ type: 'many-to-one', target: 'organization', field: 'organizationId' },
|
|
1329
|
+
{ type: 'many-to-one', target: 'user', field: 'inviterId' },
|
|
1330
|
+
],
|
|
1331
|
+
},
|
|
1332
|
+
},
|
|
1333
|
+
userExtensions: {
|
|
1334
|
+
fields: [],
|
|
1335
|
+
relationships: [
|
|
1336
|
+
{ type: 'one-to-many', target: 'member', field: 'userId' },
|
|
1337
|
+
{ type: 'one-to-many', target: 'invitation', field: 'inviterId' },
|
|
1338
|
+
],
|
|
1339
|
+
},
|
|
1340
|
+
sessionExtensions: {
|
|
1341
|
+
fields: [
|
|
1342
|
+
{
|
|
1343
|
+
name: 'activeOrganizationId',
|
|
1344
|
+
type: 'string',
|
|
1345
|
+
required: false,
|
|
1346
|
+
description: 'Active organization ID',
|
|
1347
|
+
},
|
|
1348
|
+
],
|
|
1349
|
+
relationships: [],
|
|
1350
|
+
},
|
|
1351
|
+
},
|
|
1352
|
+
teams: {
|
|
1353
|
+
tables: {
|
|
1354
|
+
team: {
|
|
1355
|
+
name: 'team',
|
|
1356
|
+
displayName: 'Team',
|
|
1357
|
+
fields: [
|
|
1358
|
+
{
|
|
1359
|
+
name: 'id',
|
|
1360
|
+
type: 'string',
|
|
1361
|
+
required: true,
|
|
1362
|
+
primaryKey: true,
|
|
1363
|
+
description: 'Unique team identifier',
|
|
1364
|
+
},
|
|
1365
|
+
{ name: 'name', type: 'string', required: true, description: 'Team name' },
|
|
1366
|
+
{
|
|
1367
|
+
name: 'organizationId',
|
|
1368
|
+
type: 'string',
|
|
1369
|
+
required: true,
|
|
1370
|
+
description: 'Organization ID',
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
name: 'createdAt',
|
|
1374
|
+
type: 'date',
|
|
1375
|
+
required: true,
|
|
1376
|
+
description: 'Team creation timestamp',
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
name: 'updatedAt',
|
|
1380
|
+
type: 'date',
|
|
1381
|
+
required: false,
|
|
1382
|
+
description: 'Last update timestamp',
|
|
1383
|
+
},
|
|
1384
|
+
],
|
|
1385
|
+
relationships: [
|
|
1386
|
+
{ type: 'many-to-one', target: 'organization', field: 'organizationId' },
|
|
1387
|
+
{ type: 'one-to-many', target: 'teamMember', field: 'teamId' },
|
|
1388
|
+
],
|
|
1389
|
+
},
|
|
1390
|
+
teamMember: {
|
|
1391
|
+
name: 'teamMember',
|
|
1392
|
+
displayName: 'Team Member',
|
|
1393
|
+
fields: [
|
|
1394
|
+
{
|
|
1395
|
+
name: 'id',
|
|
1396
|
+
type: 'string',
|
|
1397
|
+
required: true,
|
|
1398
|
+
primaryKey: true,
|
|
1399
|
+
description: 'Unique team member identifier',
|
|
1400
|
+
},
|
|
1401
|
+
{ name: 'teamId', type: 'string', required: true, description: 'Team ID' },
|
|
1402
|
+
{ name: 'userId', type: 'string', required: true, description: 'User ID' },
|
|
1403
|
+
{
|
|
1404
|
+
name: 'createdAt',
|
|
1405
|
+
type: 'date',
|
|
1406
|
+
required: false,
|
|
1407
|
+
description: 'Team membership creation timestamp',
|
|
1408
|
+
},
|
|
1409
|
+
],
|
|
1410
|
+
relationships: [
|
|
1411
|
+
{ type: 'many-to-one', target: 'team', field: 'teamId' },
|
|
1412
|
+
{ type: 'many-to-one', target: 'user', field: 'userId' },
|
|
1413
|
+
],
|
|
1414
|
+
},
|
|
1415
|
+
},
|
|
1416
|
+
organizationExtensions: {
|
|
1417
|
+
relationships: [{ type: 'one-to-many', target: 'team', field: 'organizationId' }],
|
|
1418
|
+
},
|
|
1419
|
+
sessionExtensions: {
|
|
1420
|
+
fields: [
|
|
1421
|
+
{ name: 'activeTeamId', type: 'string', required: false, description: 'Active team ID' },
|
|
1422
|
+
],
|
|
1423
|
+
relationships: [],
|
|
1424
|
+
},
|
|
1425
|
+
},
|
|
1426
|
+
twoFactor: {
|
|
1427
|
+
tables: {
|
|
1428
|
+
twoFactor: {
|
|
1429
|
+
name: 'twoFactor',
|
|
1430
|
+
displayName: 'Two Factor',
|
|
1431
|
+
fields: [
|
|
1432
|
+
{
|
|
1433
|
+
name: 'id',
|
|
1434
|
+
type: 'string',
|
|
1435
|
+
required: true,
|
|
1436
|
+
primaryKey: true,
|
|
1437
|
+
description: 'Unique two-factor authentication identifier',
|
|
1438
|
+
},
|
|
1439
|
+
{ name: 'userId', type: 'string', required: true, description: 'Associated user ID' },
|
|
1440
|
+
{
|
|
1441
|
+
name: 'secret',
|
|
1442
|
+
type: 'string',
|
|
1443
|
+
required: true,
|
|
1444
|
+
description: 'Two-factor authentication secret',
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
name: 'backupCodes',
|
|
1448
|
+
type: 'string',
|
|
1449
|
+
required: true,
|
|
1450
|
+
description: 'Backup codes for two-factor authentication',
|
|
1451
|
+
},
|
|
1452
|
+
],
|
|
1453
|
+
relationships: [{ type: 'many-to-one', target: 'user', field: 'userId' }],
|
|
1454
|
+
},
|
|
1455
|
+
},
|
|
1456
|
+
userExtensions: {
|
|
1457
|
+
fields: [
|
|
1458
|
+
{
|
|
1459
|
+
name: 'twoFactorEnabled',
|
|
1460
|
+
type: 'boolean',
|
|
1461
|
+
required: false,
|
|
1462
|
+
description: 'Two-factor authentication enabled status',
|
|
1463
|
+
},
|
|
1464
|
+
],
|
|
1465
|
+
relationships: [{ type: 'one-to-one', target: 'twoFactor', field: 'userId' }],
|
|
1466
|
+
},
|
|
1467
|
+
},
|
|
1468
|
+
apiKey: {
|
|
1469
|
+
tables: {
|
|
1470
|
+
apiKey: {
|
|
1471
|
+
name: 'apiKey',
|
|
1472
|
+
displayName: 'API Key',
|
|
1473
|
+
fields: [
|
|
1474
|
+
{
|
|
1475
|
+
name: 'id',
|
|
1476
|
+
type: 'string',
|
|
1477
|
+
required: true,
|
|
1478
|
+
primaryKey: true,
|
|
1479
|
+
description: 'Unique API key identifier',
|
|
1480
|
+
},
|
|
1481
|
+
{ name: 'userId', type: 'string', required: true, description: 'Associated user ID' },
|
|
1482
|
+
{ name: 'name', type: 'string', required: true, description: 'API key name' },
|
|
1483
|
+
{
|
|
1484
|
+
name: 'key',
|
|
1485
|
+
type: 'string',
|
|
1486
|
+
required: true,
|
|
1487
|
+
unique: true,
|
|
1488
|
+
description: 'API key value',
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
name: 'expiresAt',
|
|
1492
|
+
type: 'date',
|
|
1493
|
+
required: false,
|
|
1494
|
+
description: 'API key expiration timestamp',
|
|
1495
|
+
},
|
|
1496
|
+
{
|
|
1497
|
+
name: 'lastUsedAt',
|
|
1498
|
+
type: 'date',
|
|
1499
|
+
required: false,
|
|
1500
|
+
description: 'Last usage timestamp',
|
|
1501
|
+
},
|
|
1502
|
+
{
|
|
1503
|
+
name: 'createdAt',
|
|
1504
|
+
type: 'date',
|
|
1505
|
+
required: true,
|
|
1506
|
+
description: 'API key creation timestamp',
|
|
1507
|
+
},
|
|
1508
|
+
],
|
|
1509
|
+
relationships: [{ type: 'many-to-one', target: 'user', field: 'userId' }],
|
|
1510
|
+
},
|
|
1511
|
+
},
|
|
1512
|
+
userExtensions: {
|
|
1513
|
+
relationships: [{ type: 'one-to-many', target: 'apiKey', field: 'userId' }],
|
|
1514
|
+
},
|
|
1515
|
+
},
|
|
1516
|
+
passkey: {
|
|
1517
|
+
tables: {
|
|
1518
|
+
passkey: {
|
|
1519
|
+
name: 'passkey',
|
|
1520
|
+
displayName: 'Passkey',
|
|
1521
|
+
fields: [
|
|
1522
|
+
{
|
|
1523
|
+
name: 'id',
|
|
1524
|
+
type: 'string',
|
|
1525
|
+
required: true,
|
|
1526
|
+
primaryKey: true,
|
|
1527
|
+
description: 'Unique passkey identifier',
|
|
1528
|
+
},
|
|
1529
|
+
{ name: 'userId', type: 'string', required: true, description: 'Associated user ID' },
|
|
1530
|
+
{ name: 'name', type: 'string', required: true, description: 'Passkey name' },
|
|
1531
|
+
{
|
|
1532
|
+
name: 'credentialId',
|
|
1533
|
+
type: 'string',
|
|
1534
|
+
required: true,
|
|
1535
|
+
unique: true,
|
|
1536
|
+
description: 'WebAuthn credential ID',
|
|
1537
|
+
},
|
|
1538
|
+
{ name: 'publicKey', type: 'string', required: true, description: 'Public key' },
|
|
1539
|
+
{ name: 'counter', type: 'number', required: true, description: 'Usage counter' },
|
|
1540
|
+
{
|
|
1541
|
+
name: 'createdAt',
|
|
1542
|
+
type: 'date',
|
|
1543
|
+
required: true,
|
|
1544
|
+
description: 'Passkey creation timestamp',
|
|
1545
|
+
},
|
|
1546
|
+
{
|
|
1547
|
+
name: 'lastUsedAt',
|
|
1548
|
+
type: 'date',
|
|
1549
|
+
required: false,
|
|
1550
|
+
description: 'Last usage timestamp',
|
|
1551
|
+
},
|
|
1552
|
+
],
|
|
1553
|
+
relationships: [{ type: 'many-to-one', target: 'user', field: 'userId' }],
|
|
1554
|
+
},
|
|
1555
|
+
},
|
|
1556
|
+
userExtensions: {
|
|
1557
|
+
relationships: [{ type: 'one-to-many', target: 'passkey', field: 'userId' }],
|
|
1558
|
+
},
|
|
1559
|
+
},
|
|
1560
|
+
};
|
|
1561
|
+
// Function to generate schema based on selected plugins
|
|
1562
|
+
function generateSchema(selectedPlugins) {
|
|
1563
|
+
const schema = { tables: [] };
|
|
1564
|
+
// Start with base tables (deep clone to avoid mutations)
|
|
1565
|
+
const baseTables = Object.values(BASE_SCHEMA).map((table) => ({
|
|
1566
|
+
...table,
|
|
1567
|
+
fields: [...table.fields],
|
|
1568
|
+
relationships: [...table.relationships],
|
|
1569
|
+
}));
|
|
1570
|
+
schema.tables.push(...baseTables);
|
|
1571
|
+
// Apply plugin extensions
|
|
1572
|
+
selectedPlugins.forEach((pluginName) => {
|
|
1573
|
+
const plugin = PLUGIN_SCHEMAS[pluginName];
|
|
1574
|
+
if (!plugin)
|
|
1575
|
+
return;
|
|
1576
|
+
// Add plugin-specific tables
|
|
1577
|
+
if (plugin.tables) {
|
|
1578
|
+
Object.values(plugin.tables).forEach((table) => {
|
|
1579
|
+
schema.tables.push({
|
|
1580
|
+
...table,
|
|
1581
|
+
fields: [...table.fields],
|
|
1582
|
+
relationships: [...table.relationships],
|
|
1583
|
+
});
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
// Extend existing tables (with duplicate prevention)
|
|
1587
|
+
if ('userExtensions' in plugin && plugin.userExtensions) {
|
|
1588
|
+
const userTable = schema.tables.find((t) => t.name === 'user');
|
|
1589
|
+
if (userTable && 'fields' in plugin.userExtensions) {
|
|
1590
|
+
// Add fields only if they don't already exist
|
|
1591
|
+
(plugin.userExtensions.fields || []).forEach((field) => {
|
|
1592
|
+
if (!userTable.fields.some((f) => f.name === field.name)) {
|
|
1593
|
+
userTable.fields.push(field);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
// Add relationships only if they don't already exist
|
|
1597
|
+
(plugin.userExtensions.relationships || []).forEach((rel) => {
|
|
1598
|
+
if (!userTable.relationships.some((r) => r.target === rel.target && r.field === rel.field && r.type === rel.type)) {
|
|
1599
|
+
userTable.relationships.push(rel);
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
if ('sessionExtensions' in plugin && plugin.sessionExtensions) {
|
|
1605
|
+
const sessionTable = schema.tables.find((t) => t.name === 'session');
|
|
1606
|
+
if (sessionTable && 'fields' in plugin.sessionExtensions) {
|
|
1607
|
+
// Add fields only if they don't already exist
|
|
1608
|
+
(plugin.sessionExtensions.fields || []).forEach((field) => {
|
|
1609
|
+
if (!sessionTable.fields.some((f) => f.name === field.name)) {
|
|
1610
|
+
sessionTable.fields.push(field);
|
|
1611
|
+
}
|
|
1612
|
+
});
|
|
1613
|
+
// Add relationships only if they don't already exist
|
|
1614
|
+
(plugin.sessionExtensions.relationships || []).forEach((rel) => {
|
|
1615
|
+
if (!sessionTable.relationships.some((r) => r.target === rel.target && r.field === rel.field && r.type === rel.type)) {
|
|
1616
|
+
sessionTable.relationships.push(rel);
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
if ('organizationExtensions' in plugin && plugin.organizationExtensions) {
|
|
1622
|
+
const orgTable = schema.tables.find((t) => t.name === 'organization');
|
|
1623
|
+
if (orgTable) {
|
|
1624
|
+
// Add relationships only if they don't already exist
|
|
1625
|
+
(plugin.organizationExtensions.relationships || []).forEach((rel) => {
|
|
1626
|
+
if (!orgTable.relationships.some((r) => r.target === rel.target && r.field === rel.field && r.type === rel.type)) {
|
|
1627
|
+
orgTable.relationships.push(rel);
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
return schema;
|
|
1634
|
+
}
|
|
1635
|
+
router.get('/api/database/schema', async (req, res) => {
|
|
1636
|
+
try {
|
|
1637
|
+
const adapter = await getAuthAdapterWithConfig();
|
|
1638
|
+
const { plugins } = req.query;
|
|
1639
|
+
let selectedPlugins = [];
|
|
1640
|
+
if (plugins && typeof plugins === 'string') {
|
|
1641
|
+
selectedPlugins = plugins.split(',').filter(Boolean);
|
|
1642
|
+
}
|
|
1643
|
+
if (!adapter) {
|
|
1644
|
+
return res.json({
|
|
1645
|
+
schema: null,
|
|
1646
|
+
error: 'Auth adapter not available',
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
const schema = generateSchema(selectedPlugins);
|
|
1650
|
+
res.json({
|
|
1651
|
+
success: true,
|
|
1652
|
+
schema: schema,
|
|
1653
|
+
availablePlugins: Object.keys(PLUGIN_SCHEMAS),
|
|
1654
|
+
selectedPlugins: selectedPlugins,
|
|
1655
|
+
});
|
|
1656
|
+
}
|
|
1657
|
+
catch (error) {
|
|
1658
|
+
console.error('Error fetching database schema:', error);
|
|
1659
|
+
res.status(500).json({
|
|
1660
|
+
success: false,
|
|
1661
|
+
error: 'Failed to fetch database schema',
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1033
1665
|
router.get('/api/plugins/teams/status', async (req, res) => {
|
|
1034
1666
|
try {
|
|
1035
1667
|
const authConfigPath = configPath || (await findAuthConfigPath());
|
|
@@ -1066,7 +1698,8 @@ export function createRoutes(authConfig, configPath, geoDbPath) {
|
|
|
1066
1698
|
});
|
|
1067
1699
|
}
|
|
1068
1700
|
const organizationPlugin = auth.options?.plugins?.find((plugin) => plugin.id === 'organization');
|
|
1069
|
-
const
|
|
1701
|
+
const teamOptions = organizationPlugin.options.teams;
|
|
1702
|
+
const teamsEnabled = teamOptions?.enabled;
|
|
1070
1703
|
res.json({
|
|
1071
1704
|
enabled: teamsEnabled,
|
|
1072
1705
|
configPath: authConfigPath,
|