@@ -5,6 +5,7 @@ import { AuthZService } from 'nest-authz';
55import { afterEach , beforeEach , describe , expect , it , vi } from 'vitest' ;
66
77import type { ApiKey , ApiKeyWithSecret , UserAccount } from '@app/graphql/generated/api/types.js' ;
8+ import type { FastifyRequest } from '@app/types/fastify.js' ;
89import { Resource , Role } from '@app/graphql/generated/api/types.js' ;
910import { ApiKeyService } from '@app/unraid-api/auth/api-key.service.js' ;
1011import { AuthService } from '@app/unraid-api/auth/auth.service.js' ;
@@ -48,6 +49,19 @@ describe('AuthService', () => {
4849 roles : [ Role . GUEST , Role . CONNECT ] ,
4950 } ;
5051
52+ // Mock FastifyRequest object for tests
53+ const createMockRequest = ( overrides = { } ) : FastifyRequest => {
54+ return {
55+ headers : { } ,
56+ query : { } ,
57+ cookies : { } ,
58+ id : 'test-id' ,
59+ params : { } ,
60+ raw : { } as any ,
61+ ...overrides ,
62+ } as FastifyRequest ;
63+ } ;
64+
5165 beforeEach ( async ( ) => {
5266 const enforcer = await newEnforcer ( ) ;
5367
@@ -66,36 +80,57 @@ describe('AuthService', () => {
6680 vi . spyOn ( cookieService , 'hasValidAuthCookie' ) . mockResolvedValue ( true ) ;
6781 vi . spyOn ( authService , 'getSessionUser' ) . mockResolvedValue ( mockUser ) ;
6882 vi . spyOn ( authzService , 'getRolesForUser' ) . mockResolvedValue ( [ Role . ADMIN ] ) ;
83+ vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( true ) ;
6984
70- const result = await authService . validateCookiesCasbin ( { } ) ;
85+ const mockRequest = createMockRequest ( ) ;
86+ const result = await authService . validateCookiesCasbin ( mockRequest ) ;
7187
7288 expect ( result ) . toEqual ( mockUser ) ;
7389 } ) ;
7490
7591 it ( 'should throw UnauthorizedException when auth cookie is invalid' , async ( ) => {
7692 vi . spyOn ( cookieService , 'hasValidAuthCookie' ) . mockResolvedValue ( false ) ;
93+ vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( true ) ;
7794
78- await expect ( authService . validateCookiesCasbin ( { } ) ) . rejects . toThrow ( UnauthorizedException ) ;
95+ const mockRequest = createMockRequest ( ) ;
96+ await expect ( authService . validateCookiesCasbin ( mockRequest ) ) . rejects . toThrow (
97+ UnauthorizedException
98+ ) ;
7999 } ) ;
80100
81101 it ( 'should throw UnauthorizedException when session user is missing' , async ( ) => {
82102 vi . spyOn ( cookieService , 'hasValidAuthCookie' ) . mockResolvedValue ( true ) ;
83103 vi . spyOn ( authService , 'getSessionUser' ) . mockResolvedValue ( null as unknown as UserAccount ) ;
104+ vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( true ) ;
84105
85- await expect ( authService . validateCookiesCasbin ( { } ) ) . rejects . toThrow ( UnauthorizedException ) ;
106+ const mockRequest = createMockRequest ( ) ;
107+ await expect ( authService . validateCookiesCasbin ( mockRequest ) ) . rejects . toThrow (
108+ UnauthorizedException
109+ ) ;
86110 } ) ;
87111
88112 it ( 'should add guest role when user has no roles' , async ( ) => {
89113 vi . spyOn ( cookieService , 'hasValidAuthCookie' ) . mockResolvedValue ( true ) ;
90114 vi . spyOn ( authService , 'getSessionUser' ) . mockResolvedValue ( mockUser ) ;
91115 vi . spyOn ( authzService , 'getRolesForUser' ) . mockResolvedValue ( [ ] ) ;
116+ vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( true ) ;
92117
93118 const addRoleSpy = vi . spyOn ( authzService , 'addRoleForUser' ) ;
94- const result = await authService . validateCookiesCasbin ( { } ) ;
119+ const mockRequest = createMockRequest ( ) ;
120+ const result = await authService . validateCookiesCasbin ( mockRequest ) ;
95121
96122 expect ( result ) . toEqual ( mockUser ) ;
97123 expect ( addRoleSpy ) . toHaveBeenCalledWith ( mockUser . id , 'guest' ) ;
98124 } ) ;
125+
126+ it ( 'should throw UnauthorizedException when CSRF token is invalid' , async ( ) => {
127+ vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( false ) ;
128+
129+ const mockRequest = createMockRequest ( ) ;
130+ await expect ( authService . validateCookiesCasbin ( mockRequest ) ) . rejects . toThrow (
131+ new UnauthorizedException ( 'Invalid CSRF token' )
132+ ) ;
133+ } ) ;
99134 } ) ;
100135
101136 describe ( 'syncApiKeyRoles' , ( ) => {
0 commit comments