@vue-skuilder/express 0.1.12 → 0.1.13-10
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/app-factory.d.ts.map +1 -1
- package/dist/app-factory.js +12 -0
- package/dist/app-factory.js.map +1 -1
- package/dist/couchdb/userDesignDocs.d.ts +37 -0
- package/dist/couchdb/userDesignDocs.d.ts.map +1 -0
- package/dist/couchdb/userDesignDocs.js +78 -0
- package/dist/couchdb/userDesignDocs.js.map +1 -0
- package/dist/couchdb/userLookup.d.ts +22 -0
- package/dist/couchdb/userLookup.d.ts.map +1 -0
- package/dist/couchdb/userLookup.js +146 -0
- package/dist/couchdb/userLookup.js.map +1 -0
- package/dist/routes/auth.d.ts +3 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +233 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/services/email.d.ts +17 -0
- package/dist/services/email.d.ts.map +1 -0
- package/dist/services/email.js +78 -0
- package/dist/services/email.js.map +1 -0
- package/dist/utils/tokens.d.ts +18 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js +27 -0
- package/dist/utils/tokens.js.map +1 -0
- package/dist/utils/types.d.ts +7 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +7 -0
- package/dist/utils/types.js.map +1 -0
- package/package.json +4 -4
- package/src/app-factory.ts +16 -4
- package/src/couchdb/userDesignDocs.ts +84 -0
- package/src/couchdb/userLookup.ts +173 -0
- package/src/routes/auth.ts +292 -0
- package/src/services/email.ts +100 -0
- package/src/utils/tokens.ts +29 -0
- package/src/utils/types.ts +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-factory.d.ts","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,aAAa,EAEd,MAAM,sBAAsB,CAAC;AAK9B,OAAO,OAAO,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"app-factory.d.ts","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,aAAa,EAEd,MAAM,sBAAsB,CAAC;AAK9B,OAAO,OAAO,MAAM,SAAS,CAAC;AAoB9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGzE,MAAM,WAAW,gBAAiB,SAAQ,OAAO,CAAC,OAAO;IACvD,IAAI,EAAE,aAAa,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAwBhE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CA+LvE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DzE"}
|
package/dist/app-factory.js
CHANGED
|
@@ -14,6 +14,8 @@ import { getCouchDB, initializeCouchDB, useOrCreateCourseDB, useOrCreateDB } fro
|
|
|
14
14
|
import { classroomDbDesignDoc } from './design-docs.js';
|
|
15
15
|
import logger from './logger.js';
|
|
16
16
|
import logsRouter from './routes/logs.js';
|
|
17
|
+
import authRouter from './routes/auth.js';
|
|
18
|
+
import { applyUsersDesignDocs } from './couchdb/userDesignDocs.js';
|
|
17
19
|
/**
|
|
18
20
|
* Type guard to determine if config is ExpressServerConfig (programmatic usage)
|
|
19
21
|
*/
|
|
@@ -58,6 +60,7 @@ export function createExpressApp(config) {
|
|
|
58
60
|
stream: { write: (message) => logger.info(message.trim()) },
|
|
59
61
|
}));
|
|
60
62
|
app.use('/logs', logsRouter);
|
|
63
|
+
app.use('/auth', authRouter);
|
|
61
64
|
// Routes
|
|
62
65
|
app.get('/courses', (_req, res) => {
|
|
63
66
|
void (async () => {
|
|
@@ -229,6 +232,15 @@ export async function initializeServices(config) {
|
|
|
229
232
|
// In programmatic mode, we shouldn't exit the process, but let the error propagate
|
|
230
233
|
throw e;
|
|
231
234
|
});
|
|
235
|
+
// Apply design documents to _users database for auth flows
|
|
236
|
+
try {
|
|
237
|
+
await applyUsersDesignDocs();
|
|
238
|
+
logger.info('Auth design documents applied successfully');
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
logger.error('Error applying auth design documents:', error);
|
|
242
|
+
// Don't throw - auth design docs are nice-to-have, not critical for startup
|
|
243
|
+
}
|
|
232
244
|
try {
|
|
233
245
|
// start the change-listener that does post-processing on user
|
|
234
246
|
// media uploads
|
package/dist/app-factory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-factory.js","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACL,iBAAiB,IAAI,WAAW,EAEhC,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,WAAW,MAAM,qCAAqC,CAAC;AAC9D,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,UAAU,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"app-factory.js","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design documents for _users database.
|
|
3
|
+
* Provides views for efficient user lookups by email and tokens.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Design document for user lookups in _users database.
|
|
7
|
+
*/
|
|
8
|
+
export declare const usersDesignDoc: {
|
|
9
|
+
_id: string;
|
|
10
|
+
views: {
|
|
11
|
+
/**
|
|
12
|
+
* Index users by email address.
|
|
13
|
+
*/
|
|
14
|
+
by_email: {
|
|
15
|
+
map: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Index users by verification token.
|
|
19
|
+
*/
|
|
20
|
+
by_verification_token: {
|
|
21
|
+
map: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Index users by password reset token.
|
|
25
|
+
*/
|
|
26
|
+
by_reset_token: {
|
|
27
|
+
map: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
language: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Apply design documents to _users database.
|
|
34
|
+
* Safe to call multiple times - will only update if changed.
|
|
35
|
+
*/
|
|
36
|
+
export declare function applyUsersDesignDocs(): Promise<void>;
|
|
37
|
+
//# sourceMappingURL=userDesignDocs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userDesignDocs.d.ts","sourceRoot":"","sources":["../../src/couchdb/userDesignDocs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;GAEG;AACH,eAAO,MAAM,cAAc;;;QAGvB;;WAEG;;;;QAQH;;WAEG;;;;QAQH;;WAEG;;;;;;CAUN,CAAC;AAEF;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6B1D"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design documents for _users database.
|
|
3
|
+
* Provides views for efficient user lookups by email and tokens.
|
|
4
|
+
*/
|
|
5
|
+
import { getCouchDB } from './index.js';
|
|
6
|
+
import logger from '../logger.js';
|
|
7
|
+
import { isNanoError } from '../utils/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Design document for user lookups in _users database.
|
|
10
|
+
*/
|
|
11
|
+
export const usersDesignDoc = {
|
|
12
|
+
_id: '_design/users',
|
|
13
|
+
views: {
|
|
14
|
+
/**
|
|
15
|
+
* Index users by email address.
|
|
16
|
+
*/
|
|
17
|
+
by_email: {
|
|
18
|
+
map: `function(doc) {
|
|
19
|
+
if (doc.type === 'user' && doc.email) {
|
|
20
|
+
emit(doc.email, doc._id);
|
|
21
|
+
}
|
|
22
|
+
}`,
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* Index users by verification token.
|
|
26
|
+
*/
|
|
27
|
+
by_verification_token: {
|
|
28
|
+
map: `function(doc) {
|
|
29
|
+
if (doc.type === 'user' && doc.verificationToken) {
|
|
30
|
+
emit(doc.verificationToken, doc._id);
|
|
31
|
+
}
|
|
32
|
+
}`,
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Index users by password reset token.
|
|
36
|
+
*/
|
|
37
|
+
by_reset_token: {
|
|
38
|
+
map: `function(doc) {
|
|
39
|
+
if (doc.type === 'user' && doc.passwordResetToken) {
|
|
40
|
+
emit(doc.passwordResetToken, doc._id);
|
|
41
|
+
}
|
|
42
|
+
}`,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
language: 'javascript',
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Apply design documents to _users database.
|
|
49
|
+
* Safe to call multiple times - will only update if changed.
|
|
50
|
+
*/
|
|
51
|
+
export async function applyUsersDesignDocs() {
|
|
52
|
+
try {
|
|
53
|
+
const usersDB = getCouchDB().use('_users');
|
|
54
|
+
// Try to get existing design doc
|
|
55
|
+
let existingDoc = null;
|
|
56
|
+
try {
|
|
57
|
+
existingDoc = await usersDB.get(usersDesignDoc._id);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (isNanoError(error) && error.statusCode !== 404) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
// Doc doesn't exist, will create new
|
|
64
|
+
}
|
|
65
|
+
// Prepare doc with _rev if updating
|
|
66
|
+
const docToInsert = existingDoc
|
|
67
|
+
? { ...usersDesignDoc, _rev: existingDoc._rev }
|
|
68
|
+
: usersDesignDoc;
|
|
69
|
+
await usersDB.insert(docToInsert);
|
|
70
|
+
logger.info(`Applied design doc ${usersDesignDoc._id} to _users database` +
|
|
71
|
+
(existingDoc ? ' (updated)' : ' (created)'));
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logger.error('Error applying _users design documents:', error);
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=userDesignDocs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userDesignDocs.js","sourceRoot":"","sources":["../../src/couchdb/userDesignDocs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,GAAG,EAAE,eAAe;IACpB,KAAK,EAAE;QACL;;WAEG;QACH,QAAQ,EAAE;YACR,GAAG,EAAE;;;;QAIH;SACH;QACD;;WAEG;QACH,qBAAqB,EAAE;YACrB,GAAG,EAAE;;;;QAIH;SACH;QACD;;WAEG;QACH,cAAc,EAAE;YACd,GAAG,EAAE;;;;QAIH;SACH;KACF;IACD,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE3C,iCAAiC;QACjC,IAAI,WAAW,GAAoC,IAAI,CAAC;QACxD,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBACnD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,qCAAqC;QACvC,CAAC;QAED,oCAAoC;QACpC,MAAM,WAAW,GAAG,WAAW;YAC7B,CAAC,CAAC,EAAE,GAAG,cAAc,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE;YAC/C,CAAC,CAAC,cAAc,CAAC;QAEnB,MAAM,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CACT,sBAAsB,cAAc,CAAC,GAAG,qBAAqB;YAC3D,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAC9C,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;QAC/D,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CouchDbUserDoc } from '@vue-skuilder/db';
|
|
2
|
+
/**
|
|
3
|
+
* Find user document by username.
|
|
4
|
+
*/
|
|
5
|
+
export declare function findUserByUsername(username: string): Promise<CouchDbUserDoc | null>;
|
|
6
|
+
/**
|
|
7
|
+
* Get user's email from their personal database CONFIG document.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getUserEmail(username: string): Promise<string | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Find user by verification or password reset token using design doc views.
|
|
12
|
+
*/
|
|
13
|
+
export declare function findUserByToken(token: string, tokenType: 'verification' | 'reset'): Promise<CouchDbUserDoc | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Find user by email using design doc view.
|
|
16
|
+
*/
|
|
17
|
+
export declare function findUserByEmail(email: string): Promise<CouchDbUserDoc | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Update user document in _users database.
|
|
20
|
+
*/
|
|
21
|
+
export declare function updateUserDoc(userDoc: CouchDbUserDoc): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=userLookup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userLookup.d.ts","sourceRoot":"","sources":["../../src/couchdb/userLookup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,kBAAkB,CAAC;AAqDnE;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAahC;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkB3E;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,cAAc,GAAG,OAAO,GAClC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyBhC;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAuBhC;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1E"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { getCouchDB } from './index.js';
|
|
2
|
+
import logger from '../logger.js';
|
|
3
|
+
import { isNanoError } from '../utils/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* User lookup utilities for authentication flows.
|
|
6
|
+
* Provides helper functions to query _users DB and user databases.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Get the _users database instance.
|
|
10
|
+
*/
|
|
11
|
+
function getUsersDB() {
|
|
12
|
+
return getCouchDB().use('_users');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get a user's personal database instance.
|
|
16
|
+
*/
|
|
17
|
+
function getUserDB(username) {
|
|
18
|
+
const userDbName = `userdb-${hexEncode(username)}`;
|
|
19
|
+
return getCouchDB().use(userDbName);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Convert string to hex encoding (for userdb naming).
|
|
23
|
+
* @param str - String to encode (typically username)
|
|
24
|
+
* @throws Error if string exceeds maximum safe length
|
|
25
|
+
*/
|
|
26
|
+
function hexEncode(str) {
|
|
27
|
+
// Prevent DoS via extremely long usernames
|
|
28
|
+
// CouchDB usernames are typically limited to 256 chars, but we'll be more restrictive
|
|
29
|
+
const MAX_USERNAME_LENGTH = 256;
|
|
30
|
+
if (str.length > MAX_USERNAME_LENGTH) {
|
|
31
|
+
throw new Error(`Username exceeds maximum length of ${MAX_USERNAME_LENGTH} characters`);
|
|
32
|
+
}
|
|
33
|
+
let hex;
|
|
34
|
+
let returnStr = '';
|
|
35
|
+
const len = str.length; // Cache length to avoid repeated property access
|
|
36
|
+
for (let i = 0; i < len; i++) {
|
|
37
|
+
hex = str.charCodeAt(i).toString(16);
|
|
38
|
+
returnStr += ('000' + hex).slice(-4);
|
|
39
|
+
}
|
|
40
|
+
return returnStr;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Find user document by username.
|
|
44
|
+
*/
|
|
45
|
+
export async function findUserByUsername(username) {
|
|
46
|
+
try {
|
|
47
|
+
const usersDB = getUsersDB();
|
|
48
|
+
const docId = `org.couchdb.user:${username}`;
|
|
49
|
+
const userDoc = await usersDB.get(docId);
|
|
50
|
+
return userDoc;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (isNanoError(error) && error.statusCode === 404) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
logger.error(`Error finding user by username ${username}:`, error);
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get user's email from their personal database CONFIG document.
|
|
62
|
+
*/
|
|
63
|
+
export async function getUserEmail(username) {
|
|
64
|
+
try {
|
|
65
|
+
const userDB = getUserDB(username);
|
|
66
|
+
const configDoc = await userDB.get('CONFIG');
|
|
67
|
+
if (configDoc && typeof configDoc === 'object' && 'email' in configDoc) {
|
|
68
|
+
return configDoc.email || null;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (isNanoError(error) && error.statusCode === 404) {
|
|
74
|
+
logger.warn(`No CONFIG doc found for user ${username}`);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
logger.error(`Error getting email for user ${username}:`, error);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Find user by verification or password reset token using design doc views.
|
|
83
|
+
*/
|
|
84
|
+
export async function findUserByToken(token, tokenType) {
|
|
85
|
+
try {
|
|
86
|
+
const usersDB = getUsersDB();
|
|
87
|
+
const viewName = tokenType === 'verification' ? 'by_verification_token' : 'by_reset_token';
|
|
88
|
+
const result = await usersDB.view('users', viewName, {
|
|
89
|
+
key: token,
|
|
90
|
+
include_docs: true,
|
|
91
|
+
limit: 1,
|
|
92
|
+
});
|
|
93
|
+
if (result.rows.length > 0 && result.rows[0].doc) {
|
|
94
|
+
return result.rows[0].doc;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (isNanoError(error) && error.statusCode === 404) {
|
|
100
|
+
logger.warn(`Design doc or view not found for ${tokenType} token lookup`);
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
logger.error(`Error finding user by ${tokenType} token:`, error);
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Find user by email using design doc view.
|
|
109
|
+
*/
|
|
110
|
+
export async function findUserByEmail(email) {
|
|
111
|
+
try {
|
|
112
|
+
const usersDB = getUsersDB();
|
|
113
|
+
const result = await usersDB.view('users', 'by_email', {
|
|
114
|
+
key: email,
|
|
115
|
+
include_docs: true,
|
|
116
|
+
limit: 1,
|
|
117
|
+
});
|
|
118
|
+
if (result.rows.length > 0 && result.rows[0].doc) {
|
|
119
|
+
return result.rows[0].doc;
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (isNanoError(error) && error.statusCode === 404) {
|
|
125
|
+
logger.warn('Design doc or view not found for email lookup');
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
logger.error(`Error finding user by email ${email}:`, error);
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Update user document in _users database.
|
|
134
|
+
*/
|
|
135
|
+
export async function updateUserDoc(userDoc) {
|
|
136
|
+
try {
|
|
137
|
+
const usersDB = getUsersDB();
|
|
138
|
+
await usersDB.insert(userDoc);
|
|
139
|
+
logger.info(`Updated user doc for ${userDoc.name}`);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
logger.error(`Error updating user doc for ${userDoc.name}:`, error);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=userLookup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userLookup.js","sourceRoot":"","sources":["../../src/couchdb/userLookup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"AA2BA,QAAA,MAAM,MAAM,4CAAmB,CAAC;AAwQhC,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import Nano from 'nano';
|
|
3
|
+
import { getCouchURLWithProtocol } from '../couchdb/index.js';
|
|
4
|
+
import { findUserByUsername, findUserByToken, findUserByEmail, getUserEmail, updateUserDoc, } from '../couchdb/userLookup.js';
|
|
5
|
+
import { generateSecureToken, getTokenExpiry, isTokenExpired } from '../utils/tokens.js';
|
|
6
|
+
import { sendVerificationEmail, sendPasswordResetEmail } from '../services/email.js';
|
|
7
|
+
import logger from '../logger.js';
|
|
8
|
+
const router = express.Router();
|
|
9
|
+
/**
|
|
10
|
+
* POST /auth/send-verification
|
|
11
|
+
* Trigger verification email for a newly created account.
|
|
12
|
+
*
|
|
13
|
+
* Body params:
|
|
14
|
+
* - username: string (required)
|
|
15
|
+
* - email: string (optional) - If provided, uses this email directly (avoids DB sync race condition)
|
|
16
|
+
* - origin: string (optional) - Frontend origin URL for constructing verification link
|
|
17
|
+
*/
|
|
18
|
+
router.post('/send-verification', (req, res) => {
|
|
19
|
+
void (async () => {
|
|
20
|
+
try {
|
|
21
|
+
const { username, email: providedEmail, origin } = req.body;
|
|
22
|
+
if (!username) {
|
|
23
|
+
return res.status(400).json({ ok: false, error: 'Username required' });
|
|
24
|
+
}
|
|
25
|
+
// Get user doc
|
|
26
|
+
const userDoc = await findUserByUsername(username);
|
|
27
|
+
if (!userDoc) {
|
|
28
|
+
return res.status(404).json({ ok: false, error: 'User not found' });
|
|
29
|
+
}
|
|
30
|
+
// Use provided email if available, otherwise lookup in database
|
|
31
|
+
let email = providedEmail;
|
|
32
|
+
if (!email) {
|
|
33
|
+
email = await getUserEmail(username);
|
|
34
|
+
if (!email) {
|
|
35
|
+
return res.status(400).json({
|
|
36
|
+
ok: false,
|
|
37
|
+
error: 'No email found for user. Please provide email during registration.',
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Generate verification token (24 hour expiry)
|
|
42
|
+
const token = generateSecureToken();
|
|
43
|
+
const expiresAt = getTokenExpiry(24);
|
|
44
|
+
// Update user doc with token and email (for password reset lookup)
|
|
45
|
+
userDoc.verificationToken = token;
|
|
46
|
+
userDoc.verificationTokenExpiresAt = expiresAt;
|
|
47
|
+
userDoc.status = 'pending_verification';
|
|
48
|
+
// Save email to _users doc if not already present (enables findUserByEmail)
|
|
49
|
+
if (email && !userDoc.email) {
|
|
50
|
+
userDoc.email = email;
|
|
51
|
+
}
|
|
52
|
+
await updateUserDoc(userDoc);
|
|
53
|
+
// Send verification email with origin for link construction
|
|
54
|
+
await sendVerificationEmail(email, token, origin);
|
|
55
|
+
logger.info(`Verification email sent to ${username} at ${email}`);
|
|
56
|
+
res.json({ ok: true });
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
logger.error('Error sending verification email:', error);
|
|
60
|
+
res.status(500).json({
|
|
61
|
+
ok: false,
|
|
62
|
+
error: 'Failed to send verification email',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* POST /auth/verify
|
|
69
|
+
* Complete email verification using token.
|
|
70
|
+
*/
|
|
71
|
+
router.post('/verify', (req, res) => {
|
|
72
|
+
void (async () => {
|
|
73
|
+
try {
|
|
74
|
+
const { token } = req.body;
|
|
75
|
+
if (!token) {
|
|
76
|
+
return res.status(400).json({ ok: false, error: 'Token required' });
|
|
77
|
+
}
|
|
78
|
+
// Find user by verification token
|
|
79
|
+
const userDoc = await findUserByToken(token, 'verification');
|
|
80
|
+
if (!userDoc) {
|
|
81
|
+
return res.status(404).json({ ok: false, error: 'Invalid or expired token' });
|
|
82
|
+
}
|
|
83
|
+
// Check token expiry
|
|
84
|
+
if (userDoc.verificationTokenExpiresAt &&
|
|
85
|
+
isTokenExpired(userDoc.verificationTokenExpiresAt)) {
|
|
86
|
+
return res.status(400).json({ ok: false, error: 'Token has expired' });
|
|
87
|
+
}
|
|
88
|
+
// Update user status
|
|
89
|
+
userDoc.status = 'verified';
|
|
90
|
+
userDoc.verificationToken = null;
|
|
91
|
+
userDoc.verificationTokenExpiresAt = null;
|
|
92
|
+
await updateUserDoc(userDoc);
|
|
93
|
+
logger.info(`User ${userDoc.name} verified successfully`);
|
|
94
|
+
res.json({ ok: true, username: userDoc.name });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
logger.error('Error verifying email:', error);
|
|
98
|
+
res.status(500).json({
|
|
99
|
+
ok: false,
|
|
100
|
+
error: 'Failed to verify email',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
})();
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* GET /auth/status
|
|
107
|
+
* Get current user's account status (verification status, email).
|
|
108
|
+
* Requires AuthSession cookie.
|
|
109
|
+
*/
|
|
110
|
+
router.get('/status', (req, res) => {
|
|
111
|
+
void (async () => {
|
|
112
|
+
try {
|
|
113
|
+
const authCookie = req.cookies?.AuthSession;
|
|
114
|
+
if (!authCookie) {
|
|
115
|
+
return res.status(401).json({ ok: false, error: 'Not authenticated' });
|
|
116
|
+
}
|
|
117
|
+
// Verify session with CouchDB to get username
|
|
118
|
+
const session = await Nano({
|
|
119
|
+
cookie: 'AuthSession=' + authCookie,
|
|
120
|
+
url: getCouchURLWithProtocol(),
|
|
121
|
+
}).session();
|
|
122
|
+
const username = session.userCtx.name;
|
|
123
|
+
if (!username) {
|
|
124
|
+
return res.status(401).json({ ok: false, error: 'Invalid session' });
|
|
125
|
+
}
|
|
126
|
+
// Use admin credentials to read user's status from _users
|
|
127
|
+
const userDoc = await findUserByUsername(username);
|
|
128
|
+
if (!userDoc) {
|
|
129
|
+
return res.status(404).json({ ok: false, error: 'User not found' });
|
|
130
|
+
}
|
|
131
|
+
res.json({
|
|
132
|
+
ok: true,
|
|
133
|
+
username: userDoc.name,
|
|
134
|
+
status: userDoc.status || 'pending_verification', // Default to pending if not explicitly set
|
|
135
|
+
email: userDoc.email || null,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
logger.error('Error fetching user status:', error);
|
|
140
|
+
res.status(500).json({ ok: false, error: 'Failed to fetch user status' });
|
|
141
|
+
}
|
|
142
|
+
})();
|
|
143
|
+
});
|
|
144
|
+
/**
|
|
145
|
+
* POST /auth/request-reset
|
|
146
|
+
* Request password reset email.
|
|
147
|
+
*
|
|
148
|
+
* Body params:
|
|
149
|
+
* - email: string (required)
|
|
150
|
+
* - origin: string (optional) - Frontend origin URL for constructing reset link
|
|
151
|
+
*/
|
|
152
|
+
router.post('/request-reset', (req, res) => {
|
|
153
|
+
void (async () => {
|
|
154
|
+
try {
|
|
155
|
+
const { email, origin } = req.body;
|
|
156
|
+
if (!email) {
|
|
157
|
+
return res.status(400).json({ ok: false, error: 'Email required' });
|
|
158
|
+
}
|
|
159
|
+
// Find user by email (using design doc view)
|
|
160
|
+
const userDoc = await findUserByEmail(email);
|
|
161
|
+
if (!userDoc) {
|
|
162
|
+
// Don't reveal whether email exists (security best practice)
|
|
163
|
+
logger.warn(`Password reset requested for non-existent email: ${email}`);
|
|
164
|
+
return res.json({ ok: true }); // Return success anyway
|
|
165
|
+
}
|
|
166
|
+
// Generate reset token (1 hour expiry)
|
|
167
|
+
const token = generateSecureToken();
|
|
168
|
+
const expiresAt = getTokenExpiry(1);
|
|
169
|
+
// Update user doc with reset token
|
|
170
|
+
userDoc.passwordResetToken = token;
|
|
171
|
+
userDoc.passwordResetTokenExpiresAt = expiresAt;
|
|
172
|
+
await updateUserDoc(userDoc);
|
|
173
|
+
// Send password reset email with origin for link construction
|
|
174
|
+
await sendPasswordResetEmail(email, token, origin);
|
|
175
|
+
logger.info(`Password reset email sent to ${userDoc.name} at ${email}`);
|
|
176
|
+
res.json({ ok: true });
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
logger.error('Error requesting password reset:', error);
|
|
180
|
+
res.status(500).json({
|
|
181
|
+
ok: false,
|
|
182
|
+
error: 'Failed to send password reset email',
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
})();
|
|
186
|
+
});
|
|
187
|
+
/**
|
|
188
|
+
* POST /auth/reset-password
|
|
189
|
+
* Reset password using token.
|
|
190
|
+
*/
|
|
191
|
+
router.post('/reset-password', (req, res) => {
|
|
192
|
+
void (async () => {
|
|
193
|
+
try {
|
|
194
|
+
const { token, newPassword } = req.body;
|
|
195
|
+
if (!token || !newPassword) {
|
|
196
|
+
return res.status(400).json({ ok: false, error: 'Token and new password required' });
|
|
197
|
+
}
|
|
198
|
+
// Find user by reset token
|
|
199
|
+
const userDoc = await findUserByToken(token, 'reset');
|
|
200
|
+
if (!userDoc) {
|
|
201
|
+
return res.status(404).json({ ok: false, error: 'Invalid or expired token' });
|
|
202
|
+
}
|
|
203
|
+
// Check token expiry
|
|
204
|
+
if (userDoc.passwordResetTokenExpiresAt &&
|
|
205
|
+
isTokenExpired(userDoc.passwordResetTokenExpiresAt)) {
|
|
206
|
+
return res.status(400).json({ ok: false, error: 'Token has expired' });
|
|
207
|
+
}
|
|
208
|
+
// Update password in CouchDB
|
|
209
|
+
// CouchDB has an internal hook that automatically hashes the password
|
|
210
|
+
// when a 'password' field is present in the user document.
|
|
211
|
+
// see https://docs.couchdb.org/en/stable/intro/security.html#password-changing
|
|
212
|
+
// @ts-expect-error writing to metadata field here.
|
|
213
|
+
userDoc.password = newPassword; // Add plain text password field
|
|
214
|
+
// Clear reset token
|
|
215
|
+
userDoc.passwordResetToken = null;
|
|
216
|
+
userDoc.passwordResetTokenExpiresAt = null;
|
|
217
|
+
await updateUserDoc(userDoc);
|
|
218
|
+
logger.info(`Password reset completed for ${userDoc.name}`);
|
|
219
|
+
res.json({
|
|
220
|
+
ok: true,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
logger.error('Error resetting password:', error);
|
|
225
|
+
res.status(500).json({
|
|
226
|
+
ok: false,
|
|
227
|
+
error: 'Failed to reset password',
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
})();
|
|
231
|
+
});
|
|
232
|
+
export default router;
|
|
233
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"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"}
|