refactor(CookieService): make cookie prefix & session directory injectable via Nest.js

This commit is contained in:
Pujit Mehrotra
2024-10-07 10:11:22 -04:00
parent 287aabfda7
commit 173da0e65b
2 changed files with 45 additions and 8 deletions

View File

@@ -3,10 +3,15 @@ import { AuthService } from './auth.service';
import { UsersModule } from '@app/unraid-api/users/users.module';
import { PassportModule } from '@nestjs/passport';
import { ServerHeaderStrategy } from '@app/unraid-api/auth/header.strategy';
import { CookieService } from './cookie.service';
import { CookieService, SESSION_COOKIE_OPTIONS } from './cookie.service';
@Module({
imports: [UsersModule, PassportModule],
providers: [AuthService, ServerHeaderStrategy, CookieService],
providers: [
AuthService,
ServerHeaderStrategy,
CookieService,
{ provide: SESSION_COOKIE_OPTIONS, useValue: CookieService.defaultOpts() },
],
})
export class AuthModule {}

View File

@@ -1,13 +1,33 @@
import { fileExists } from '@app/core/utils/files/file-exists';
import { batchProcess } from '@app/utils';
import { Injectable } from '@nestjs/common';
import { Injectable, Inject } from '@nestjs/common';
import { join } from 'path';
/** token for dependency injection of a session cookie options object */
export const SESSION_COOKIE_OPTIONS = 'SESSION_COOKIE_OPTIONS';
type SessionCookieOptions = {
namePrefix: string;
sessionDir: string;
};
@Injectable()
export class CookieService {
constructor(
@Inject(SESSION_COOKIE_OPTIONS) readonly opts: SessionCookieOptions = CookieService.defaultOpts()
) {}
/**
* @returns new SessionCookieOptions with `namePrefix: 'unraid_', sessionDir: '/var/lib/php'`
*/
static defaultOpts(): SessionCookieOptions {
return { namePrefix: 'unraid_', sessionDir: '/var/lib/php' };
}
/**
* Given a cookies object, returns true if any of the cookies are a valid unraid session cookie.
* @param cookies an object of cookie name => cookie value
* @param opts optional overrides for the session directory & prefix of the session cookie to look for
* @returns true if any of the cookies are a valid unraid session cookie, false otherwise
*/
async hasValidAuthCookie(cookies: object): Promise<boolean> {
@@ -17,20 +37,32 @@ export class CookieService {
return data.some((valid) => valid);
}
async isValidAuthCookie(cookieName: string, cookieValue: string): Promise<boolean> {
if (!cookieName.startsWith('unraid_')) {
/**
* Checks if a given details point to a valid unraid session cookie.
*
* A valid cookie is one where the name starts with the configured prefix
* and the value corresponds to an existing session file on disk.
*
* @param cookieName the name of the cookie to check
* @param cookieValue the value of the cookie to check
* @returns true if the cookie is valid, false otherwise
*/
private async isValidAuthCookie(cookieName: string, cookieValue: string): Promise<boolean> {
const { namePrefix } = this.opts;
if (!cookieName.startsWith(namePrefix)) {
return false;
}
return fileExists(this.makeSessionFilePath(cookieValue));
return fileExists(this.getSessionFilePath(cookieValue));
}
/**
* Given a session id, returns the full path to the session file on disk.
*
* @param sessionId the session id, as read from the session cookie.
* @param basePath path to the directory of session files.
* @returns the full path to the session file on disk.
*/
private makeSessionFilePath(sessionId: string): string {
return join('/var/lib/php', `sess_${sessionId}`);
public getSessionFilePath(sessionId: string): string {
return join(this.opts.sessionDir, `sess_${sessionId}`);
}
}