@executor-js/emulate 0.6.0 → 0.7.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.
- package/dist/api.d.ts +333 -3
- package/dist/api.js +125 -13
- package/dist/api.js.map +1 -1
- package/dist/{dist-YPRJYQHW.js → dist-FE2JWST3.js} +846 -234
- package/dist/dist-FE2JWST3.js.map +1 -0
- package/dist/{dist-K4CVTD6K.js → dist-KBZ6SM7D.js} +357 -12
- package/dist/dist-KBZ6SM7D.js.map +1 -0
- package/dist/{dist-RMPDKZUA.js → dist-OT6R2YO2.js} +440 -81
- package/dist/dist-OT6R2YO2.js.map +1 -0
- package/dist/{dist-WBKONLOE.js → dist-OVTPVMMW.js} +636 -165
- package/dist/dist-OVTPVMMW.js.map +1 -0
- package/dist/{dist-BTEY33DJ.js → dist-QXFWC3LV.js} +567 -75
- package/dist/dist-QXFWC3LV.js.map +1 -0
- package/dist/{dist-IYZPDKJW.js → dist-S47YJ552.js} +543 -43
- package/dist/dist-S47YJ552.js.map +1 -0
- package/dist/{dist-XM5HSBDC.js → dist-TWJXVA7X.js} +268 -30
- package/dist/dist-TWJXVA7X.js.map +1 -0
- package/dist/{dist-JJ2ZRCAX.js → dist-YXHZTLFR.js} +138 -7
- package/dist/dist-YXHZTLFR.js.map +1 -0
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -7
- package/dist/dist-BTEY33DJ.js.map +0 -1
- package/dist/dist-IYZPDKJW.js.map +0 -1
- package/dist/dist-JJ2ZRCAX.js.map +0 -1
- package/dist/dist-K4CVTD6K.js.map +0 -1
- package/dist/dist-RMPDKZUA.js.map +0 -1
- package/dist/dist-WBKONLOE.js.map +0 -1
- package/dist/dist-XM5HSBDC.js.map +0 -1
- package/dist/dist-YPRJYQHW.js.map +0 -1
|
@@ -427,14 +427,14 @@ function getPendingCodes(store) {
|
|
|
427
427
|
function isCodeExpired(code) {
|
|
428
428
|
return Date.now() - code.createdAt > CODE_TTL_MS;
|
|
429
429
|
}
|
|
430
|
-
async function createSessionToken(store, user,
|
|
430
|
+
async function createSessionToken(store, user, sessionId2, baseUrl, orgId2, orgRole, orgSlug, orgPermissions) {
|
|
431
431
|
const { privateKey } = await keyPairPromise;
|
|
432
432
|
const now = Math.floor(Date.now() / 1e3);
|
|
433
433
|
const claims = {
|
|
434
|
-
sid:
|
|
434
|
+
sid: sessionId2
|
|
435
435
|
};
|
|
436
|
-
if (
|
|
437
|
-
claims.org_id =
|
|
436
|
+
if (orgId2) {
|
|
437
|
+
claims.org_id = orgId2;
|
|
438
438
|
claims.org_role = orgRole ?? "org:member";
|
|
439
439
|
claims.org_slug = orgSlug;
|
|
440
440
|
claims.org_permissions = orgPermissions ?? [];
|
|
@@ -690,10 +690,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
690
690
|
if (!user) return c.json({ error: "invalid_grant", error_description: "Unknown user." }, 400);
|
|
691
691
|
getPendingCodes(store).delete(code);
|
|
692
692
|
const { generateClerkId: generateClerkId2, nowUnix: nowUnix2 } = await import("./helpers-LXLP3DFE-LBOTATT5.js");
|
|
693
|
-
const
|
|
693
|
+
const sessionId2 = generateClerkId2("sess_");
|
|
694
694
|
const now = nowUnix2();
|
|
695
695
|
clerkStore.sessions.insert({
|
|
696
|
-
clerk_id:
|
|
696
|
+
clerk_id: sessionId2,
|
|
697
697
|
user_id: user.clerk_id,
|
|
698
698
|
client_id: clientId || "default",
|
|
699
699
|
status: "active",
|
|
@@ -714,7 +714,7 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
714
714
|
const emails = clerkStore.emailAddresses.findBy("user_id", user.clerk_id);
|
|
715
715
|
const primaryEmail = emails.find((e) => e.is_primary) ?? emails[0];
|
|
716
716
|
const idToken = await new SignJWT({
|
|
717
|
-
sid:
|
|
717
|
+
sid: sessionId2,
|
|
718
718
|
email: primaryEmail?.email_address,
|
|
719
719
|
email_verified: primaryEmail?.verification_status === "verified",
|
|
720
720
|
name: [user.first_name, user.last_name].filter(Boolean).join(" ") || void 0
|
|
@@ -791,17 +791,17 @@ function deletedResponse(objectType, objectId) {
|
|
|
791
791
|
deleted: true
|
|
792
792
|
};
|
|
793
793
|
}
|
|
794
|
-
function paginatedResponse(data, totalCount,
|
|
794
|
+
function paginatedResponse(data, totalCount, limit2, offset2) {
|
|
795
795
|
return {
|
|
796
796
|
data,
|
|
797
797
|
total_count: totalCount,
|
|
798
|
-
has_more:
|
|
798
|
+
has_more: offset2 + limit2 < totalCount
|
|
799
799
|
};
|
|
800
800
|
}
|
|
801
801
|
function parsePagination(c) {
|
|
802
|
-
const
|
|
803
|
-
const
|
|
804
|
-
return { limit, offset };
|
|
802
|
+
const limit2 = Math.min(Math.max(Number.parseInt(c.req.query("limit") ?? "10", 10) || 10, 1), 500);
|
|
803
|
+
const offset2 = Math.max(Number.parseInt(c.req.query("offset") ?? "0", 10) || 0, 0);
|
|
804
|
+
return { limit: limit2, offset: offset2 };
|
|
805
805
|
}
|
|
806
806
|
function userResponse(user, emailAddresses) {
|
|
807
807
|
return {
|
|
@@ -932,7 +932,7 @@ function userRoutes({ app, store, tokenMap }) {
|
|
|
932
932
|
app.get("/v1/users", (c) => {
|
|
933
933
|
const auth = requireSecretKey(c, tokenMap);
|
|
934
934
|
if (isAuthResponse(auth)) return auth;
|
|
935
|
-
const { limit, offset } = parsePagination(c);
|
|
935
|
+
const { limit: limit2, offset: offset2 } = parsePagination(c);
|
|
936
936
|
const query = c.req.query("query");
|
|
937
937
|
const orderBy = c.req.query("order_by") ?? "-created_at";
|
|
938
938
|
const emailFilter = c.req.queries("email_address");
|
|
@@ -959,12 +959,12 @@ function userRoutes({ app, store, tokenMap }) {
|
|
|
959
959
|
return desc ? bVal - aVal : aVal - bVal;
|
|
960
960
|
});
|
|
961
961
|
const totalCount = users.length;
|
|
962
|
-
const paged = users.slice(
|
|
962
|
+
const paged = users.slice(offset2, offset2 + limit2);
|
|
963
963
|
const data = paged.map((u) => {
|
|
964
964
|
const emails = cs.emailAddresses.findBy("user_id", u.clerk_id);
|
|
965
965
|
return userResponse(u, emails);
|
|
966
966
|
});
|
|
967
|
-
return c.json(paginatedResponse(data, totalCount,
|
|
967
|
+
return c.json(paginatedResponse(data, totalCount, limit2, offset2));
|
|
968
968
|
});
|
|
969
969
|
app.get("/v1/users/count", (c) => {
|
|
970
970
|
const auth = requireSecretKey(c, tokenMap);
|
|
@@ -974,8 +974,8 @@ function userRoutes({ app, store, tokenMap }) {
|
|
|
974
974
|
app.get("/v1/users/:userId", (c) => {
|
|
975
975
|
const auth = requireSecretKey(c, tokenMap);
|
|
976
976
|
if (isAuthResponse(auth)) return auth;
|
|
977
|
-
const
|
|
978
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
977
|
+
const userId2 = c.req.param("userId");
|
|
978
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
979
979
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
980
980
|
const emails = cs.emailAddresses.findBy("user_id", user.clerk_id);
|
|
981
981
|
return c.json(userResponse(user, emails));
|
|
@@ -1038,8 +1038,8 @@ function userRoutes({ app, store, tokenMap }) {
|
|
|
1038
1038
|
app.patch("/v1/users/:userId", async (c) => {
|
|
1039
1039
|
const auth = requireSecretKey(c, tokenMap);
|
|
1040
1040
|
if (isAuthResponse(auth)) return auth;
|
|
1041
|
-
const
|
|
1042
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1041
|
+
const userId2 = c.req.param("userId");
|
|
1042
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1043
1043
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1044
1044
|
const body = await readJsonBody(c);
|
|
1045
1045
|
const now = nowUnix();
|
|
@@ -1060,79 +1060,79 @@ function userRoutes({ app, store, tokenMap }) {
|
|
|
1060
1060
|
patch.password_hash = body.password;
|
|
1061
1061
|
}
|
|
1062
1062
|
cs.users.update(user.id, patch);
|
|
1063
|
-
const updated = cs.users.findOneBy("clerk_id",
|
|
1064
|
-
const emails = cs.emailAddresses.findBy("user_id",
|
|
1063
|
+
const updated = cs.users.findOneBy("clerk_id", userId2);
|
|
1064
|
+
const emails = cs.emailAddresses.findBy("user_id", userId2);
|
|
1065
1065
|
return c.json(userResponse(updated, emails));
|
|
1066
1066
|
});
|
|
1067
1067
|
app.delete("/v1/users/:userId", (c) => {
|
|
1068
1068
|
const auth = requireSecretKey(c, tokenMap);
|
|
1069
1069
|
if (isAuthResponse(auth)) return auth;
|
|
1070
|
-
const
|
|
1071
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1070
|
+
const userId2 = c.req.param("userId");
|
|
1071
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1072
1072
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1073
|
-
for (const email of cs.emailAddresses.findBy("user_id",
|
|
1073
|
+
for (const email of cs.emailAddresses.findBy("user_id", userId2)) {
|
|
1074
1074
|
cs.emailAddresses.delete(email.id);
|
|
1075
1075
|
}
|
|
1076
|
-
for (const membership of cs.memberships.findBy("user_id",
|
|
1076
|
+
for (const membership of cs.memberships.findBy("user_id", userId2)) {
|
|
1077
1077
|
cs.memberships.delete(membership.id);
|
|
1078
1078
|
const org = cs.organizations.findOneBy("clerk_id", membership.org_id);
|
|
1079
1079
|
if (org) cs.organizations.update(org.id, { members_count: Math.max(0, org.members_count - 1) });
|
|
1080
1080
|
}
|
|
1081
|
-
for (const session of cs.sessions.findBy("user_id",
|
|
1081
|
+
for (const session of cs.sessions.findBy("user_id", userId2)) {
|
|
1082
1082
|
cs.sessions.delete(session.id);
|
|
1083
1083
|
}
|
|
1084
1084
|
cs.users.delete(user.id);
|
|
1085
|
-
return c.json(deletedResponse("user",
|
|
1085
|
+
return c.json(deletedResponse("user", userId2));
|
|
1086
1086
|
});
|
|
1087
1087
|
app.post("/v1/users/:userId/ban", (c) => {
|
|
1088
1088
|
const auth = requireSecretKey(c, tokenMap);
|
|
1089
1089
|
if (isAuthResponse(auth)) return auth;
|
|
1090
|
-
const
|
|
1091
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1090
|
+
const userId2 = c.req.param("userId");
|
|
1091
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1092
1092
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1093
1093
|
cs.users.update(user.id, { banned: true, updated_at_unix: nowUnix() });
|
|
1094
|
-
const updated = cs.users.findOneBy("clerk_id",
|
|
1095
|
-
const emails = cs.emailAddresses.findBy("user_id",
|
|
1094
|
+
const updated = cs.users.findOneBy("clerk_id", userId2);
|
|
1095
|
+
const emails = cs.emailAddresses.findBy("user_id", userId2);
|
|
1096
1096
|
return c.json(userResponse(updated, emails));
|
|
1097
1097
|
});
|
|
1098
1098
|
app.post("/v1/users/:userId/unban", (c) => {
|
|
1099
1099
|
const auth = requireSecretKey(c, tokenMap);
|
|
1100
1100
|
if (isAuthResponse(auth)) return auth;
|
|
1101
|
-
const
|
|
1102
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1101
|
+
const userId2 = c.req.param("userId");
|
|
1102
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1103
1103
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1104
1104
|
cs.users.update(user.id, { banned: false, updated_at_unix: nowUnix() });
|
|
1105
|
-
const updated = cs.users.findOneBy("clerk_id",
|
|
1106
|
-
const emails = cs.emailAddresses.findBy("user_id",
|
|
1105
|
+
const updated = cs.users.findOneBy("clerk_id", userId2);
|
|
1106
|
+
const emails = cs.emailAddresses.findBy("user_id", userId2);
|
|
1107
1107
|
return c.json(userResponse(updated, emails));
|
|
1108
1108
|
});
|
|
1109
1109
|
app.post("/v1/users/:userId/lock", (c) => {
|
|
1110
1110
|
const auth = requireSecretKey(c, tokenMap);
|
|
1111
1111
|
if (isAuthResponse(auth)) return auth;
|
|
1112
|
-
const
|
|
1113
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1112
|
+
const userId2 = c.req.param("userId");
|
|
1113
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1114
1114
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1115
1115
|
cs.users.update(user.id, { locked: true, updated_at_unix: nowUnix() });
|
|
1116
|
-
const updated = cs.users.findOneBy("clerk_id",
|
|
1117
|
-
const emails = cs.emailAddresses.findBy("user_id",
|
|
1116
|
+
const updated = cs.users.findOneBy("clerk_id", userId2);
|
|
1117
|
+
const emails = cs.emailAddresses.findBy("user_id", userId2);
|
|
1118
1118
|
return c.json(userResponse(updated, emails));
|
|
1119
1119
|
});
|
|
1120
1120
|
app.post("/v1/users/:userId/unlock", (c) => {
|
|
1121
1121
|
const auth = requireSecretKey(c, tokenMap);
|
|
1122
1122
|
if (isAuthResponse(auth)) return auth;
|
|
1123
|
-
const
|
|
1124
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1123
|
+
const userId2 = c.req.param("userId");
|
|
1124
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1125
1125
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1126
1126
|
cs.users.update(user.id, { locked: false, updated_at_unix: nowUnix() });
|
|
1127
|
-
const updated = cs.users.findOneBy("clerk_id",
|
|
1128
|
-
const emails = cs.emailAddresses.findBy("user_id",
|
|
1127
|
+
const updated = cs.users.findOneBy("clerk_id", userId2);
|
|
1128
|
+
const emails = cs.emailAddresses.findBy("user_id", userId2);
|
|
1129
1129
|
return c.json(userResponse(updated, emails));
|
|
1130
1130
|
});
|
|
1131
1131
|
app.patch("/v1/users/:userId/metadata", async (c) => {
|
|
1132
1132
|
const auth = requireSecretKey(c, tokenMap);
|
|
1133
1133
|
if (isAuthResponse(auth)) return auth;
|
|
1134
|
-
const
|
|
1135
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1134
|
+
const userId2 = c.req.param("userId");
|
|
1135
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1136
1136
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1137
1137
|
const body = await readJsonBody(c);
|
|
1138
1138
|
const patch = { updated_at_unix: nowUnix() };
|
|
@@ -1146,15 +1146,15 @@ function userRoutes({ app, store, tokenMap }) {
|
|
|
1146
1146
|
patch.unsafe_metadata = { ...user.unsafe_metadata, ...body.unsafe_metadata };
|
|
1147
1147
|
}
|
|
1148
1148
|
cs.users.update(user.id, patch);
|
|
1149
|
-
const updated = cs.users.findOneBy("clerk_id",
|
|
1150
|
-
const emails = cs.emailAddresses.findBy("user_id",
|
|
1149
|
+
const updated = cs.users.findOneBy("clerk_id", userId2);
|
|
1150
|
+
const emails = cs.emailAddresses.findBy("user_id", userId2);
|
|
1151
1151
|
return c.json(userResponse(updated, emails));
|
|
1152
1152
|
});
|
|
1153
1153
|
app.post("/v1/users/:userId/verify_password", async (c) => {
|
|
1154
1154
|
const auth = requireSecretKey(c, tokenMap);
|
|
1155
1155
|
if (isAuthResponse(auth)) return auth;
|
|
1156
|
-
const
|
|
1157
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1156
|
+
const userId2 = c.req.param("userId");
|
|
1157
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1158
1158
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1159
1159
|
const body = await readJsonBody(c);
|
|
1160
1160
|
const password = body.password;
|
|
@@ -1167,8 +1167,8 @@ function emailAddressRoutes({ app, store, tokenMap }) {
|
|
|
1167
1167
|
app.get("/v1/email_addresses/:emailId", (c) => {
|
|
1168
1168
|
const auth = requireSecretKey(c, tokenMap);
|
|
1169
1169
|
if (isAuthResponse(auth)) return auth;
|
|
1170
|
-
const
|
|
1171
|
-
const email = cs.emailAddresses.findOneBy("email_id",
|
|
1170
|
+
const emailId2 = c.req.param("emailId");
|
|
1171
|
+
const email = cs.emailAddresses.findOneBy("email_id", emailId2);
|
|
1172
1172
|
if (!email) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Email address not found");
|
|
1173
1173
|
return c.json(emailAddressResponse(email));
|
|
1174
1174
|
});
|
|
@@ -1176,20 +1176,20 @@ function emailAddressRoutes({ app, store, tokenMap }) {
|
|
|
1176
1176
|
const auth = requireSecretKey(c, tokenMap);
|
|
1177
1177
|
if (isAuthResponse(auth)) return auth;
|
|
1178
1178
|
const body = await readJsonBody(c);
|
|
1179
|
-
const
|
|
1179
|
+
const userId2 = body.user_id;
|
|
1180
1180
|
const emailAddr = body.email_address;
|
|
1181
1181
|
const verified = body.verified ?? false;
|
|
1182
1182
|
const primary = body.primary ?? false;
|
|
1183
|
-
if (!
|
|
1183
|
+
if (!userId2 || !emailAddr) {
|
|
1184
1184
|
return clerkError(c, 422, "INVALID_REQUEST_BODY", "user_id and email_address are required");
|
|
1185
1185
|
}
|
|
1186
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1186
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1187
1187
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1188
1188
|
const now = nowUnix();
|
|
1189
1189
|
const email = cs.emailAddresses.insert({
|
|
1190
1190
|
email_id: generateClerkId("idn_"),
|
|
1191
1191
|
email_address: emailAddr,
|
|
1192
|
-
user_id:
|
|
1192
|
+
user_id: userId2,
|
|
1193
1193
|
verification_status: verified ? "verified" : "unverified",
|
|
1194
1194
|
verification_strategy: "email_code",
|
|
1195
1195
|
is_primary: primary,
|
|
@@ -1198,7 +1198,7 @@ function emailAddressRoutes({ app, store, tokenMap }) {
|
|
|
1198
1198
|
updated_at_unix: now
|
|
1199
1199
|
});
|
|
1200
1200
|
if (primary) {
|
|
1201
|
-
for (const existing of cs.emailAddresses.findBy("user_id",
|
|
1201
|
+
for (const existing of cs.emailAddresses.findBy("user_id", userId2)) {
|
|
1202
1202
|
if (existing.email_id !== email.email_id && existing.is_primary) {
|
|
1203
1203
|
cs.emailAddresses.update(existing.id, { is_primary: false });
|
|
1204
1204
|
}
|
|
@@ -1210,8 +1210,8 @@ function emailAddressRoutes({ app, store, tokenMap }) {
|
|
|
1210
1210
|
app.patch("/v1/email_addresses/:emailId", async (c) => {
|
|
1211
1211
|
const auth = requireSecretKey(c, tokenMap);
|
|
1212
1212
|
if (isAuthResponse(auth)) return auth;
|
|
1213
|
-
const
|
|
1214
|
-
const email = cs.emailAddresses.findOneBy("email_id",
|
|
1213
|
+
const emailId2 = c.req.param("emailId");
|
|
1214
|
+
const email = cs.emailAddresses.findOneBy("email_id", emailId2);
|
|
1215
1215
|
if (!email) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Email address not found");
|
|
1216
1216
|
const body = await readJsonBody(c);
|
|
1217
1217
|
const now = nowUnix();
|
|
@@ -1222,22 +1222,22 @@ function emailAddressRoutes({ app, store, tokenMap }) {
|
|
|
1222
1222
|
if (body.primary === true) {
|
|
1223
1223
|
patch.is_primary = true;
|
|
1224
1224
|
for (const existing of cs.emailAddresses.findBy("user_id", email.user_id)) {
|
|
1225
|
-
if (existing.email_id !==
|
|
1225
|
+
if (existing.email_id !== emailId2 && existing.is_primary) {
|
|
1226
1226
|
cs.emailAddresses.update(existing.id, { is_primary: false });
|
|
1227
1227
|
}
|
|
1228
1228
|
}
|
|
1229
1229
|
const user = cs.users.findOneBy("clerk_id", email.user_id);
|
|
1230
|
-
if (user) cs.users.update(user.id, { primary_email_address_id:
|
|
1230
|
+
if (user) cs.users.update(user.id, { primary_email_address_id: emailId2, updated_at_unix: now });
|
|
1231
1231
|
}
|
|
1232
1232
|
cs.emailAddresses.update(email.id, patch);
|
|
1233
|
-
const updated = cs.emailAddresses.findOneBy("email_id",
|
|
1233
|
+
const updated = cs.emailAddresses.findOneBy("email_id", emailId2);
|
|
1234
1234
|
return c.json(emailAddressResponse(updated));
|
|
1235
1235
|
});
|
|
1236
1236
|
app.delete("/v1/email_addresses/:emailId", (c) => {
|
|
1237
1237
|
const auth = requireSecretKey(c, tokenMap);
|
|
1238
1238
|
if (isAuthResponse(auth)) return auth;
|
|
1239
|
-
const
|
|
1240
|
-
const email = cs.emailAddresses.findOneBy("email_id",
|
|
1239
|
+
const emailId2 = c.req.param("emailId");
|
|
1240
|
+
const email = cs.emailAddresses.findOneBy("email_id", emailId2);
|
|
1241
1241
|
if (!email) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Email address not found");
|
|
1242
1242
|
cs.emailAddresses.delete(email.id);
|
|
1243
1243
|
if (email.is_primary) {
|
|
@@ -1253,7 +1253,7 @@ function emailAddressRoutes({ app, store, tokenMap }) {
|
|
|
1253
1253
|
}
|
|
1254
1254
|
}
|
|
1255
1255
|
}
|
|
1256
|
-
return c.json(deletedResponse("email_address",
|
|
1256
|
+
return c.json(deletedResponse("email_address", emailId2));
|
|
1257
1257
|
});
|
|
1258
1258
|
}
|
|
1259
1259
|
function organizationRoutes({ app, store, tokenMap }) {
|
|
@@ -1261,7 +1261,7 @@ function organizationRoutes({ app, store, tokenMap }) {
|
|
|
1261
1261
|
app.get("/v1/organizations", (c) => {
|
|
1262
1262
|
const auth = requireSecretKey(c, tokenMap);
|
|
1263
1263
|
if (isAuthResponse(auth)) return auth;
|
|
1264
|
-
const { limit, offset } = parsePagination(c);
|
|
1264
|
+
const { limit: limit2, offset: offset2 } = parsePagination(c);
|
|
1265
1265
|
const query = c.req.query("query");
|
|
1266
1266
|
let orgs = cs.organizations.all();
|
|
1267
1267
|
if (query) {
|
|
@@ -1270,14 +1270,14 @@ function organizationRoutes({ app, store, tokenMap }) {
|
|
|
1270
1270
|
}
|
|
1271
1271
|
orgs.sort((a, b) => b.created_at_unix - a.created_at_unix);
|
|
1272
1272
|
const totalCount = orgs.length;
|
|
1273
|
-
const paged = orgs.slice(
|
|
1274
|
-
return c.json(paginatedResponse(paged.map(organizationResponse), totalCount,
|
|
1273
|
+
const paged = orgs.slice(offset2, offset2 + limit2);
|
|
1274
|
+
return c.json(paginatedResponse(paged.map(organizationResponse), totalCount, limit2, offset2));
|
|
1275
1275
|
});
|
|
1276
1276
|
app.get("/v1/organizations/:orgId", (c) => {
|
|
1277
1277
|
const auth = requireSecretKey(c, tokenMap);
|
|
1278
1278
|
if (isAuthResponse(auth)) return auth;
|
|
1279
|
-
const
|
|
1280
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1279
|
+
const orgId2 = c.req.param("orgId");
|
|
1280
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2) ?? cs.organizations.findOneBy("slug", orgId2);
|
|
1281
1281
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1282
1282
|
return c.json(organizationResponse(org));
|
|
1283
1283
|
});
|
|
@@ -1305,13 +1305,13 @@ function organizationRoutes({ app, store, tokenMap }) {
|
|
|
1305
1305
|
updated_at_unix: now
|
|
1306
1306
|
});
|
|
1307
1307
|
if (body.created_by) {
|
|
1308
|
-
const
|
|
1309
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1308
|
+
const userId2 = body.created_by;
|
|
1309
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1310
1310
|
if (user) {
|
|
1311
1311
|
cs.memberships.insert({
|
|
1312
1312
|
membership_id: generateClerkId("orgmem_"),
|
|
1313
1313
|
org_id: org.clerk_id,
|
|
1314
|
-
user_id:
|
|
1314
|
+
user_id: userId2,
|
|
1315
1315
|
role: "org:admin",
|
|
1316
1316
|
permissions: [
|
|
1317
1317
|
"org:sys_profile:manage",
|
|
@@ -1335,8 +1335,8 @@ function organizationRoutes({ app, store, tokenMap }) {
|
|
|
1335
1335
|
app.patch("/v1/organizations/:orgId", async (c) => {
|
|
1336
1336
|
const auth = requireSecretKey(c, tokenMap);
|
|
1337
1337
|
if (isAuthResponse(auth)) return auth;
|
|
1338
|
-
const
|
|
1339
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1338
|
+
const orgId2 = c.req.param("orgId");
|
|
1339
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1340
1340
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1341
1341
|
const body = await readJsonBody(c);
|
|
1342
1342
|
const now = nowUnix();
|
|
@@ -1348,25 +1348,25 @@ function organizationRoutes({ app, store, tokenMap }) {
|
|
|
1348
1348
|
if (body.max_allowed_memberships !== void 0) patch.max_allowed_memberships = body.max_allowed_memberships;
|
|
1349
1349
|
if (body.admin_delete_enabled !== void 0) patch.admin_delete_enabled = body.admin_delete_enabled;
|
|
1350
1350
|
cs.organizations.update(org.id, patch);
|
|
1351
|
-
const updated = cs.organizations.findOneBy("clerk_id",
|
|
1351
|
+
const updated = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1352
1352
|
return c.json(organizationResponse(updated));
|
|
1353
1353
|
});
|
|
1354
1354
|
app.delete("/v1/organizations/:orgId", (c) => {
|
|
1355
1355
|
const auth = requireSecretKey(c, tokenMap);
|
|
1356
1356
|
if (isAuthResponse(auth)) return auth;
|
|
1357
|
-
const
|
|
1358
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1357
|
+
const orgId2 = c.req.param("orgId");
|
|
1358
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1359
1359
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1360
|
-
for (const m of cs.memberships.findBy("org_id",
|
|
1361
|
-
for (const inv of cs.invitations.findBy("org_id",
|
|
1360
|
+
for (const m of cs.memberships.findBy("org_id", orgId2)) cs.memberships.delete(m.id);
|
|
1361
|
+
for (const inv of cs.invitations.findBy("org_id", orgId2)) cs.invitations.delete(inv.id);
|
|
1362
1362
|
cs.organizations.delete(org.id);
|
|
1363
|
-
return c.json(deletedResponse("organization",
|
|
1363
|
+
return c.json(deletedResponse("organization", orgId2));
|
|
1364
1364
|
});
|
|
1365
1365
|
app.patch("/v1/organizations/:orgId/metadata", async (c) => {
|
|
1366
1366
|
const auth = requireSecretKey(c, tokenMap);
|
|
1367
1367
|
if (isAuthResponse(auth)) return auth;
|
|
1368
|
-
const
|
|
1369
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1368
|
+
const orgId2 = c.req.param("orgId");
|
|
1369
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1370
1370
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1371
1371
|
const body = await readJsonBody(c);
|
|
1372
1372
|
const now = nowUnix();
|
|
@@ -1378,7 +1378,7 @@ function organizationRoutes({ app, store, tokenMap }) {
|
|
|
1378
1378
|
patch.private_metadata = { ...org.private_metadata, ...body.private_metadata };
|
|
1379
1379
|
}
|
|
1380
1380
|
cs.organizations.update(org.id, patch);
|
|
1381
|
-
const updated = cs.organizations.findOneBy("clerk_id",
|
|
1381
|
+
const updated = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1382
1382
|
return c.json(organizationResponse(updated));
|
|
1383
1383
|
});
|
|
1384
1384
|
}
|
|
@@ -1400,43 +1400,43 @@ function membershipRoutes({ app, store, tokenMap }) {
|
|
|
1400
1400
|
app.get("/v1/organizations/:orgId/memberships", (c) => {
|
|
1401
1401
|
const auth = requireSecretKey(c, tokenMap);
|
|
1402
1402
|
if (isAuthResponse(auth)) return auth;
|
|
1403
|
-
const
|
|
1404
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1403
|
+
const orgId2 = c.req.param("orgId");
|
|
1404
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1405
1405
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1406
|
-
const { limit, offset } = parsePagination(c);
|
|
1406
|
+
const { limit: limit2, offset: offset2 } = parsePagination(c);
|
|
1407
1407
|
const roleFilter = c.req.query("role");
|
|
1408
|
-
let memberships = cs.memberships.findBy("org_id",
|
|
1408
|
+
let memberships = cs.memberships.findBy("org_id", orgId2);
|
|
1409
1409
|
if (roleFilter) {
|
|
1410
1410
|
memberships = memberships.filter((m) => m.role === roleFilter);
|
|
1411
1411
|
}
|
|
1412
1412
|
const totalCount = memberships.length;
|
|
1413
|
-
const paged = memberships.slice(
|
|
1413
|
+
const paged = memberships.slice(offset2, offset2 + limit2);
|
|
1414
1414
|
const data = paged.map((m) => {
|
|
1415
1415
|
const user = cs.users.findOneBy("clerk_id", m.user_id);
|
|
1416
1416
|
const emails = user ? cs.emailAddresses.findBy("user_id", user.clerk_id) : [];
|
|
1417
1417
|
return membershipResponse(m, org, user, emails);
|
|
1418
1418
|
});
|
|
1419
|
-
return c.json(paginatedResponse(data, totalCount,
|
|
1419
|
+
return c.json(paginatedResponse(data, totalCount, limit2, offset2));
|
|
1420
1420
|
});
|
|
1421
1421
|
app.post("/v1/organizations/:orgId/memberships", async (c) => {
|
|
1422
1422
|
const auth = requireSecretKey(c, tokenMap);
|
|
1423
1423
|
if (isAuthResponse(auth)) return auth;
|
|
1424
|
-
const
|
|
1425
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1424
|
+
const orgId2 = c.req.param("orgId");
|
|
1425
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1426
1426
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1427
1427
|
const body = await readJsonBody(c);
|
|
1428
|
-
const
|
|
1428
|
+
const userId2 = body.user_id;
|
|
1429
1429
|
const role = body.role ?? "org:member";
|
|
1430
|
-
if (!
|
|
1431
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1430
|
+
if (!userId2) return clerkError(c, 422, "INVALID_REQUEST_BODY", "user_id is required");
|
|
1431
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1432
1432
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1433
|
-
const existing = cs.memberships.findBy("org_id",
|
|
1433
|
+
const existing = cs.memberships.findBy("org_id", orgId2).find((m) => m.user_id === userId2);
|
|
1434
1434
|
if (existing) return clerkError(c, 422, "DUPLICATE_RECORD", "User is already a member of this organization");
|
|
1435
1435
|
const now = nowUnix();
|
|
1436
1436
|
const membership = cs.memberships.insert({
|
|
1437
1437
|
membership_id: generateClerkId("orgmem_"),
|
|
1438
|
-
org_id:
|
|
1439
|
-
user_id:
|
|
1438
|
+
org_id: orgId2,
|
|
1439
|
+
user_id: userId2,
|
|
1440
1440
|
role,
|
|
1441
1441
|
permissions: defaultPermissions(role),
|
|
1442
1442
|
public_metadata: {},
|
|
@@ -1445,18 +1445,18 @@ function membershipRoutes({ app, store, tokenMap }) {
|
|
|
1445
1445
|
updated_at_unix: now
|
|
1446
1446
|
});
|
|
1447
1447
|
cs.organizations.update(org.id, { members_count: org.members_count + 1, updated_at_unix: now });
|
|
1448
|
-
const emails = cs.emailAddresses.findBy("user_id",
|
|
1449
|
-
const updatedOrg = cs.organizations.findOneBy("clerk_id",
|
|
1448
|
+
const emails = cs.emailAddresses.findBy("user_id", userId2);
|
|
1449
|
+
const updatedOrg = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1450
1450
|
return c.json(membershipResponse(membership, updatedOrg, user, emails), 200);
|
|
1451
1451
|
});
|
|
1452
1452
|
app.patch("/v1/organizations/:orgId/memberships/:userId", async (c) => {
|
|
1453
1453
|
const auth = requireSecretKey(c, tokenMap);
|
|
1454
1454
|
if (isAuthResponse(auth)) return auth;
|
|
1455
|
-
const
|
|
1456
|
-
const
|
|
1457
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1455
|
+
const orgId2 = c.req.param("orgId");
|
|
1456
|
+
const userId2 = c.req.param("userId");
|
|
1457
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1458
1458
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1459
|
-
const membership = cs.memberships.findBy("org_id",
|
|
1459
|
+
const membership = cs.memberships.findBy("org_id", orgId2).find((m) => m.user_id === userId2);
|
|
1460
1460
|
if (!membership) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Membership not found");
|
|
1461
1461
|
const body = await readJsonBody(c);
|
|
1462
1462
|
const now = nowUnix();
|
|
@@ -1466,19 +1466,19 @@ function membershipRoutes({ app, store, tokenMap }) {
|
|
|
1466
1466
|
patch.permissions = defaultPermissions(body.role);
|
|
1467
1467
|
}
|
|
1468
1468
|
cs.memberships.update(membership.id, patch);
|
|
1469
|
-
const updated = cs.memberships.findBy("org_id",
|
|
1470
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1471
|
-
const emails = user ? cs.emailAddresses.findBy("user_id",
|
|
1469
|
+
const updated = cs.memberships.findBy("org_id", orgId2).find((m) => m.user_id === userId2);
|
|
1470
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1471
|
+
const emails = user ? cs.emailAddresses.findBy("user_id", userId2) : [];
|
|
1472
1472
|
return c.json(membershipResponse(updated, org, user, emails));
|
|
1473
1473
|
});
|
|
1474
1474
|
app.delete("/v1/organizations/:orgId/memberships/:userId", (c) => {
|
|
1475
1475
|
const auth = requireSecretKey(c, tokenMap);
|
|
1476
1476
|
if (isAuthResponse(auth)) return auth;
|
|
1477
|
-
const
|
|
1478
|
-
const
|
|
1479
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1477
|
+
const orgId2 = c.req.param("orgId");
|
|
1478
|
+
const userId2 = c.req.param("userId");
|
|
1479
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1480
1480
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1481
|
-
const membership = cs.memberships.findBy("org_id",
|
|
1481
|
+
const membership = cs.memberships.findBy("org_id", orgId2).find((m) => m.user_id === userId2);
|
|
1482
1482
|
if (!membership) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Membership not found");
|
|
1483
1483
|
cs.memberships.delete(membership.id);
|
|
1484
1484
|
cs.organizations.update(org.id, { members_count: Math.max(0, org.members_count - 1), updated_at_unix: nowUnix() });
|
|
@@ -1487,11 +1487,11 @@ function membershipRoutes({ app, store, tokenMap }) {
|
|
|
1487
1487
|
app.patch("/v1/organizations/:orgId/memberships/:userId/metadata", async (c) => {
|
|
1488
1488
|
const auth = requireSecretKey(c, tokenMap);
|
|
1489
1489
|
if (isAuthResponse(auth)) return auth;
|
|
1490
|
-
const
|
|
1491
|
-
const
|
|
1492
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1490
|
+
const orgId2 = c.req.param("orgId");
|
|
1491
|
+
const userId2 = c.req.param("userId");
|
|
1492
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1493
1493
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1494
|
-
const membership = cs.memberships.findBy("org_id",
|
|
1494
|
+
const membership = cs.memberships.findBy("org_id", orgId2).find((m) => m.user_id === userId2);
|
|
1495
1495
|
if (!membership) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Membership not found");
|
|
1496
1496
|
const body = await readJsonBody(c);
|
|
1497
1497
|
const now = nowUnix();
|
|
@@ -1506,9 +1506,9 @@ function membershipRoutes({ app, store, tokenMap }) {
|
|
|
1506
1506
|
};
|
|
1507
1507
|
}
|
|
1508
1508
|
cs.memberships.update(membership.id, patch);
|
|
1509
|
-
const updated = cs.memberships.findBy("org_id",
|
|
1510
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1511
|
-
const emails = user ? cs.emailAddresses.findBy("user_id",
|
|
1509
|
+
const updated = cs.memberships.findBy("org_id", orgId2).find((m) => m.user_id === userId2);
|
|
1510
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1511
|
+
const emails = user ? cs.emailAddresses.findBy("user_id", userId2) : [];
|
|
1512
1512
|
return c.json(membershipResponse(updated, org, user, emails));
|
|
1513
1513
|
});
|
|
1514
1514
|
}
|
|
@@ -1517,28 +1517,28 @@ function invitationRoutes({ app, store, tokenMap }) {
|
|
|
1517
1517
|
app.get("/v1/organizations/:orgId/invitations", (c) => {
|
|
1518
1518
|
const auth = requireSecretKey(c, tokenMap);
|
|
1519
1519
|
if (isAuthResponse(auth)) return auth;
|
|
1520
|
-
const
|
|
1521
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1520
|
+
const orgId2 = c.req.param("orgId");
|
|
1521
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1522
1522
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1523
|
-
const { limit, offset } = parsePagination(c);
|
|
1523
|
+
const { limit: limit2, offset: offset2 } = parsePagination(c);
|
|
1524
1524
|
const statusFilter = c.req.query("status");
|
|
1525
|
-
let invitations = cs.invitations.findBy("org_id",
|
|
1525
|
+
let invitations = cs.invitations.findBy("org_id", orgId2);
|
|
1526
1526
|
if (statusFilter) {
|
|
1527
1527
|
invitations = invitations.filter((inv) => inv.status === statusFilter);
|
|
1528
1528
|
}
|
|
1529
1529
|
const totalCount = invitations.length;
|
|
1530
|
-
const paged = invitations.slice(
|
|
1531
|
-
return c.json(paginatedResponse(paged.map(invitationResponse), totalCount,
|
|
1530
|
+
const paged = invitations.slice(offset2, offset2 + limit2);
|
|
1531
|
+
return c.json(paginatedResponse(paged.map(invitationResponse), totalCount, limit2, offset2));
|
|
1532
1532
|
});
|
|
1533
1533
|
app.get("/v1/organizations/:orgId/invitations/:invitationId", (c) => {
|
|
1534
1534
|
const auth = requireSecretKey(c, tokenMap);
|
|
1535
1535
|
if (isAuthResponse(auth)) return auth;
|
|
1536
|
-
const
|
|
1537
|
-
const
|
|
1538
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1536
|
+
const orgId2 = c.req.param("orgId");
|
|
1537
|
+
const invitationId2 = c.req.param("invitationId");
|
|
1538
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1539
1539
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1540
|
-
const invitation = cs.invitations.findOneBy("invitation_id",
|
|
1541
|
-
if (!invitation || invitation.org_id !==
|
|
1540
|
+
const invitation = cs.invitations.findOneBy("invitation_id", invitationId2);
|
|
1541
|
+
if (!invitation || invitation.org_id !== orgId2) {
|
|
1542
1542
|
return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Invitation not found");
|
|
1543
1543
|
}
|
|
1544
1544
|
return c.json(invitationResponse(invitation));
|
|
@@ -1546,8 +1546,8 @@ function invitationRoutes({ app, store, tokenMap }) {
|
|
|
1546
1546
|
app.post("/v1/organizations/:orgId/invitations", async (c) => {
|
|
1547
1547
|
const auth = requireSecretKey(c, tokenMap);
|
|
1548
1548
|
if (isAuthResponse(auth)) return auth;
|
|
1549
|
-
const
|
|
1550
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1549
|
+
const orgId2 = c.req.param("orgId");
|
|
1550
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1551
1551
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1552
1552
|
const body = await readJsonBody(c);
|
|
1553
1553
|
const emailAddress = body.email_address;
|
|
@@ -1558,7 +1558,7 @@ function invitationRoutes({ app, store, tokenMap }) {
|
|
|
1558
1558
|
const invitation = cs.invitations.insert({
|
|
1559
1559
|
invitation_id: generateClerkId("orginv_"),
|
|
1560
1560
|
email_address: emailAddress,
|
|
1561
|
-
org_id:
|
|
1561
|
+
org_id: orgId2,
|
|
1562
1562
|
role,
|
|
1563
1563
|
status: "pending",
|
|
1564
1564
|
expires_at: now + expiresInDays * 86400,
|
|
@@ -1574,8 +1574,8 @@ function invitationRoutes({ app, store, tokenMap }) {
|
|
|
1574
1574
|
app.post("/v1/organizations/:orgId/invitations/bulk", async (c) => {
|
|
1575
1575
|
const auth = requireSecretKey(c, tokenMap);
|
|
1576
1576
|
if (isAuthResponse(auth)) return auth;
|
|
1577
|
-
const
|
|
1578
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1577
|
+
const orgId2 = c.req.param("orgId");
|
|
1578
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1579
1579
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1580
1580
|
const body = await readJsonBody(c);
|
|
1581
1581
|
const emailAddresses = body.email_addresses;
|
|
@@ -1589,7 +1589,7 @@ function invitationRoutes({ app, store, tokenMap }) {
|
|
|
1589
1589
|
(email) => cs.invitations.insert({
|
|
1590
1590
|
invitation_id: generateClerkId("orginv_"),
|
|
1591
1591
|
email_address: email,
|
|
1592
|
-
org_id:
|
|
1592
|
+
org_id: orgId2,
|
|
1593
1593
|
role,
|
|
1594
1594
|
status: "pending",
|
|
1595
1595
|
expires_at: now + expiresInDays * 86400,
|
|
@@ -1606,12 +1606,12 @@ function invitationRoutes({ app, store, tokenMap }) {
|
|
|
1606
1606
|
app.post("/v1/organizations/:orgId/invitations/:invitationId/revoke", (c) => {
|
|
1607
1607
|
const auth = requireSecretKey(c, tokenMap);
|
|
1608
1608
|
if (isAuthResponse(auth)) return auth;
|
|
1609
|
-
const
|
|
1610
|
-
const
|
|
1611
|
-
const org = cs.organizations.findOneBy("clerk_id",
|
|
1609
|
+
const orgId2 = c.req.param("orgId");
|
|
1610
|
+
const invitationId2 = c.req.param("invitationId");
|
|
1611
|
+
const org = cs.organizations.findOneBy("clerk_id", orgId2);
|
|
1612
1612
|
if (!org) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Organization not found");
|
|
1613
|
-
const invitation = cs.invitations.findOneBy("invitation_id",
|
|
1614
|
-
if (!invitation || invitation.org_id !==
|
|
1613
|
+
const invitation = cs.invitations.findOneBy("invitation_id", invitationId2);
|
|
1614
|
+
if (!invitation || invitation.org_id !== orgId2) {
|
|
1615
1615
|
return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Invitation not found");
|
|
1616
1616
|
}
|
|
1617
1617
|
if (invitation.status !== "pending") {
|
|
@@ -1623,7 +1623,7 @@ function invitationRoutes({ app, store, tokenMap }) {
|
|
|
1623
1623
|
pending_invitations_count: Math.max(0, org.pending_invitations_count - 1),
|
|
1624
1624
|
updated_at_unix: now
|
|
1625
1625
|
});
|
|
1626
|
-
const updated = cs.invitations.findOneBy("invitation_id",
|
|
1626
|
+
const updated = cs.invitations.findOneBy("invitation_id", invitationId2);
|
|
1627
1627
|
return c.json(invitationResponse(updated));
|
|
1628
1628
|
});
|
|
1629
1629
|
}
|
|
@@ -1632,7 +1632,7 @@ function sessionRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
1632
1632
|
app.get("/v1/sessions", (c) => {
|
|
1633
1633
|
const auth = requireSecretKey(c, tokenMap);
|
|
1634
1634
|
if (isAuthResponse(auth)) return auth;
|
|
1635
|
-
const { limit, offset } = parsePagination(c);
|
|
1635
|
+
const { limit: limit2, offset: offset2 } = parsePagination(c);
|
|
1636
1636
|
const userIdFilter = c.req.query("user_id");
|
|
1637
1637
|
let sessions = cs.sessions.all();
|
|
1638
1638
|
if (userIdFilter) {
|
|
@@ -1640,14 +1640,14 @@ function sessionRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
1640
1640
|
}
|
|
1641
1641
|
sessions.sort((a, b) => b.created_at_unix - a.created_at_unix);
|
|
1642
1642
|
const totalCount = sessions.length;
|
|
1643
|
-
const paged = sessions.slice(
|
|
1644
|
-
return c.json(paginatedResponse(paged.map(sessionResponse), totalCount,
|
|
1643
|
+
const paged = sessions.slice(offset2, offset2 + limit2);
|
|
1644
|
+
return c.json(paginatedResponse(paged.map(sessionResponse), totalCount, limit2, offset2));
|
|
1645
1645
|
});
|
|
1646
1646
|
app.get("/v1/sessions/:sessionId", (c) => {
|
|
1647
1647
|
const auth = requireSecretKey(c, tokenMap);
|
|
1648
1648
|
if (isAuthResponse(auth)) return auth;
|
|
1649
|
-
const
|
|
1650
|
-
const session = cs.sessions.findOneBy("clerk_id",
|
|
1649
|
+
const sessionId2 = c.req.param("sessionId");
|
|
1650
|
+
const session = cs.sessions.findOneBy("clerk_id", sessionId2);
|
|
1651
1651
|
if (!session) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Session not found");
|
|
1652
1652
|
return c.json(sessionResponse(session));
|
|
1653
1653
|
});
|
|
@@ -1655,14 +1655,14 @@ function sessionRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
1655
1655
|
const auth = requireSecretKey(c, tokenMap);
|
|
1656
1656
|
if (isAuthResponse(auth)) return auth;
|
|
1657
1657
|
const body = await readJsonBody(c);
|
|
1658
|
-
const
|
|
1659
|
-
if (!
|
|
1660
|
-
const user = cs.users.findOneBy("clerk_id",
|
|
1658
|
+
const userId2 = body.user_id;
|
|
1659
|
+
if (!userId2) return clerkError(c, 422, "INVALID_REQUEST_BODY", "user_id is required");
|
|
1660
|
+
const user = cs.users.findOneBy("clerk_id", userId2);
|
|
1661
1661
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1662
1662
|
const now = nowUnix();
|
|
1663
1663
|
const session = cs.sessions.insert({
|
|
1664
1664
|
clerk_id: generateClerkId("sess_"),
|
|
1665
|
-
user_id:
|
|
1665
|
+
user_id: userId2,
|
|
1666
1666
|
client_id: body.client_id ?? "client_emulate",
|
|
1667
1667
|
status: "active",
|
|
1668
1668
|
last_active_at: now,
|
|
@@ -1677,18 +1677,18 @@ function sessionRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
1677
1677
|
app.post("/v1/sessions/:sessionId/revoke", (c) => {
|
|
1678
1678
|
const auth = requireSecretKey(c, tokenMap);
|
|
1679
1679
|
if (isAuthResponse(auth)) return auth;
|
|
1680
|
-
const
|
|
1681
|
-
const session = cs.sessions.findOneBy("clerk_id",
|
|
1680
|
+
const sessionId2 = c.req.param("sessionId");
|
|
1681
|
+
const session = cs.sessions.findOneBy("clerk_id", sessionId2);
|
|
1682
1682
|
if (!session) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Session not found");
|
|
1683
1683
|
cs.sessions.update(session.id, { status: "revoked", updated_at_unix: nowUnix() });
|
|
1684
|
-
const updated = cs.sessions.findOneBy("clerk_id",
|
|
1684
|
+
const updated = cs.sessions.findOneBy("clerk_id", sessionId2);
|
|
1685
1685
|
return c.json(sessionResponse(updated));
|
|
1686
1686
|
});
|
|
1687
1687
|
app.post("/v1/sessions/:sessionId/tokens", async (c) => {
|
|
1688
1688
|
const auth = requireSecretKey(c, tokenMap);
|
|
1689
1689
|
if (isAuthResponse(auth)) return auth;
|
|
1690
|
-
const
|
|
1691
|
-
const session = cs.sessions.findOneBy("clerk_id",
|
|
1690
|
+
const sessionId2 = c.req.param("sessionId");
|
|
1691
|
+
const session = cs.sessions.findOneBy("clerk_id", sessionId2);
|
|
1692
1692
|
if (!session) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Session not found");
|
|
1693
1693
|
if (session.status !== "active") {
|
|
1694
1694
|
return clerkError(c, 422, "SESSION_NOT_ACTIVE", "Session is not active");
|
|
@@ -1697,39 +1697,508 @@ function sessionRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
1697
1697
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1698
1698
|
const memberships = cs.memberships.findBy("user_id", user.clerk_id);
|
|
1699
1699
|
const firstMembership = memberships[0];
|
|
1700
|
-
let
|
|
1700
|
+
let orgId2;
|
|
1701
1701
|
let orgRole;
|
|
1702
1702
|
let orgSlug;
|
|
1703
1703
|
let orgPermissions;
|
|
1704
1704
|
if (firstMembership) {
|
|
1705
1705
|
const org = cs.organizations.findOneBy("clerk_id", firstMembership.org_id);
|
|
1706
1706
|
if (org) {
|
|
1707
|
-
|
|
1707
|
+
orgId2 = org.clerk_id;
|
|
1708
1708
|
orgRole = firstMembership.role;
|
|
1709
1709
|
orgSlug = org.slug;
|
|
1710
1710
|
orgPermissions = firstMembership.permissions;
|
|
1711
1711
|
}
|
|
1712
1712
|
}
|
|
1713
|
-
const jwt = await createSessionToken(store, user,
|
|
1713
|
+
const jwt = await createSessionToken(store, user, sessionId2, baseUrl, orgId2, orgRole, orgSlug, orgPermissions);
|
|
1714
1714
|
cs.sessions.update(session.id, { last_active_at: nowUnix() });
|
|
1715
1715
|
return c.json({ object: "token", jwt });
|
|
1716
1716
|
});
|
|
1717
1717
|
app.post("/v1/sessions/:sessionId/tokens/:template", async (c) => {
|
|
1718
1718
|
const auth = requireSecretKey(c, tokenMap);
|
|
1719
1719
|
if (isAuthResponse(auth)) return auth;
|
|
1720
|
-
const
|
|
1721
|
-
const session = cs.sessions.findOneBy("clerk_id",
|
|
1720
|
+
const sessionId2 = c.req.param("sessionId");
|
|
1721
|
+
const session = cs.sessions.findOneBy("clerk_id", sessionId2);
|
|
1722
1722
|
if (!session) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "Session not found");
|
|
1723
1723
|
if (session.status !== "active") {
|
|
1724
1724
|
return clerkError(c, 422, "SESSION_NOT_ACTIVE", "Session is not active");
|
|
1725
1725
|
}
|
|
1726
1726
|
const user = cs.users.findOneBy("clerk_id", session.user_id);
|
|
1727
1727
|
if (!user) return clerkError(c, 404, "RESOURCE_NOT_FOUND", "User not found");
|
|
1728
|
-
const jwt = await createSessionToken(store, user,
|
|
1728
|
+
const jwt = await createSessionToken(store, user, sessionId2, baseUrl);
|
|
1729
1729
|
cs.sessions.update(session.id, { last_active_at: nowUnix() });
|
|
1730
1730
|
return c.json({ object: "token", jwt });
|
|
1731
1731
|
});
|
|
1732
1732
|
}
|
|
1733
|
+
function openapiRoutes({ app, baseUrl }) {
|
|
1734
|
+
app.get("/openapi.json", (c) => c.json(buildSpec(baseUrl)));
|
|
1735
|
+
}
|
|
1736
|
+
var ok = (description) => ({
|
|
1737
|
+
description,
|
|
1738
|
+
content: { "application/json": { schema: { type: "object" } } }
|
|
1739
|
+
});
|
|
1740
|
+
var userId = { name: "userId", in: "path", required: true, schema: { type: "string" } };
|
|
1741
|
+
var emailId = { name: "emailId", in: "path", required: true, schema: { type: "string" } };
|
|
1742
|
+
var orgId = { name: "orgId", in: "path", required: true, schema: { type: "string" } };
|
|
1743
|
+
var invitationId = { name: "invitationId", in: "path", required: true, schema: { type: "string" } };
|
|
1744
|
+
var sessionId = { name: "sessionId", in: "path", required: true, schema: { type: "string" } };
|
|
1745
|
+
var template = { name: "template", in: "path", required: true, schema: { type: "string" } };
|
|
1746
|
+
var limit = { name: "limit", in: "query", required: false, schema: { type: "integer" } };
|
|
1747
|
+
var offset = { name: "offset", in: "query", required: false, schema: { type: "integer" } };
|
|
1748
|
+
var jsonBody = (properties, required, description) => ({
|
|
1749
|
+
required: true,
|
|
1750
|
+
description,
|
|
1751
|
+
content: {
|
|
1752
|
+
"application/json": {
|
|
1753
|
+
schema: { type: "object", properties, required: [...required] }
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
});
|
|
1757
|
+
var metadataProperties = {
|
|
1758
|
+
public_metadata: { type: "object" },
|
|
1759
|
+
private_metadata: { type: "object" }
|
|
1760
|
+
};
|
|
1761
|
+
function buildSpec(baseUrl) {
|
|
1762
|
+
return {
|
|
1763
|
+
openapi: "3.1.0",
|
|
1764
|
+
info: {
|
|
1765
|
+
title: "Clerk Backend API (Emulated)",
|
|
1766
|
+
version: "1.0.0",
|
|
1767
|
+
description: "Emulated subset of the Clerk Backend API. Authenticate with a bearer secret key (mint one at POST /_emulate/credentials)."
|
|
1768
|
+
},
|
|
1769
|
+
servers: [{ url: baseUrl }],
|
|
1770
|
+
components: {
|
|
1771
|
+
securitySchemes: {
|
|
1772
|
+
bearerAuth: {
|
|
1773
|
+
type: "http",
|
|
1774
|
+
scheme: "bearer",
|
|
1775
|
+
description: "Clerk secret key, sent as `Authorization: Bearer sk_test_\u2026` or `sk_live_\u2026`."
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
},
|
|
1779
|
+
security: [{ bearerAuth: [] }],
|
|
1780
|
+
paths: {
|
|
1781
|
+
"/v1/users": {
|
|
1782
|
+
get: {
|
|
1783
|
+
operationId: "GetUserList",
|
|
1784
|
+
tags: ["users"],
|
|
1785
|
+
summary: "List users",
|
|
1786
|
+
parameters: [
|
|
1787
|
+
limit,
|
|
1788
|
+
offset,
|
|
1789
|
+
{ name: "query", in: "query", required: false, schema: { type: "string" } },
|
|
1790
|
+
{ name: "order_by", in: "query", required: false, schema: { type: "string" } },
|
|
1791
|
+
{
|
|
1792
|
+
name: "email_address",
|
|
1793
|
+
in: "query",
|
|
1794
|
+
required: false,
|
|
1795
|
+
schema: { type: "array", items: { type: "string" } }
|
|
1796
|
+
}
|
|
1797
|
+
],
|
|
1798
|
+
responses: { "200": ok("Paginated user list.") }
|
|
1799
|
+
},
|
|
1800
|
+
post: {
|
|
1801
|
+
operationId: "CreateUser",
|
|
1802
|
+
tags: ["users"],
|
|
1803
|
+
summary: "Create a user",
|
|
1804
|
+
requestBody: jsonBody(
|
|
1805
|
+
{
|
|
1806
|
+
email_address: { type: ["string", "array"], items: { type: "string" } },
|
|
1807
|
+
username: { type: "string" },
|
|
1808
|
+
first_name: { type: "string" },
|
|
1809
|
+
last_name: { type: "string" },
|
|
1810
|
+
external_id: { type: "string" },
|
|
1811
|
+
password: { type: "string" },
|
|
1812
|
+
...metadataProperties,
|
|
1813
|
+
unsafe_metadata: { type: "object" }
|
|
1814
|
+
},
|
|
1815
|
+
[],
|
|
1816
|
+
"The user to create."
|
|
1817
|
+
),
|
|
1818
|
+
responses: { "200": ok("The created user.") }
|
|
1819
|
+
}
|
|
1820
|
+
},
|
|
1821
|
+
"/v1/users/count": {
|
|
1822
|
+
get: {
|
|
1823
|
+
operationId: "GetUsersCount",
|
|
1824
|
+
tags: ["users"],
|
|
1825
|
+
summary: "Count users",
|
|
1826
|
+
responses: { "200": ok("Total user count.") }
|
|
1827
|
+
}
|
|
1828
|
+
},
|
|
1829
|
+
"/v1/users/{userId}": {
|
|
1830
|
+
get: {
|
|
1831
|
+
operationId: "GetUser",
|
|
1832
|
+
tags: ["users"],
|
|
1833
|
+
summary: "Retrieve a user",
|
|
1834
|
+
parameters: [userId],
|
|
1835
|
+
responses: { "200": ok("The user."), "404": ok("Not found.") }
|
|
1836
|
+
},
|
|
1837
|
+
patch: {
|
|
1838
|
+
operationId: "UpdateUser",
|
|
1839
|
+
tags: ["users"],
|
|
1840
|
+
summary: "Update a user",
|
|
1841
|
+
parameters: [userId],
|
|
1842
|
+
requestBody: jsonBody(
|
|
1843
|
+
{
|
|
1844
|
+
first_name: { type: "string" },
|
|
1845
|
+
last_name: { type: "string" },
|
|
1846
|
+
username: { type: "string" },
|
|
1847
|
+
external_id: { type: "string" },
|
|
1848
|
+
primary_email_address_id: { type: "string" },
|
|
1849
|
+
primary_phone_number_id: { type: "string" },
|
|
1850
|
+
password: { type: "string" },
|
|
1851
|
+
...metadataProperties,
|
|
1852
|
+
unsafe_metadata: { type: "object" }
|
|
1853
|
+
},
|
|
1854
|
+
[],
|
|
1855
|
+
"The fields to update."
|
|
1856
|
+
),
|
|
1857
|
+
responses: { "200": ok("The updated user."), "404": ok("Not found.") }
|
|
1858
|
+
},
|
|
1859
|
+
delete: {
|
|
1860
|
+
operationId: "DeleteUser",
|
|
1861
|
+
tags: ["users"],
|
|
1862
|
+
summary: "Delete a user",
|
|
1863
|
+
parameters: [userId],
|
|
1864
|
+
responses: { "200": ok("Deletion confirmation."), "404": ok("Not found.") }
|
|
1865
|
+
}
|
|
1866
|
+
},
|
|
1867
|
+
"/v1/users/{userId}/ban": {
|
|
1868
|
+
post: {
|
|
1869
|
+
operationId: "BanUser",
|
|
1870
|
+
tags: ["users"],
|
|
1871
|
+
summary: "Ban a user",
|
|
1872
|
+
parameters: [userId],
|
|
1873
|
+
responses: { "200": ok("The banned user."), "404": ok("Not found.") }
|
|
1874
|
+
}
|
|
1875
|
+
},
|
|
1876
|
+
"/v1/users/{userId}/unban": {
|
|
1877
|
+
post: {
|
|
1878
|
+
operationId: "UnbanUser",
|
|
1879
|
+
tags: ["users"],
|
|
1880
|
+
summary: "Unban a user",
|
|
1881
|
+
parameters: [userId],
|
|
1882
|
+
responses: { "200": ok("The unbanned user."), "404": ok("Not found.") }
|
|
1883
|
+
}
|
|
1884
|
+
},
|
|
1885
|
+
"/v1/users/{userId}/lock": {
|
|
1886
|
+
post: {
|
|
1887
|
+
operationId: "LockUser",
|
|
1888
|
+
tags: ["users"],
|
|
1889
|
+
summary: "Lock a user",
|
|
1890
|
+
parameters: [userId],
|
|
1891
|
+
responses: { "200": ok("The locked user."), "404": ok("Not found.") }
|
|
1892
|
+
}
|
|
1893
|
+
},
|
|
1894
|
+
"/v1/users/{userId}/unlock": {
|
|
1895
|
+
post: {
|
|
1896
|
+
operationId: "UnlockUser",
|
|
1897
|
+
tags: ["users"],
|
|
1898
|
+
summary: "Unlock a user",
|
|
1899
|
+
parameters: [userId],
|
|
1900
|
+
responses: { "200": ok("The unlocked user."), "404": ok("Not found.") }
|
|
1901
|
+
}
|
|
1902
|
+
},
|
|
1903
|
+
"/v1/users/{userId}/metadata": {
|
|
1904
|
+
patch: {
|
|
1905
|
+
operationId: "UpdateUserMetadata",
|
|
1906
|
+
tags: ["users"],
|
|
1907
|
+
summary: "Merge and update a user's metadata",
|
|
1908
|
+
parameters: [userId],
|
|
1909
|
+
requestBody: jsonBody(
|
|
1910
|
+
{ ...metadataProperties, unsafe_metadata: { type: "object" } },
|
|
1911
|
+
[],
|
|
1912
|
+
"Metadata objects to deep-merge into the user."
|
|
1913
|
+
),
|
|
1914
|
+
responses: { "200": ok("The updated user."), "404": ok("Not found.") }
|
|
1915
|
+
}
|
|
1916
|
+
},
|
|
1917
|
+
"/v1/users/{userId}/verify_password": {
|
|
1918
|
+
post: {
|
|
1919
|
+
operationId: "VerifyPassword",
|
|
1920
|
+
tags: ["users"],
|
|
1921
|
+
summary: "Verify a user's password",
|
|
1922
|
+
parameters: [userId],
|
|
1923
|
+
requestBody: jsonBody({ password: { type: "string" } }, ["password"], "The password to verify."),
|
|
1924
|
+
responses: { "200": ok("Verification result."), "404": ok("Not found.") }
|
|
1925
|
+
}
|
|
1926
|
+
},
|
|
1927
|
+
"/v1/email_addresses": {
|
|
1928
|
+
post: {
|
|
1929
|
+
operationId: "CreateEmailAddress",
|
|
1930
|
+
tags: ["email-addresses"],
|
|
1931
|
+
summary: "Create an email address",
|
|
1932
|
+
requestBody: jsonBody(
|
|
1933
|
+
{
|
|
1934
|
+
user_id: { type: "string" },
|
|
1935
|
+
email_address: { type: "string" },
|
|
1936
|
+
verified: { type: "boolean" },
|
|
1937
|
+
primary: { type: "boolean" }
|
|
1938
|
+
},
|
|
1939
|
+
["user_id", "email_address"],
|
|
1940
|
+
"The email address to create."
|
|
1941
|
+
),
|
|
1942
|
+
responses: { "200": ok("The created email address."), "422": ok("Validation error.") }
|
|
1943
|
+
}
|
|
1944
|
+
},
|
|
1945
|
+
"/v1/email_addresses/{emailId}": {
|
|
1946
|
+
get: {
|
|
1947
|
+
operationId: "GetEmailAddress",
|
|
1948
|
+
tags: ["email-addresses"],
|
|
1949
|
+
summary: "Retrieve an email address",
|
|
1950
|
+
parameters: [emailId],
|
|
1951
|
+
responses: { "200": ok("The email address."), "404": ok("Not found.") }
|
|
1952
|
+
},
|
|
1953
|
+
patch: {
|
|
1954
|
+
operationId: "UpdateEmailAddress",
|
|
1955
|
+
tags: ["email-addresses"],
|
|
1956
|
+
summary: "Update an email address",
|
|
1957
|
+
parameters: [emailId],
|
|
1958
|
+
requestBody: jsonBody(
|
|
1959
|
+
{ verified: { type: "boolean" }, primary: { type: "boolean" } },
|
|
1960
|
+
[],
|
|
1961
|
+
"The fields to update."
|
|
1962
|
+
),
|
|
1963
|
+
responses: { "200": ok("The updated email address."), "404": ok("Not found.") }
|
|
1964
|
+
},
|
|
1965
|
+
delete: {
|
|
1966
|
+
operationId: "DeleteEmailAddress",
|
|
1967
|
+
tags: ["email-addresses"],
|
|
1968
|
+
summary: "Delete an email address",
|
|
1969
|
+
parameters: [emailId],
|
|
1970
|
+
responses: { "200": ok("Deletion confirmation."), "404": ok("Not found.") }
|
|
1971
|
+
}
|
|
1972
|
+
},
|
|
1973
|
+
"/v1/organizations": {
|
|
1974
|
+
get: {
|
|
1975
|
+
operationId: "ListOrganizations",
|
|
1976
|
+
tags: ["organizations"],
|
|
1977
|
+
summary: "List organizations",
|
|
1978
|
+
parameters: [limit, offset, { name: "query", in: "query", required: false, schema: { type: "string" } }],
|
|
1979
|
+
responses: { "200": ok("Paginated organization list.") }
|
|
1980
|
+
},
|
|
1981
|
+
post: {
|
|
1982
|
+
operationId: "CreateOrganization",
|
|
1983
|
+
tags: ["organizations"],
|
|
1984
|
+
summary: "Create an organization",
|
|
1985
|
+
requestBody: jsonBody(
|
|
1986
|
+
{
|
|
1987
|
+
name: { type: "string" },
|
|
1988
|
+
slug: { type: "string" },
|
|
1989
|
+
created_by: { type: "string" },
|
|
1990
|
+
max_allowed_memberships: { type: "integer" },
|
|
1991
|
+
admin_delete_enabled: { type: "boolean" },
|
|
1992
|
+
...metadataProperties
|
|
1993
|
+
},
|
|
1994
|
+
["name"],
|
|
1995
|
+
"The organization to create."
|
|
1996
|
+
),
|
|
1997
|
+
responses: { "200": ok("The created organization."), "422": ok("Validation error.") }
|
|
1998
|
+
}
|
|
1999
|
+
},
|
|
2000
|
+
"/v1/organizations/{orgId}": {
|
|
2001
|
+
get: {
|
|
2002
|
+
operationId: "GetOrganization",
|
|
2003
|
+
tags: ["organizations"],
|
|
2004
|
+
summary: "Retrieve an organization by id or slug",
|
|
2005
|
+
parameters: [orgId],
|
|
2006
|
+
responses: { "200": ok("The organization."), "404": ok("Not found.") }
|
|
2007
|
+
},
|
|
2008
|
+
patch: {
|
|
2009
|
+
operationId: "UpdateOrganization",
|
|
2010
|
+
tags: ["organizations"],
|
|
2011
|
+
summary: "Update an organization",
|
|
2012
|
+
parameters: [orgId],
|
|
2013
|
+
requestBody: jsonBody(
|
|
2014
|
+
{
|
|
2015
|
+
name: { type: "string" },
|
|
2016
|
+
slug: { type: "string" },
|
|
2017
|
+
max_allowed_memberships: { type: "integer" },
|
|
2018
|
+
admin_delete_enabled: { type: "boolean" },
|
|
2019
|
+
...metadataProperties
|
|
2020
|
+
},
|
|
2021
|
+
[],
|
|
2022
|
+
"The fields to update."
|
|
2023
|
+
),
|
|
2024
|
+
responses: { "200": ok("The updated organization."), "404": ok("Not found.") }
|
|
2025
|
+
},
|
|
2026
|
+
delete: {
|
|
2027
|
+
operationId: "DeleteOrganization",
|
|
2028
|
+
tags: ["organizations"],
|
|
2029
|
+
summary: "Delete an organization",
|
|
2030
|
+
parameters: [orgId],
|
|
2031
|
+
responses: { "200": ok("Deletion confirmation."), "404": ok("Not found.") }
|
|
2032
|
+
}
|
|
2033
|
+
},
|
|
2034
|
+
"/v1/organizations/{orgId}/memberships": {
|
|
2035
|
+
get: {
|
|
2036
|
+
operationId: "ListOrganizationMemberships",
|
|
2037
|
+
tags: ["memberships"],
|
|
2038
|
+
summary: "List organization memberships",
|
|
2039
|
+
parameters: [
|
|
2040
|
+
orgId,
|
|
2041
|
+
limit,
|
|
2042
|
+
offset,
|
|
2043
|
+
{ name: "role", in: "query", required: false, schema: { type: "string" } }
|
|
2044
|
+
],
|
|
2045
|
+
responses: { "200": ok("Paginated membership list."), "404": ok("Organization not found.") }
|
|
2046
|
+
},
|
|
2047
|
+
post: {
|
|
2048
|
+
operationId: "CreateOrganizationMembership",
|
|
2049
|
+
tags: ["memberships"],
|
|
2050
|
+
summary: "Add a member to an organization",
|
|
2051
|
+
parameters: [orgId],
|
|
2052
|
+
requestBody: jsonBody(
|
|
2053
|
+
{ user_id: { type: "string" }, role: { type: "string" } },
|
|
2054
|
+
["user_id"],
|
|
2055
|
+
"The membership to create."
|
|
2056
|
+
),
|
|
2057
|
+
responses: { "200": ok("The created membership."), "422": ok("Validation error.") }
|
|
2058
|
+
}
|
|
2059
|
+
},
|
|
2060
|
+
"/v1/organizations/{orgId}/memberships/{userId}": {
|
|
2061
|
+
patch: {
|
|
2062
|
+
operationId: "UpdateOrganizationMembership",
|
|
2063
|
+
tags: ["memberships"],
|
|
2064
|
+
summary: "Update an organization membership",
|
|
2065
|
+
parameters: [orgId, userId],
|
|
2066
|
+
requestBody: jsonBody({ role: { type: "string" } }, [], "The fields to update."),
|
|
2067
|
+
responses: { "200": ok("The updated membership."), "404": ok("Not found.") }
|
|
2068
|
+
},
|
|
2069
|
+
delete: {
|
|
2070
|
+
operationId: "DeleteOrganizationMembership",
|
|
2071
|
+
tags: ["memberships"],
|
|
2072
|
+
summary: "Remove a member from an organization",
|
|
2073
|
+
parameters: [orgId, userId],
|
|
2074
|
+
responses: { "200": ok("Deletion confirmation."), "404": ok("Not found.") }
|
|
2075
|
+
}
|
|
2076
|
+
},
|
|
2077
|
+
"/v1/organizations/{orgId}/invitations": {
|
|
2078
|
+
get: {
|
|
2079
|
+
operationId: "ListOrganizationInvitations",
|
|
2080
|
+
tags: ["invitations"],
|
|
2081
|
+
summary: "List organization invitations",
|
|
2082
|
+
parameters: [
|
|
2083
|
+
orgId,
|
|
2084
|
+
limit,
|
|
2085
|
+
offset,
|
|
2086
|
+
{ name: "status", in: "query", required: false, schema: { type: "string" } }
|
|
2087
|
+
],
|
|
2088
|
+
responses: { "200": ok("Paginated invitation list."), "404": ok("Organization not found.") }
|
|
2089
|
+
},
|
|
2090
|
+
post: {
|
|
2091
|
+
operationId: "CreateOrganizationInvitation",
|
|
2092
|
+
tags: ["invitations"],
|
|
2093
|
+
summary: "Invite a user to an organization",
|
|
2094
|
+
parameters: [orgId],
|
|
2095
|
+
requestBody: jsonBody(
|
|
2096
|
+
{
|
|
2097
|
+
email_address: { type: "string" },
|
|
2098
|
+
role: { type: "string" },
|
|
2099
|
+
expires_in_days: { type: "integer" }
|
|
2100
|
+
},
|
|
2101
|
+
["email_address"],
|
|
2102
|
+
"The invitation to create."
|
|
2103
|
+
),
|
|
2104
|
+
responses: { "200": ok("The created invitation."), "422": ok("Validation error.") }
|
|
2105
|
+
}
|
|
2106
|
+
},
|
|
2107
|
+
"/v1/organizations/{orgId}/invitations/bulk": {
|
|
2108
|
+
post: {
|
|
2109
|
+
operationId: "CreateOrganizationInvitationBulk",
|
|
2110
|
+
tags: ["invitations"],
|
|
2111
|
+
summary: "Invite multiple users to an organization",
|
|
2112
|
+
parameters: [orgId],
|
|
2113
|
+
requestBody: jsonBody(
|
|
2114
|
+
{
|
|
2115
|
+
email_addresses: { type: "array", items: { type: "string" } },
|
|
2116
|
+
role: { type: "string" },
|
|
2117
|
+
expires_in_days: { type: "integer" }
|
|
2118
|
+
},
|
|
2119
|
+
["email_addresses"],
|
|
2120
|
+
"The invitations to create."
|
|
2121
|
+
),
|
|
2122
|
+
responses: { "200": ok("The created invitations."), "422": ok("Validation error.") }
|
|
2123
|
+
}
|
|
2124
|
+
},
|
|
2125
|
+
"/v1/organizations/{orgId}/invitations/{invitationId}/revoke": {
|
|
2126
|
+
post: {
|
|
2127
|
+
operationId: "RevokeOrganizationInvitation",
|
|
2128
|
+
tags: ["invitations"],
|
|
2129
|
+
summary: "Revoke a pending invitation",
|
|
2130
|
+
parameters: [orgId, invitationId],
|
|
2131
|
+
responses: { "200": ok("The revoked invitation."), "404": ok("Not found.") }
|
|
2132
|
+
}
|
|
2133
|
+
},
|
|
2134
|
+
"/v1/sessions": {
|
|
2135
|
+
get: {
|
|
2136
|
+
operationId: "GetSessionList",
|
|
2137
|
+
tags: ["sessions"],
|
|
2138
|
+
summary: "List sessions",
|
|
2139
|
+
parameters: [limit, offset, { name: "user_id", in: "query", required: false, schema: { type: "string" } }],
|
|
2140
|
+
responses: { "200": ok("Paginated session list.") }
|
|
2141
|
+
},
|
|
2142
|
+
post: {
|
|
2143
|
+
operationId: "CreateSession",
|
|
2144
|
+
tags: ["sessions"],
|
|
2145
|
+
summary: "Create a session",
|
|
2146
|
+
requestBody: jsonBody(
|
|
2147
|
+
{ user_id: { type: "string" }, client_id: { type: "string" } },
|
|
2148
|
+
["user_id"],
|
|
2149
|
+
"The session to create."
|
|
2150
|
+
),
|
|
2151
|
+
responses: { "200": ok("The created session."), "422": ok("Validation error.") }
|
|
2152
|
+
}
|
|
2153
|
+
},
|
|
2154
|
+
"/v1/sessions/{sessionId}": {
|
|
2155
|
+
get: {
|
|
2156
|
+
operationId: "GetSession",
|
|
2157
|
+
tags: ["sessions"],
|
|
2158
|
+
summary: "Retrieve a session",
|
|
2159
|
+
parameters: [sessionId],
|
|
2160
|
+
responses: { "200": ok("The session."), "404": ok("Not found.") }
|
|
2161
|
+
}
|
|
2162
|
+
},
|
|
2163
|
+
"/v1/sessions/{sessionId}/revoke": {
|
|
2164
|
+
post: {
|
|
2165
|
+
operationId: "RevokeSession",
|
|
2166
|
+
tags: ["sessions"],
|
|
2167
|
+
summary: "Revoke a session",
|
|
2168
|
+
parameters: [sessionId],
|
|
2169
|
+
responses: { "200": ok("The revoked session."), "404": ok("Not found.") }
|
|
2170
|
+
}
|
|
2171
|
+
},
|
|
2172
|
+
"/v1/sessions/{sessionId}/tokens": {
|
|
2173
|
+
post: {
|
|
2174
|
+
operationId: "CreateSessionToken",
|
|
2175
|
+
tags: ["sessions"],
|
|
2176
|
+
summary: "Mint a session JWT",
|
|
2177
|
+
parameters: [sessionId],
|
|
2178
|
+
responses: { "200": ok("The session token."), "404": ok("Not found.") }
|
|
2179
|
+
}
|
|
2180
|
+
},
|
|
2181
|
+
"/v1/sessions/{sessionId}/tokens/{template}": {
|
|
2182
|
+
post: {
|
|
2183
|
+
operationId: "CreateSessionTokenFromTemplate",
|
|
2184
|
+
tags: ["sessions"],
|
|
2185
|
+
summary: "Mint a session JWT from a template",
|
|
2186
|
+
parameters: [sessionId, template],
|
|
2187
|
+
responses: { "200": ok("The session token."), "404": ok("Not found.") }
|
|
2188
|
+
}
|
|
2189
|
+
},
|
|
2190
|
+
"/v1/jwks": {
|
|
2191
|
+
get: {
|
|
2192
|
+
operationId: "GetJWKS",
|
|
2193
|
+
tags: ["jwks"],
|
|
2194
|
+
summary: "Retrieve the JSON Web Key Set",
|
|
2195
|
+
security: [],
|
|
2196
|
+
responses: { "200": ok("The JWKS used to verify session tokens.") }
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
};
|
|
2201
|
+
}
|
|
1733
2202
|
var manifest = {
|
|
1734
2203
|
id: "clerk",
|
|
1735
2204
|
name: "Clerk",
|
|
@@ -1750,6 +2219,7 @@ var manifest = {
|
|
|
1750
2219
|
kind: "openapi",
|
|
1751
2220
|
title: "Clerk Backend API subset",
|
|
1752
2221
|
coverage: "hand-authored",
|
|
2222
|
+
url: "/openapi.json",
|
|
1753
2223
|
operations: [
|
|
1754
2224
|
{ operationId: "GetUserList", method: "GET", path: "/v1/users", status: "hand-authored" },
|
|
1755
2225
|
{ operationId: "GetUsersCount", method: "GET", path: "/v1/users/count", status: "hand-authored" },
|
|
@@ -2061,9 +2531,9 @@ function seedFromConfig(store, _baseUrl, config) {
|
|
|
2061
2531
|
const existingSlug = orgCfg.slug ?? orgCfg.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
2062
2532
|
const existing = cs.organizations.findOneBy("slug", existingSlug);
|
|
2063
2533
|
if (existing) continue;
|
|
2064
|
-
const
|
|
2534
|
+
const orgId2 = orgCfg.clerk_id ?? generateClerkId("org_");
|
|
2065
2535
|
const org = cs.organizations.insert({
|
|
2066
|
-
clerk_id:
|
|
2536
|
+
clerk_id: orgId2,
|
|
2067
2537
|
name: orgCfg.name,
|
|
2068
2538
|
slug: existingSlug,
|
|
2069
2539
|
image_url: null,
|
|
@@ -2084,12 +2554,12 @@ function seedFromConfig(store, _baseUrl, config) {
|
|
|
2084
2554
|
if (!emailEntry) continue;
|
|
2085
2555
|
const user = cs.users.findOneBy("clerk_id", emailEntry.user_id);
|
|
2086
2556
|
if (!user) continue;
|
|
2087
|
-
const existingMembership = cs.memberships.findBy("org_id",
|
|
2557
|
+
const existingMembership = cs.memberships.findBy("org_id", orgId2).find((m) => m.user_id === user.clerk_id);
|
|
2088
2558
|
if (existingMembership) continue;
|
|
2089
2559
|
const role = memberCfg.role.startsWith("org:") ? memberCfg.role : `org:${memberCfg.role}`;
|
|
2090
2560
|
cs.memberships.insert({
|
|
2091
2561
|
membership_id: generateClerkId("orgmem_"),
|
|
2092
|
-
org_id:
|
|
2562
|
+
org_id: orgId2,
|
|
2093
2563
|
user_id: user.clerk_id,
|
|
2094
2564
|
role,
|
|
2095
2565
|
permissions: role === "org:admin" ? [
|
|
@@ -2138,6 +2608,7 @@ var clerkPlugin = {
|
|
|
2138
2608
|
membershipRoutes(ctx);
|
|
2139
2609
|
invitationRoutes(ctx);
|
|
2140
2610
|
sessionRoutes(ctx);
|
|
2611
|
+
openapiRoutes(ctx);
|
|
2141
2612
|
},
|
|
2142
2613
|
seed(store, baseUrl) {
|
|
2143
2614
|
seedDefaults(store, baseUrl);
|
|
@@ -2151,4 +2622,4 @@ export {
|
|
|
2151
2622
|
manifest,
|
|
2152
2623
|
seedFromConfig
|
|
2153
2624
|
};
|
|
2154
|
-
//# sourceMappingURL=dist-
|
|
2625
|
+
//# sourceMappingURL=dist-OVTPVMMW.js.map
|