CurrentUserIdProvider

mail@pastecode.io avatar
unknown
typescript
25 days ago
1.7 kB
2
Indexable
Never
import { AsyncLocalStorage } from 'async_hooks';
import { Uuid } from "@server/fd/fd-toolbox/types/uuid";
import { tryGetFromCoreCache, setCoreCache } from "@server/fd/fd-toolbox/caching/core-memory-cache";

const asyncLocalStorage = new AsyncLocalStorage<{ userId: Uuid }>();
const USER_CACHE_KEY = 'CurrentUserId';

export function getCurrentUserId(): Uuid {
    const store = asyncLocalStorage.getStore();
    if (store?.userId) {
        return store.userId;
    }

    const cachedUserId = tryGetFromCoreCache<Uuid>(USER_CACHE_KEY);
    if (cachedUserId) {
        return cachedUserId;
    }

    throw new Error('Current user ID is not set');
}

export function setCurrentUserId(userId: Uuid): void {
    asyncLocalStorage.enterWith({ userId });
    setCoreCache(USER_CACHE_KEY, userId);
}

export function resetCurrentUserId(): void {
    asyncLocalStorage.enterWith({ userId: null as unknown as Uuid });
    setCoreCache(USER_CACHE_KEY, null);
}

export function withUserId<T>(userId: Uuid, callback: () => T): T {
    return asyncLocalStorage.run({ userId }, callback);
}

export async function impersonateUser<T>(userId: Uuid, action: () => Promise<T>): Promise<T> {
    const originalUserId = getCurrentUserId();

    try {
        setCurrentUserId(userId);
        return await action();
    } finally {
        setCurrentUserId(originalUserId);
    }
}

//For instance, in your authentication middleware or login handler, you might have code similar to this:
import { setCurrentUserId } from '../services/currentUserIdProvider';

export function authMiddleware(req, res, next) {
    const userId = extractUserIdFromToken(req.headers.authorization);
    if (userId) {
        setCurrentUserId(userId);
    }
    next();
}

Leave a Comment