u
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
import env from '../../config/env.js';
|
||||
import { getSchemaVersion } from '../../db/store.js';
|
||||
|
||||
export function respondWithAuthenticatedUser(res, status, body) {
|
||||
return res.status(status).json({ ...body, googleClientId: env.googleClientId });
|
||||
export async function respondWithAuthenticatedUser(res, status, body) {
|
||||
let schemaVersion = null;
|
||||
try {
|
||||
schemaVersion = await getSchemaVersion();
|
||||
} catch {
|
||||
// ignore if database not accessible
|
||||
}
|
||||
return res.status(status).json({
|
||||
...body,
|
||||
googleClientId: env.googleClientId,
|
||||
schemaVersion,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export function clearCachedCompanyUsers(companyId) {
|
||||
}
|
||||
}
|
||||
|
||||
function respondWithAuthPayload(res, req, status, body) {
|
||||
async function respondWithAuthPayload(res, req, status, body) {
|
||||
if (req.path === '/api/auth/me') {
|
||||
return respondWithAuthenticatedUser(res, status, body);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ export const authMiddleware = async (req, res, next) => {
|
||||
const isDocs = req.path.startsWith('/docs') || req.path.startsWith('/api/docs');
|
||||
if (!token) {
|
||||
if (isDocs || isOAuthAuthorize) return next();
|
||||
return respondWithAuthPayload(res, req, 401, { error: 'Unauthorized' });
|
||||
return await respondWithAuthPayload(res, req, 401, { error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -94,7 +94,7 @@ export const authMiddleware = async (req, res, next) => {
|
||||
if (!Number.isInteger(authId) || authId <= 0) {
|
||||
if (req.cookies.token) clearTokenCookie(res);
|
||||
if (isDocs) return next();
|
||||
return respondWithAuthPayload(res, req, 401, { error: 'Invalid token' });
|
||||
return await respondWithAuthPayload(res, req, 401, { error: 'Invalid token' });
|
||||
}
|
||||
|
||||
let user = getCachedUser(authId);
|
||||
@@ -111,7 +111,7 @@ export const authMiddleware = async (req, res, next) => {
|
||||
clearCachedUser(authId);
|
||||
if (req.cookies.token) clearTokenCookie(res);
|
||||
if (isDocs) return next();
|
||||
return respondWithAuthPayload(res, req, 403, { error: 'User is no longer authorized' });
|
||||
return await respondWithAuthPayload(res, req, 403, { error: 'User is no longer authorized' });
|
||||
}
|
||||
|
||||
req.user = {
|
||||
@@ -133,7 +133,7 @@ export const authMiddleware = async (req, res, next) => {
|
||||
} catch {
|
||||
if (req.cookies.token) clearTokenCookie(res);
|
||||
if (isDocs || isOAuthAuthorize) return next();
|
||||
return respondWithAuthPayload(res, req, 401, { error: 'Invalid token' });
|
||||
return await respondWithAuthPayload(res, req, 401, { error: 'Invalid token' });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export function register(app, basePath = '') {
|
||||
* description: |
|
||||
* Returns the authenticated user from the session cookie and the Google client ID.
|
||||
* `user.picture` is the stored profile image as a base64 string when present.
|
||||
* Unauthenticated calls still receive `googleClientId` with 401.
|
||||
* Unauthenticated calls still receive `googleClientId` and `schemaVersion` with 401.
|
||||
* security:
|
||||
* - cookieAuth: []
|
||||
* x-markdown: auth/me.md
|
||||
@@ -33,8 +33,11 @@ export function register(app, basePath = '') {
|
||||
* $ref: '#/components/schemas/User'
|
||||
* googleClientId:
|
||||
* type: string
|
||||
* schemaVersion:
|
||||
* type: integer
|
||||
* description: Current database schema version
|
||||
* 401:
|
||||
* description: Unauthorized — still includes `googleClientId` for the frontend
|
||||
* description: Unauthorized — still includes `googleClientId` and `schemaVersion` for the frontend
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
@@ -44,12 +47,15 @@ export function register(app, basePath = '') {
|
||||
* type: string
|
||||
* googleClientId:
|
||||
* type: string
|
||||
* schemaVersion:
|
||||
* type: integer
|
||||
* description: Current database schema version
|
||||
*/
|
||||
app.get(`${basePath}/auth/me`, async (req, res) => {
|
||||
try {
|
||||
const row = await db.getById(req.user.id);
|
||||
if (!row) {
|
||||
return respondWithAuthenticatedUser(res, 403, { error: 'User is no longer authorized' });
|
||||
return await respondWithAuthenticatedUser(res, 403, { error: 'User is no longer authorized' });
|
||||
}
|
||||
|
||||
const pictureBinary = toPictureBuffer(row.pictureBinary);
|
||||
@@ -59,10 +65,10 @@ export function register(app, basePath = '') {
|
||||
selectedCompanyId: row.selectedCompanyId,
|
||||
...(pictureBinary && { picture: pictureBinary.toString('base64') }),
|
||||
};
|
||||
respondWithAuthenticatedUser(res, 200, { user });
|
||||
await respondWithAuthenticatedUser(res, 200, { user });
|
||||
} catch (error) {
|
||||
console.error('Get current user failed:', error);
|
||||
respondWithAuthenticatedUser(res, 500, { error: 'Failed to load user' });
|
||||
await respondWithAuthenticatedUser(res, 500, { error: 'Failed to load user' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ const schemaLog = createLogger('schema');
|
||||
let provider;
|
||||
let store;
|
||||
let connecting;
|
||||
let schemaVersion;
|
||||
|
||||
const STORE_NAMESPACES = [
|
||||
'companyuser',
|
||||
@@ -149,6 +150,7 @@ export async function getStore() {
|
||||
provider = createProvider();
|
||||
try {
|
||||
await provider.initialize((msg) => schemaLog.info(msg));
|
||||
schemaVersion = await provider.getSchemaVersion();
|
||||
} catch (err) {
|
||||
schemaLog.error('Database schema initialization failed:', err);
|
||||
throw err;
|
||||
@@ -168,6 +170,19 @@ export async function getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current database schema version.
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
export async function getSchemaVersion() {
|
||||
if (schemaVersion != null) {
|
||||
return schemaVersion;
|
||||
}
|
||||
const prov = await getProvider();
|
||||
schemaVersion = await prov.getSchemaVersion();
|
||||
return schemaVersion;
|
||||
}
|
||||
|
||||
export async function ensureConnection() {
|
||||
await getStore();
|
||||
}
|
||||
@@ -177,6 +192,7 @@ export async function closeStore() {
|
||||
await provider.close();
|
||||
provider = undefined;
|
||||
store = undefined;
|
||||
schemaVersion = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user