@@ -5,8 +5,8 @@ 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' ;
98import { Resource , Role } from '@app/graphql/generated/api/types.js' ;
9+ import { FastifyRequest } from '@app/types/fastify.js' ;
1010import { ApiKeyService } from '@app/unraid-api/auth/api-key.service.js' ;
1111import { AuthService } from '@app/unraid-api/auth/auth.service.js' ;
1212import { CookieService } from '@app/unraid-api/auth/cookie.service.js' ;
@@ -50,17 +50,13 @@ describe('AuthService', () => {
5050 } ;
5151
5252 // Mock FastifyRequest object for tests
53- const createMockRequest = ( overrides = { } ) : FastifyRequest => {
54- return {
55- headers : { } ,
56- query : { } ,
53+ const createMockRequest = ( overrides = { } ) =>
54+ ( {
55+ headers : { 'x-csrf-token' : undefined } ,
56+ query : { csrf_token : undefined } ,
5757 cookies : { } ,
58- id : 'test-id' ,
59- params : { } ,
60- raw : { } as any ,
6158 ...overrides ,
62- } as FastifyRequest ;
63- } ;
59+ } ) as FastifyRequest ;
6460
6561 beforeEach ( async ( ) => {
6662 const enforcer = await newEnforcer ( ) ;
@@ -82,7 +78,9 @@ describe('AuthService', () => {
8278 vi . spyOn ( authzService , 'getRolesForUser' ) . mockResolvedValue ( [ Role . ADMIN ] ) ;
8379 vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( true ) ;
8480
85- const mockRequest = createMockRequest ( ) ;
81+ const mockRequest = createMockRequest ( {
82+ headers : { 'x-csrf-token' : 'valid-token' } ,
83+ } ) ;
8684 const result = await authService . validateCookiesCasbin ( mockRequest ) ;
8785
8886 expect ( result ) . toEqual ( mockUser ) ;
@@ -92,7 +90,9 @@ describe('AuthService', () => {
9290 vi . spyOn ( cookieService , 'hasValidAuthCookie' ) . mockResolvedValue ( false ) ;
9391 vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( true ) ;
9492
95- const mockRequest = createMockRequest ( ) ;
93+ const mockRequest = createMockRequest ( {
94+ headers : { 'x-csrf-token' : 'valid-token' } ,
95+ } ) ;
9696 await expect ( authService . validateCookiesCasbin ( mockRequest ) ) . rejects . toThrow (
9797 UnauthorizedException
9898 ) ;
@@ -126,11 +126,27 @@ describe('AuthService', () => {
126126 it ( 'should throw UnauthorizedException when CSRF token is invalid' , async ( ) => {
127127 vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( false ) ;
128128
129- const mockRequest = createMockRequest ( ) ;
129+ const mockRequest = createMockRequest ( {
130+ headers : { 'x-csrf-token' : 'invalid-token' } ,
131+ } ) ;
130132 await expect ( authService . validateCookiesCasbin ( mockRequest ) ) . rejects . toThrow (
131133 new UnauthorizedException ( 'Invalid CSRF token' )
132134 ) ;
133135 } ) ;
136+
137+ it ( 'should accept CSRF token from query parameter' , async ( ) => {
138+ vi . spyOn ( cookieService , 'hasValidAuthCookie' ) . mockResolvedValue ( true ) ;
139+ vi . spyOn ( authService , 'getSessionUser' ) . mockResolvedValue ( mockUser ) ;
140+ vi . spyOn ( authzService , 'getRolesForUser' ) . mockResolvedValue ( [ Role . ADMIN ] ) ;
141+ vi . spyOn ( authService , 'validateCsrfToken' ) . mockReturnValue ( true ) ;
142+
143+ const mockRequest = createMockRequest ( {
144+ query : { csrf_token : 'valid-token' } ,
145+ } ) ;
146+ const result = await authService . validateCookiesCasbin ( mockRequest ) ;
147+
148+ expect ( result ) . toEqual ( mockUser ) ;
149+ } ) ;
134150 } ) ;
135151
136152 describe ( 'syncApiKeyRoles' , ( ) => {
0 commit comments