@nexpress/core 0.3.0 → 0.3.2
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/auth.d.ts +26 -3
- package/dist/auth.js +5 -3
- package/dist/{can-FKIEV54H.js → can-UJ2NAOIR.js} +3 -3
- package/dist/{chunk-CHQJG4BB.js → chunk-2N53KKIL.js} +2 -2
- package/dist/{chunk-DWG3RZH2.js → chunk-2VZZ7M26.js} +2 -2
- package/dist/{chunk-4EPNN4XG.js → chunk-54KUQF3S.js} +2 -2
- package/dist/{chunk-QYP6E5FP.js → chunk-6UV2P5MW.js} +63 -50
- package/dist/chunk-6UV2P5MW.js.map +1 -0
- package/dist/{chunk-QSJIKNQJ.js → chunk-ANZBCOEH.js} +9 -9
- package/dist/{chunk-TD4KNSEP.js → chunk-C6HXDY46.js} +19 -19
- package/dist/{chunk-26RYBFTF.js → chunk-LMPYQLMH.js} +37 -5
- package/dist/chunk-LMPYQLMH.js.map +1 -0
- package/dist/{chunk-EVOBLRHW.js → chunk-M2FWG5OJ.js} +5 -5
- package/dist/chunk-P5WGQRSG.js +180 -0
- package/dist/chunk-P5WGQRSG.js.map +1 -0
- package/dist/{chunk-HM46WM45.js → chunk-RDTTK27V.js} +6 -6
- package/dist/{chunk-PQBJWZ7D.js → chunk-RJ76SKWQ.js} +4 -4
- package/dist/{chunk-74CGJJDY.js → chunk-RKM4GDWM.js} +1 -1
- package/dist/{chunk-CKT4QZDC.js → chunk-WJJ5MBH5.js} +5 -5
- package/dist/{chunk-DPRBHEHI.js → chunk-YOFCLTBR.js} +7 -4
- package/dist/chunk-YOFCLTBR.js.map +1 -0
- package/dist/{chunk-HTDDXBMY.js → chunk-ZA3IRJUQ.js} +81 -131
- package/dist/chunk-ZA3IRJUQ.js.map +1 -0
- package/dist/community.d.ts +1 -1
- package/dist/community.js +20 -19
- package/dist/{config-2Y2YGD25.js → config-O7QM2OQS.js} +8 -7
- package/dist/db-schema.d.ts +2 -2
- package/dist/db.d.ts +3 -3
- package/dist/db.js +1 -1
- package/dist/fields.d.ts +54 -0
- package/dist/fields.js +14 -0
- package/dist/{host-YSADWU7J.js → host-NI3LR774.js} +6 -5
- package/dist/i18n.d.ts +1 -1
- package/dist/i18n.js +1 -1
- package/dist/{index-9IhVtFfA.d.ts → index-CPp-zGgL.d.ts} +2 -2
- package/dist/{index-CXuqW_Gl.d.ts → index-DKoSaszT.d.ts} +1 -1
- package/dist/{index-ClcinJ29.d.ts → index-DymnczhP.d.ts} +1 -1
- package/dist/{index-7_PBSyOq.d.ts → index-UZn29S3i.d.ts} +1 -1
- package/dist/index.d.ts +102 -16
- package/dist/index.js +191 -79
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +2 -2
- package/dist/jobs.js +2 -2
- package/dist/media.d.ts +2 -2
- package/dist/media.js +2 -2
- package/dist/{mentions-NCQR4B72.js → mentions-U4JACYI6.js} +3 -3
- package/dist/{mutes-FJSSU2JP.js → mutes-MNQP6ACF.js} +3 -3
- package/dist/{scheduled-F77QCDOG.js → scheduled-BWJG35Z2.js} +7 -6
- package/dist/seo.d.ts +16 -3
- package/dist/seo.js +6 -5
- package/dist/{settings-JODDWMDB.js → settings-OZWM6L2K.js} +2 -2
- package/dist/settings-OZWM6L2K.js.map +1 -0
- package/dist/strings-4EWJYDOG.js +1 -1
- package/dist/{types-DI3gxsiY.d.ts → types-D31ppGJw.d.ts} +294 -2
- package/package.json +6 -1
- package/dist/chunk-26RYBFTF.js.map +0 -1
- package/dist/chunk-DPRBHEHI.js.map +0 -1
- package/dist/chunk-HTDDXBMY.js.map +0 -1
- package/dist/chunk-QYP6E5FP.js.map +0 -1
- /package/dist/{can-FKIEV54H.js.map → can-UJ2NAOIR.js.map} +0 -0
- /package/dist/{chunk-CHQJG4BB.js.map → chunk-2N53KKIL.js.map} +0 -0
- /package/dist/{chunk-DWG3RZH2.js.map → chunk-2VZZ7M26.js.map} +0 -0
- /package/dist/{chunk-4EPNN4XG.js.map → chunk-54KUQF3S.js.map} +0 -0
- /package/dist/{chunk-QSJIKNQJ.js.map → chunk-ANZBCOEH.js.map} +0 -0
- /package/dist/{chunk-TD4KNSEP.js.map → chunk-C6HXDY46.js.map} +0 -0
- /package/dist/{chunk-EVOBLRHW.js.map → chunk-M2FWG5OJ.js.map} +0 -0
- /package/dist/{chunk-HM46WM45.js.map → chunk-RDTTK27V.js.map} +0 -0
- /package/dist/{chunk-PQBJWZ7D.js.map → chunk-RJ76SKWQ.js.map} +0 -0
- /package/dist/{chunk-74CGJJDY.js.map → chunk-RKM4GDWM.js.map} +0 -0
- /package/dist/{chunk-CKT4QZDC.js.map → chunk-WJJ5MBH5.js.map} +0 -0
- /package/dist/{config-2Y2YGD25.js.map → config-O7QM2OQS.js.map} +0 -0
- /package/dist/{host-YSADWU7J.js.map → fields.js.map} +0 -0
- /package/dist/{mentions-NCQR4B72.js.map → host-NI3LR774.js.map} +0 -0
- /package/dist/{mutes-FJSSU2JP.js.map → mentions-U4JACYI6.js.map} +0 -0
- /package/dist/{scheduled-F77QCDOG.js.map → mutes-MNQP6ACF.js.map} +0 -0
- /package/dist/{settings-JODDWMDB.js.map → scheduled-BWJG35Z2.js.map} +0 -0
package/dist/auth.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { p as NpAccessFunction,
|
|
2
|
-
export {
|
|
1
|
+
import { p as NpAccessFunction, m as NpUserRole, e as NpAuthUser } from './types-D31ppGJw.js';
|
|
2
|
+
export { H as NpPrincipal } from './types-D31ppGJw.js';
|
|
3
3
|
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
4
4
|
import { Options } from '@node-rs/argon2';
|
|
5
5
|
|
|
@@ -72,6 +72,29 @@ declare function verifyToken(token: string, secret: string, expectedUse?: NpToke
|
|
|
72
72
|
*/
|
|
73
73
|
declare function isTokenVerificationError(err: unknown): boolean;
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Minimal public projection of a user row — `id` + `name` + `email`.
|
|
77
|
+
* Themes / plugins reach for this when they need to display a byline
|
|
78
|
+
* (post.author → user) without pulling in session machinery. Password
|
|
79
|
+
* hash + tokenVersion + reset state stay private to the auth module.
|
|
80
|
+
*/
|
|
81
|
+
interface NpUserBasic {
|
|
82
|
+
id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
email: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Look up a user by id. Returns `null` when the id doesn't exist
|
|
88
|
+
* (caller handles missing-author UI). UUID validation lives at the
|
|
89
|
+
* caller — Postgres rejects malformed ids inside `eq()` and the
|
|
90
|
+
* surfacing error is already informative.
|
|
91
|
+
*
|
|
92
|
+
* This is the supported entry point for theme code that needs to
|
|
93
|
+
* render a byline from `posts.author: relationTo("users")`. Direct
|
|
94
|
+
* drizzle reads against `np_users` are private to the framework.
|
|
95
|
+
*/
|
|
96
|
+
declare function getUserById(id: string): Promise<NpUserBasic | null>;
|
|
97
|
+
|
|
75
98
|
declare const ARGON2_OPTIONS: Options;
|
|
76
99
|
declare function hashPassword(password: string): Promise<string>;
|
|
77
100
|
declare function verifyPassword(passwordHash: string, password: string): Promise<boolean>;
|
|
@@ -637,4 +660,4 @@ interface NpConsumeMemberResetResult {
|
|
|
637
660
|
}
|
|
638
661
|
declare function consumeMemberPasswordReset(db: NodePgDatabase<Record<string, unknown>>, token: string, newPassword: string): Promise<NpConsumeMemberResetResult>;
|
|
639
662
|
|
|
640
|
-
export { ARGON2_OPTIONS, type ArcticLikeProvider, type ArcticLikeTokens, type FromArcticOptions, type IssuedOAuthState, type NpCapability, type NpConsumeMemberEmailVerifyResult, type NpConsumeMemberResetResult, type NpConsumeResetTokenOptions, type NpConsumeResetTokenResult, type NpCreateResetTokenOptions, type NpIssuedMemberToken, type NpIssuedResetToken, type NpMemberAuthRow, type NpMemberIdentityRow, type NpMemberResetRequestResult, type NpMemberTokenPayload, type NpPasswordResetPurpose, type NpResetRequestResult, type NpTokenPayload, type NpUserIdentityRow, type OAuthAuthorizeParams, type OAuthExchangeParams, type OAuthProfile, type OAuthProvider, type OAuthStatePayload, type ResolveMemberOAuthLoginInput, type ResolveMemberOAuthLoginResult, type ResolveOAuthLoginInput, type ResolveOAuthLoginResult, type ResolvedOAuthMember, type ResolvedOAuthUser, type VerifyOAuthStateResult, authenticated, can, consumeMemberEmailVerifyToken, consumeMemberPasswordReset, consumePasswordResetToken, createMemberEmailVerifyToken, createPasswordResetToken, fromArctic, getMemberFromTokenPayload, getOAuthProvider, hashPassword, invalidateAllMemberSessions, invalidateAllSessions, isAdmin, isEditorOrAbove, isOwnerOrAdmin, isTokenVerificationError, issueOAuthState, listMemberIdentities, listOAuthProviders, listUserIdentities, registerOAuthProvider, requestMemberPasswordReset, requestPasswordReset, resetOAuthProviders, resolveMemberOAuthLogin, resolveOAuthLogin, revokeMemberIdentity, revokeUserIdentity, sha256, signMemberToken, signToken, verifyCsrf, verifyMemberToken, verifyOAuthState, verifyPassword, verifyToken, verifyTokenFull };
|
|
663
|
+
export { ARGON2_OPTIONS, type ArcticLikeProvider, type ArcticLikeTokens, type FromArcticOptions, type IssuedOAuthState, type NpCapability, type NpConsumeMemberEmailVerifyResult, type NpConsumeMemberResetResult, type NpConsumeResetTokenOptions, type NpConsumeResetTokenResult, type NpCreateResetTokenOptions, type NpIssuedMemberToken, type NpIssuedResetToken, type NpMemberAuthRow, type NpMemberIdentityRow, type NpMemberResetRequestResult, type NpMemberTokenPayload, type NpPasswordResetPurpose, type NpResetRequestResult, type NpTokenPayload, type NpUserBasic, type NpUserIdentityRow, type OAuthAuthorizeParams, type OAuthExchangeParams, type OAuthProfile, type OAuthProvider, type OAuthStatePayload, type ResolveMemberOAuthLoginInput, type ResolveMemberOAuthLoginResult, type ResolveOAuthLoginInput, type ResolveOAuthLoginResult, type ResolvedOAuthMember, type ResolvedOAuthUser, type VerifyOAuthStateResult, authenticated, can, consumeMemberEmailVerifyToken, consumeMemberPasswordReset, consumePasswordResetToken, createMemberEmailVerifyToken, createPasswordResetToken, fromArctic, getMemberFromTokenPayload, getOAuthProvider, getUserById, hashPassword, invalidateAllMemberSessions, invalidateAllSessions, isAdmin, isEditorOrAbove, isOwnerOrAdmin, isTokenVerificationError, issueOAuthState, listMemberIdentities, listOAuthProviders, listUserIdentities, registerOAuthProvider, requestMemberPasswordReset, requestPasswordReset, resetOAuthProviders, resolveMemberOAuthLogin, resolveOAuthLogin, revokeMemberIdentity, revokeUserIdentity, sha256, signMemberToken, signToken, verifyCsrf, verifyMemberToken, verifyOAuthState, verifyPassword, verifyToken, verifyTokenFull };
|
package/dist/auth.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
fromArctic,
|
|
10
10
|
getMemberFromTokenPayload,
|
|
11
11
|
getOAuthProvider,
|
|
12
|
+
getUserById,
|
|
12
13
|
hashPassword,
|
|
13
14
|
invalidateAllMemberSessions,
|
|
14
15
|
invalidateAllSessions,
|
|
@@ -37,14 +38,14 @@ import {
|
|
|
37
38
|
verifyPassword,
|
|
38
39
|
verifyToken,
|
|
39
40
|
verifyTokenFull
|
|
40
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-6UV2P5MW.js";
|
|
41
42
|
import {
|
|
42
43
|
can
|
|
43
44
|
} from "./chunk-EQ2Z3KMD.js";
|
|
44
45
|
import "./chunk-ML2E3P3X.js";
|
|
45
|
-
import "./chunk-
|
|
46
|
-
import "./chunk-ZCINJSS4.js";
|
|
46
|
+
import "./chunk-RKM4GDWM.js";
|
|
47
47
|
import "./chunk-SBCVAC2Z.js";
|
|
48
|
+
import "./chunk-ZCINJSS4.js";
|
|
48
49
|
import "./chunk-OROPGO65.js";
|
|
49
50
|
import "./chunk-NFHS7CFV.js";
|
|
50
51
|
import "./chunk-XANPEOJC.js";
|
|
@@ -62,6 +63,7 @@ export {
|
|
|
62
63
|
fromArctic,
|
|
63
64
|
getMemberFromTokenPayload,
|
|
64
65
|
getOAuthProvider,
|
|
66
|
+
getUserById,
|
|
65
67
|
hashPassword,
|
|
66
68
|
invalidateAllMemberSessions,
|
|
67
69
|
invalidateAllSessions,
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
isMemberBanned,
|
|
4
4
|
memberCan,
|
|
5
5
|
withMemberWrite
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RJ76SKWQ.js";
|
|
7
7
|
import "./chunk-U4QCCLAW.js";
|
|
8
|
-
import "./chunk-ZCINJSS4.js";
|
|
9
8
|
import "./chunk-SBCVAC2Z.js";
|
|
9
|
+
import "./chunk-ZCINJSS4.js";
|
|
10
10
|
import "./chunk-XANPEOJC.js";
|
|
11
11
|
import "./chunk-X7K5F2UI.js";
|
|
12
12
|
import "./chunk-PZ5AY32C.js";
|
|
@@ -16,4 +16,4 @@ export {
|
|
|
16
16
|
memberCan,
|
|
17
17
|
withMemberWrite
|
|
18
18
|
};
|
|
19
|
-
//# sourceMappingURL=can-
|
|
19
|
+
//# sourceMappingURL=can-UJ2NAOIR.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getStorageAdapter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2VZZ7M26.js";
|
|
4
4
|
import {
|
|
5
5
|
getDb
|
|
6
6
|
} from "./chunk-XANPEOJC.js";
|
|
@@ -38,4 +38,4 @@ async function getMediaUrl(id, options = {}) {
|
|
|
38
38
|
export {
|
|
39
39
|
getMediaUrl
|
|
40
40
|
};
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
41
|
+
//# sourceMappingURL=chunk-2N53KKIL.js.map
|
|
@@ -170,7 +170,7 @@ async function uploadMedia(file, uploader, folderId) {
|
|
|
170
170
|
return { id, status: "processing" };
|
|
171
171
|
}
|
|
172
172
|
async function assertMemberUploadQuota(memberId, txDb) {
|
|
173
|
-
const { getCommunitySettings } = await import("./settings-
|
|
173
|
+
const { getCommunitySettings } = await import("./settings-OZWM6L2K.js");
|
|
174
174
|
const { NpRateLimitError } = await import("./errors-5OS3S2J3.js");
|
|
175
175
|
const settings = await getCommunitySettings();
|
|
176
176
|
const { perDay, total } = settings.memberUploadQuota;
|
|
@@ -535,4 +535,4 @@ export {
|
|
|
535
535
|
listMedia,
|
|
536
536
|
cleanupDeletedMedia
|
|
537
537
|
};
|
|
538
|
-
//# sourceMappingURL=chunk-
|
|
538
|
+
//# sourceMappingURL=chunk-2VZZ7M26.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runHook
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZA3IRJUQ.js";
|
|
4
4
|
import {
|
|
5
5
|
getAllCollectionSlugs,
|
|
6
6
|
getCollectionConfig,
|
|
@@ -80,4 +80,4 @@ async function publishScheduledDocuments(atTime = /* @__PURE__ */ new Date()) {
|
|
|
80
80
|
export {
|
|
81
81
|
publishScheduledDocuments
|
|
82
82
|
};
|
|
83
|
-
//# sourceMappingURL=chunk-
|
|
83
|
+
//# sourceMappingURL=chunk-54KUQF3S.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-ML2E3P3X.js";
|
|
4
4
|
import {
|
|
5
5
|
getCommunitySettings
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RKM4GDWM.js";
|
|
7
7
|
import {
|
|
8
8
|
NpAuthError,
|
|
9
9
|
NpForbiddenError,
|
|
@@ -65,6 +65,18 @@ function isTokenVerificationError(err) {
|
|
|
65
65
|
return false;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// src/auth/users.ts
|
|
69
|
+
import { eq } from "drizzle-orm";
|
|
70
|
+
async function getUserById(id) {
|
|
71
|
+
const db = getDb();
|
|
72
|
+
const [user] = await db.select({
|
|
73
|
+
id: npUsers.id,
|
|
74
|
+
name: npUsers.name,
|
|
75
|
+
email: npUsers.email
|
|
76
|
+
}).from(npUsers).where(eq(npUsers.id, id)).limit(1);
|
|
77
|
+
return user ?? null;
|
|
78
|
+
}
|
|
79
|
+
|
|
68
80
|
// src/auth/password.ts
|
|
69
81
|
import { hash, verify } from "@node-rs/argon2";
|
|
70
82
|
var ARGON2_OPTIONS = {
|
|
@@ -122,7 +134,7 @@ function resetOAuthProviders() {
|
|
|
122
134
|
}
|
|
123
135
|
|
|
124
136
|
// src/auth/oauth-resolve.ts
|
|
125
|
-
import { eq, and, sql } from "drizzle-orm";
|
|
137
|
+
import { eq as eq2, and, sql } from "drizzle-orm";
|
|
126
138
|
var SYNTHETIC_EMAIL_SUFFIX = ".oauth.local";
|
|
127
139
|
function syntheticEmail(provider, providerUserId) {
|
|
128
140
|
return `${providerUserId}@${provider}${SYNTHETIC_EMAIL_SUFFIX}`;
|
|
@@ -142,13 +154,13 @@ async function resolveOAuthLogin(input) {
|
|
|
142
154
|
identityId: npUserOAuthIdentities.id
|
|
143
155
|
}).from(npUserOAuthIdentities).where(
|
|
144
156
|
and(
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
eq2(npUserOAuthIdentities.provider, provider),
|
|
158
|
+
eq2(npUserOAuthIdentities.providerUserId, profile.providerUserId)
|
|
147
159
|
)
|
|
148
160
|
).limit(1);
|
|
149
161
|
if (existingLink) {
|
|
150
162
|
const metadata = mergeMetadata(profile);
|
|
151
|
-
await db.update(npUserOAuthIdentities).set({ metadata, updatedAt: /* @__PURE__ */ new Date() }).where(
|
|
163
|
+
await db.update(npUserOAuthIdentities).set({ metadata, updatedAt: /* @__PURE__ */ new Date() }).where(eq2(npUserOAuthIdentities.id, existingLink.identityId));
|
|
152
164
|
const user = await loadUser(db, existingLink.userId);
|
|
153
165
|
return { user, created: false, linked: false };
|
|
154
166
|
}
|
|
@@ -160,7 +172,7 @@ async function resolveOAuthLogin(input) {
|
|
|
160
172
|
name: npUsers.name,
|
|
161
173
|
role: npUsers.role,
|
|
162
174
|
tokenVersion: npUsers.tokenVersion
|
|
163
|
-
}).from(npUsers).where(
|
|
175
|
+
}).from(npUsers).where(eq2(sql`lower(${npUsers.email})`, normalizedEmail)).limit(1);
|
|
164
176
|
if (existingUser) {
|
|
165
177
|
await db.insert(npUserOAuthIdentities).values({
|
|
166
178
|
userId: existingUser.id,
|
|
@@ -211,7 +223,7 @@ async function loadUser(db, userId) {
|
|
|
211
223
|
name: npUsers.name,
|
|
212
224
|
role: npUsers.role,
|
|
213
225
|
tokenVersion: npUsers.tokenVersion
|
|
214
|
-
}).from(npUsers).where(
|
|
226
|
+
}).from(npUsers).where(eq2(npUsers.id, userId)).limit(1);
|
|
215
227
|
if (!row) {
|
|
216
228
|
throw new Error(`User ${userId} referenced by oauth identity is missing`);
|
|
217
229
|
}
|
|
@@ -219,7 +231,7 @@ async function loadUser(db, userId) {
|
|
|
219
231
|
}
|
|
220
232
|
|
|
221
233
|
// src/auth/oauth-resolve-member.ts
|
|
222
|
-
import { and as and2, eq as
|
|
234
|
+
import { and as and2, eq as eq3, sql as sql2 } from "drizzle-orm";
|
|
223
235
|
var SYNTHETIC_EMAIL_SUFFIX2 = ".oauth.local";
|
|
224
236
|
var HANDLE_FALLBACK = "user";
|
|
225
237
|
var HANDLE_RANDOM_SUFFIX_BYTES = 4;
|
|
@@ -254,7 +266,7 @@ async function loadMember(db, memberId) {
|
|
|
254
266
|
displayName: npMembers.displayName,
|
|
255
267
|
status: npMembers.status,
|
|
256
268
|
tokenVersion: npMembers.tokenVersion
|
|
257
|
-
}).from(npMembers).where(
|
|
269
|
+
}).from(npMembers).where(eq3(npMembers.id, memberId)).limit(1);
|
|
258
270
|
if (!row) {
|
|
259
271
|
throw new Error(`Member ${memberId} referenced by oauth identity is missing`);
|
|
260
272
|
}
|
|
@@ -265,12 +277,12 @@ async function resolveMemberOAuthLogin(input) {
|
|
|
265
277
|
const { provider, profile } = input;
|
|
266
278
|
const [existingLink] = await db.select({ memberId: npMemberIdentities.memberId, identityId: npMemberIdentities.id }).from(npMemberIdentities).where(
|
|
267
279
|
and2(
|
|
268
|
-
|
|
269
|
-
|
|
280
|
+
eq3(npMemberIdentities.provider, provider),
|
|
281
|
+
eq3(npMemberIdentities.subject, profile.providerUserId)
|
|
270
282
|
)
|
|
271
283
|
).limit(1);
|
|
272
284
|
if (existingLink) {
|
|
273
|
-
await db.update(npMemberIdentities).set({ metadata: mergeMetadata2(profile), updatedAt: /* @__PURE__ */ new Date() }).where(
|
|
285
|
+
await db.update(npMemberIdentities).set({ metadata: mergeMetadata2(profile), updatedAt: /* @__PURE__ */ new Date() }).where(eq3(npMemberIdentities.id, existingLink.identityId));
|
|
274
286
|
const member = await loadMember(db, existingLink.memberId);
|
|
275
287
|
return { member, created: false, linked: false };
|
|
276
288
|
}
|
|
@@ -283,7 +295,7 @@ async function resolveMemberOAuthLogin(input) {
|
|
|
283
295
|
displayName: npMembers.displayName,
|
|
284
296
|
status: npMembers.status,
|
|
285
297
|
tokenVersion: npMembers.tokenVersion
|
|
286
|
-
}).from(npMembers).where(
|
|
298
|
+
}).from(npMembers).where(eq3(sql2`lower(${npMembers.email})`, normalizedEmail)).limit(1);
|
|
287
299
|
if (existingMember) {
|
|
288
300
|
if (existingMember.status !== "active") {
|
|
289
301
|
return { member: existingMember, created: false, linked: false };
|
|
@@ -409,7 +421,7 @@ function fromArctic(factory, opts) {
|
|
|
409
421
|
|
|
410
422
|
// src/auth/session.ts
|
|
411
423
|
import { webcrypto } from "crypto";
|
|
412
|
-
import { eq as
|
|
424
|
+
import { eq as eq4, sql as sql3 } from "drizzle-orm";
|
|
413
425
|
async function sha256(input) {
|
|
414
426
|
const digest = await webcrypto.subtle.digest(
|
|
415
427
|
"SHA-256",
|
|
@@ -428,7 +440,7 @@ async function verifyTokenFull(token, secret, db, expectedUse = "access") {
|
|
|
428
440
|
name: npUsers.name,
|
|
429
441
|
role: npUsers.role,
|
|
430
442
|
tokenVersion: npUsers.tokenVersion
|
|
431
|
-
}).from(npUsers).where(
|
|
443
|
+
}).from(npUsers).where(eq4(npUsers.id, payload.sub)).limit(1);
|
|
432
444
|
if (!user || user.tokenVersion !== payload.ver) {
|
|
433
445
|
return null;
|
|
434
446
|
}
|
|
@@ -438,47 +450,47 @@ async function invalidateAllSessions(userId, db) {
|
|
|
438
450
|
await db.transaction(async (tx) => {
|
|
439
451
|
await tx.update(npUsers).set({
|
|
440
452
|
tokenVersion: sql3`${npUsers.tokenVersion} + 1`
|
|
441
|
-
}).where(
|
|
442
|
-
await tx.delete(npSessions).where(
|
|
453
|
+
}).where(eq4(npUsers.id, userId));
|
|
454
|
+
await tx.delete(npSessions).where(eq4(npSessions.userId, userId));
|
|
443
455
|
});
|
|
444
456
|
}
|
|
445
457
|
|
|
446
458
|
// src/auth/identities-admin.ts
|
|
447
|
-
import { and as and3, desc, eq as
|
|
459
|
+
import { and as and3, desc, eq as eq5 } from "drizzle-orm";
|
|
448
460
|
async function assertUserExists(userId) {
|
|
449
461
|
const db = getDb();
|
|
450
|
-
const [row] = await db.select({ id: npUsers.id }).from(npUsers).where(
|
|
462
|
+
const [row] = await db.select({ id: npUsers.id }).from(npUsers).where(eq5(npUsers.id, userId)).limit(1);
|
|
451
463
|
if (!row) throw new NpNotFoundError("user", userId);
|
|
452
464
|
}
|
|
453
465
|
async function assertMemberExists(memberId) {
|
|
454
466
|
const db = getDb();
|
|
455
|
-
const [row] = await db.select({ id: npMembers.id }).from(npMembers).where(
|
|
467
|
+
const [row] = await db.select({ id: npMembers.id }).from(npMembers).where(eq5(npMembers.id, memberId)).limit(1);
|
|
456
468
|
if (!row) throw new NpNotFoundError("member", memberId);
|
|
457
469
|
}
|
|
458
470
|
async function listUserIdentities(userId) {
|
|
459
471
|
await assertUserExists(userId);
|
|
460
472
|
const db = getDb();
|
|
461
|
-
const rows = await db.select().from(npUserOAuthIdentities).where(
|
|
473
|
+
const rows = await db.select().from(npUserOAuthIdentities).where(eq5(npUserOAuthIdentities.userId, userId)).orderBy(desc(npUserOAuthIdentities.createdAt));
|
|
462
474
|
return rows;
|
|
463
475
|
}
|
|
464
476
|
async function listMemberIdentities(memberId) {
|
|
465
477
|
await assertMemberExists(memberId);
|
|
466
478
|
const db = getDb();
|
|
467
|
-
const rows = await db.select().from(npMemberIdentities).where(
|
|
479
|
+
const rows = await db.select().from(npMemberIdentities).where(eq5(npMemberIdentities.memberId, memberId)).orderBy(desc(npMemberIdentities.createdAt));
|
|
468
480
|
return rows;
|
|
469
481
|
}
|
|
470
482
|
async function revokeUserIdentity(userId, identityId, actor) {
|
|
471
483
|
const db = getDb();
|
|
472
484
|
const [existing] = await db.select().from(npUserOAuthIdentities).where(
|
|
473
485
|
and3(
|
|
474
|
-
|
|
475
|
-
|
|
486
|
+
eq5(npUserOAuthIdentities.id, identityId),
|
|
487
|
+
eq5(npUserOAuthIdentities.userId, userId)
|
|
476
488
|
)
|
|
477
489
|
).limit(1);
|
|
478
490
|
if (!existing) {
|
|
479
491
|
throw new NpNotFoundError("identity", identityId);
|
|
480
492
|
}
|
|
481
|
-
const deleted = await db.delete(npUserOAuthIdentities).where(
|
|
493
|
+
const deleted = await db.delete(npUserOAuthIdentities).where(eq5(npUserOAuthIdentities.id, identityId)).returning({ id: npUserOAuthIdentities.id });
|
|
482
494
|
if (deleted.length === 0) return;
|
|
483
495
|
await recordAuditEvent({
|
|
484
496
|
actor: { kind: "staff", userId: actor.staffUserId },
|
|
@@ -496,12 +508,12 @@ async function revokeMemberIdentity(memberId, identityId, actor) {
|
|
|
496
508
|
const db = getDb();
|
|
497
509
|
const [existing] = await db.select().from(npMemberIdentities).where(
|
|
498
510
|
and3(
|
|
499
|
-
|
|
500
|
-
|
|
511
|
+
eq5(npMemberIdentities.id, identityId),
|
|
512
|
+
eq5(npMemberIdentities.memberId, memberId)
|
|
501
513
|
)
|
|
502
514
|
).limit(1);
|
|
503
515
|
if (!existing) throw new NpNotFoundError("identity", identityId);
|
|
504
|
-
const deleted = await db.delete(npMemberIdentities).where(
|
|
516
|
+
const deleted = await db.delete(npMemberIdentities).where(eq5(npMemberIdentities.id, identityId)).returning({ id: npMemberIdentities.id });
|
|
505
517
|
if (deleted.length === 0) return;
|
|
506
518
|
await recordAuditEvent({
|
|
507
519
|
actor: { kind: "staff", userId: actor.staffUserId },
|
|
@@ -518,7 +530,7 @@ async function revokeMemberIdentity(memberId, identityId, actor) {
|
|
|
518
530
|
|
|
519
531
|
// src/auth/reset-token.ts
|
|
520
532
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
521
|
-
import { and as and4, eq as
|
|
533
|
+
import { and as and4, eq as eq6, gt, isNotNull, sql as sql4 } from "drizzle-orm";
|
|
522
534
|
var MIN_PASSWORD_LENGTH = 8;
|
|
523
535
|
function generateRawToken() {
|
|
524
536
|
return randomBytes3(32).toString("hex");
|
|
@@ -532,7 +544,7 @@ async function createPasswordResetToken(db, options) {
|
|
|
532
544
|
passwordResetExpiresAt: expiresAt,
|
|
533
545
|
passwordResetPurpose: options.purpose,
|
|
534
546
|
updatedAt: /* @__PURE__ */ new Date()
|
|
535
|
-
}).where(
|
|
547
|
+
}).where(eq6(npUsers.id, options.userId));
|
|
536
548
|
return { token, expiresAt, purpose: options.purpose };
|
|
537
549
|
}
|
|
538
550
|
async function requestPasswordReset(db, email, ttlMs) {
|
|
@@ -541,7 +553,7 @@ async function requestPasswordReset(db, email, ttlMs) {
|
|
|
541
553
|
id: npUsers.id,
|
|
542
554
|
email: npUsers.email,
|
|
543
555
|
name: npUsers.name
|
|
544
|
-
}).from(npUsers).where(
|
|
556
|
+
}).from(npUsers).where(eq6(npUsers.email, normalizedEmail)).limit(1);
|
|
545
557
|
if (!user) {
|
|
546
558
|
return { userId: null, name: null, email: null, issued: null };
|
|
547
559
|
}
|
|
@@ -574,7 +586,7 @@ async function consumePasswordResetToken(db, options) {
|
|
|
574
586
|
purpose: npUsers.passwordResetPurpose
|
|
575
587
|
}).from(npUsers).where(
|
|
576
588
|
and4(
|
|
577
|
-
|
|
589
|
+
eq6(npUsers.passwordResetTokenHash, tokenHash),
|
|
578
590
|
isNotNull(npUsers.passwordResetExpiresAt),
|
|
579
591
|
gt(npUsers.passwordResetExpiresAt, now)
|
|
580
592
|
)
|
|
@@ -595,8 +607,8 @@ async function consumePasswordResetToken(db, options) {
|
|
|
595
607
|
lockUntil: null,
|
|
596
608
|
tokenVersion: sql4`${npUsers.tokenVersion} + 1`,
|
|
597
609
|
updatedAt: /* @__PURE__ */ new Date()
|
|
598
|
-
}).where(
|
|
599
|
-
await tx.delete(npSessions).where(
|
|
610
|
+
}).where(eq6(npUsers.id, user.id));
|
|
611
|
+
await tx.delete(npSessions).where(eq6(npSessions.userId, user.id));
|
|
600
612
|
});
|
|
601
613
|
return {
|
|
602
614
|
userId: user.id,
|
|
@@ -631,7 +643,7 @@ async function verifyMemberToken(token, secret, expectedUse) {
|
|
|
631
643
|
}
|
|
632
644
|
|
|
633
645
|
// src/auth/member-session.ts
|
|
634
|
-
import { and as and5, eq as
|
|
646
|
+
import { and as and5, eq as eq7, gt as gt2, sql as sql5 } from "drizzle-orm";
|
|
635
647
|
async function getMemberFromTokenPayload(db, payload, accessToken) {
|
|
636
648
|
const [row] = await db.select({
|
|
637
649
|
id: npMembers.id,
|
|
@@ -640,7 +652,7 @@ async function getMemberFromTokenPayload(db, payload, accessToken) {
|
|
|
640
652
|
displayName: npMembers.displayName,
|
|
641
653
|
status: npMembers.status,
|
|
642
654
|
tokenVersion: npMembers.tokenVersion
|
|
643
|
-
}).from(npMembers).where(
|
|
655
|
+
}).from(npMembers).where(eq7(npMembers.id, payload.sub)).limit(1);
|
|
644
656
|
if (!row) return null;
|
|
645
657
|
if (row.tokenVersion !== payload.ver) return null;
|
|
646
658
|
if (accessToken) {
|
|
@@ -648,8 +660,8 @@ async function getMemberFromTokenPayload(db, payload, accessToken) {
|
|
|
648
660
|
const now = /* @__PURE__ */ new Date();
|
|
649
661
|
const [session] = await db.select({ id: npMemberSessions.id }).from(npMemberSessions).where(
|
|
650
662
|
and5(
|
|
651
|
-
|
|
652
|
-
|
|
663
|
+
eq7(npMemberSessions.memberId, row.id),
|
|
664
|
+
eq7(npMemberSessions.tokenHash, tokenHash),
|
|
653
665
|
gt2(npMemberSessions.expiresAt, now)
|
|
654
666
|
)
|
|
655
667
|
).limit(1);
|
|
@@ -662,14 +674,14 @@ async function invalidateAllMemberSessions(db, memberId) {
|
|
|
662
674
|
await tx.update(npMembers).set({
|
|
663
675
|
tokenVersion: sql5`${npMembers.tokenVersion} + 1`,
|
|
664
676
|
updatedAt: /* @__PURE__ */ new Date()
|
|
665
|
-
}).where(
|
|
666
|
-
await tx.delete(npMemberSessions).where(
|
|
677
|
+
}).where(eq7(npMembers.id, memberId));
|
|
678
|
+
await tx.delete(npMemberSessions).where(eq7(npMemberSessions.memberId, memberId));
|
|
667
679
|
});
|
|
668
680
|
}
|
|
669
681
|
|
|
670
682
|
// src/auth/member-credentials.ts
|
|
671
683
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
672
|
-
import { and as and6, eq as
|
|
684
|
+
import { and as and6, eq as eq8, gt as gt3, isNotNull as isNotNull2, sql as sql6 } from "drizzle-orm";
|
|
673
685
|
var MIN_PASSWORD_LENGTH2 = 8;
|
|
674
686
|
function generateRawToken2() {
|
|
675
687
|
return randomBytes5(32).toString("hex");
|
|
@@ -682,7 +694,7 @@ async function createMemberEmailVerifyToken(db, memberId, ttlMs) {
|
|
|
682
694
|
emailVerifyTokenHash: tokenHash,
|
|
683
695
|
emailVerifyExpiresAt: expiresAt,
|
|
684
696
|
updatedAt: /* @__PURE__ */ new Date()
|
|
685
|
-
}).where(
|
|
697
|
+
}).where(eq8(npMembers.id, memberId));
|
|
686
698
|
return { token, expiresAt };
|
|
687
699
|
}
|
|
688
700
|
async function consumeMemberEmailVerifyToken(db, token) {
|
|
@@ -700,7 +712,7 @@ async function consumeMemberEmailVerifyToken(db, token) {
|
|
|
700
712
|
displayName: npMembers.displayName
|
|
701
713
|
}).from(npMembers).where(
|
|
702
714
|
and6(
|
|
703
|
-
|
|
715
|
+
eq8(npMembers.emailVerifyTokenHash, tokenHash),
|
|
704
716
|
isNotNull2(npMembers.emailVerifyExpiresAt),
|
|
705
717
|
gt3(npMembers.emailVerifyExpiresAt, now)
|
|
706
718
|
)
|
|
@@ -719,7 +731,7 @@ async function consumeMemberEmailVerifyToken(db, token) {
|
|
|
719
731
|
emailVerifyTokenHash: null,
|
|
720
732
|
emailVerifyExpiresAt: null,
|
|
721
733
|
updatedAt: now
|
|
722
|
-
}).where(
|
|
734
|
+
}).where(eq8(npMembers.id, member.id));
|
|
723
735
|
return {
|
|
724
736
|
memberId: member.id,
|
|
725
737
|
email: member.email,
|
|
@@ -734,7 +746,7 @@ async function requestMemberPasswordReset(db, email, ttlMs) {
|
|
|
734
746
|
email: npMembers.email,
|
|
735
747
|
displayName: npMembers.displayName,
|
|
736
748
|
status: npMembers.status
|
|
737
|
-
}).from(npMembers).where(
|
|
749
|
+
}).from(npMembers).where(eq8(npMembers.email, normalizedEmail)).limit(1);
|
|
738
750
|
if (!member || member.status === "deleted") {
|
|
739
751
|
return { memberId: null, displayName: null, email: null, issued: null };
|
|
740
752
|
}
|
|
@@ -745,7 +757,7 @@ async function requestMemberPasswordReset(db, email, ttlMs) {
|
|
|
745
757
|
passwordResetTokenHash: tokenHash,
|
|
746
758
|
passwordResetExpiresAt: expiresAt,
|
|
747
759
|
updatedAt: /* @__PURE__ */ new Date()
|
|
748
|
-
}).where(
|
|
760
|
+
}).where(eq8(npMembers.id, member.id));
|
|
749
761
|
return {
|
|
750
762
|
memberId: member.id,
|
|
751
763
|
displayName: member.displayName,
|
|
@@ -771,7 +783,7 @@ async function consumeMemberPasswordReset(db, token, newPassword) {
|
|
|
771
783
|
const now = /* @__PURE__ */ new Date();
|
|
772
784
|
const [member] = await db.select({ id: npMembers.id, email: npMembers.email }).from(npMembers).where(
|
|
773
785
|
and6(
|
|
774
|
-
|
|
786
|
+
eq8(npMembers.passwordResetTokenHash, tokenHash),
|
|
775
787
|
isNotNull2(npMembers.passwordResetExpiresAt),
|
|
776
788
|
gt3(npMembers.passwordResetExpiresAt, now)
|
|
777
789
|
)
|
|
@@ -796,8 +808,8 @@ async function consumeMemberPasswordReset(db, token, newPassword) {
|
|
|
796
808
|
emailVerified: true,
|
|
797
809
|
status: sql6`case when ${npMembers.status} = 'pending' then 'active' else ${npMembers.status} end`,
|
|
798
810
|
updatedAt: /* @__PURE__ */ new Date()
|
|
799
|
-
}).where(
|
|
800
|
-
await tx.delete(npMemberSessions).where(
|
|
811
|
+
}).where(eq8(npMembers.id, member.id));
|
|
812
|
+
await tx.delete(npMemberSessions).where(eq8(npMemberSessions.memberId, member.id));
|
|
801
813
|
});
|
|
802
814
|
return { memberId: member.id, email: member.email };
|
|
803
815
|
}
|
|
@@ -810,6 +822,7 @@ export {
|
|
|
810
822
|
signToken,
|
|
811
823
|
verifyToken,
|
|
812
824
|
isTokenVerificationError,
|
|
825
|
+
getUserById,
|
|
813
826
|
ARGON2_OPTIONS,
|
|
814
827
|
hashPassword,
|
|
815
828
|
verifyPassword,
|
|
@@ -842,4 +855,4 @@ export {
|
|
|
842
855
|
requestMemberPasswordReset,
|
|
843
856
|
consumeMemberPasswordReset
|
|
844
857
|
};
|
|
845
|
-
//# sourceMappingURL=chunk-
|
|
858
|
+
//# sourceMappingURL=chunk-6UV2P5MW.js.map
|