Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: mock CSRF meta elements in tests #870

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
global.fetch = jest.fn();

['_csrf_header', '_csrf'].forEach(csrfMeta => {
const meta = document.createElement('meta');
meta.setAttribute('name', csrfMeta);
meta.setAttribute('content', Math.floor(Math.random() * Date.now()).toString(36));
document.head.appendChild(meta);
});
6 changes: 5 additions & 1 deletion src/service/AuthService/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import fetchSpy, {
successResponse
} from '../../spec/fetchSpy';
import AuthService from '.';
import CsrfUtil from '@terrestris/base-util/dist/CsrfUtil/CsrfUtil';

describe('AuthService', () => {
let fetchMock: jest.SpyInstance;
Expand All @@ -28,9 +29,12 @@ describe('AuthService', () => {

await service.logout();

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/sso/logout', {
credentials: 'same-origin',
headers: {},
headers: {
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'POST'
});
});
Expand Down
7 changes: 5 additions & 2 deletions src/service/CacheService/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import fetchSpy, {
successResponse
} from '../../spec/fetchSpy';
import CacheService from '.';
import CsrfUtil from '@terrestris/base-util/dist/CsrfUtil/CsrfUtil';

describe('AppInfoService', () => {
let fetchMock: jest.SpyInstance;
Expand All @@ -27,9 +28,11 @@ describe('AppInfoService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.evictCache();

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/cache/evict', {
headers: {},
headers: {
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'POST'
});
});
Expand Down
19 changes: 11 additions & 8 deletions src/service/GenericEntityService/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import BaseEntity, { BaseEntityArgs } from '../../model/BaseEntity';
import fetchSpy, { failureResponse, successResponse } from '../../spec/fetchSpy';
import GenericService, { GenericEntityServiceOpts } from '.';
import CsrfUtil from '@terrestris/base-util/dist/CsrfUtil/CsrfUtil';

interface DummyEntityArgs extends BaseEntityArgs {
dummyField?: string;
Expand Down Expand Up @@ -204,11 +205,12 @@ describe('GenericService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.add({ dummyField: 'dummyValue' });

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/dummy', {
body: '{\"dummyField\":\"dummyValue\"}',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'POST'
});
Expand Down Expand Up @@ -236,7 +238,7 @@ describe('GenericService', () => {
fetchMock = fetchSpy(successResponse([]));

const resp = await service.delete(1);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/dummy/1', {
headers: {},
method: 'DELETE'
Expand All @@ -259,11 +261,12 @@ describe('GenericService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.update({ id: 1, dummyField: 'dummyValue' });

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/dummy/1', {
body: '{\"id\":1,\"dummyField\":\"dummyValue\"}',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'PUT'
});
Expand Down Expand Up @@ -291,11 +294,12 @@ describe('GenericService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.updatePartial({ id: 1, dummyField: 'dummyValue' });

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/dummy/1', {
body: '{\"id\":1,\"dummyField\":\"dummyValue\"}',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'PATCH'
});
Expand Down Expand Up @@ -367,6 +371,5 @@ describe('GenericService', () => {
await expect(service.setPublic(1)).rejects.toThrow();
});


});
});
13 changes: 10 additions & 3 deletions src/service/GenericFileService/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import BaseEntity, { BaseEntityArgs } from '../../model/BaseEntity';
import fetchSpy, { failureResponse, successResponse } from '../../spec/fetchSpy';
import GenericFileService, { GenericFileServiceOpts } from '.';
import CsrfUtil from '@terrestris/base-util/dist/CsrfUtil/CsrfUtil';

interface DummyEntityArgs extends BaseEntityArgs {
dummyField?: string;
Expand Down Expand Up @@ -114,10 +115,12 @@ describe('GenericFileService', () => {

const body = new FormData();
body.append('file', file);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/dummy/upload', {
body: body,
headers: {},
headers: {
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'POST'
});
});
Expand All @@ -131,9 +134,12 @@ describe('GenericFileService', () => {
const body = new FormData();
body.append('file', file);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/dummy/uploadToFileSystem', {
body: body,
headers: {},
headers: {
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'POST'
});
});
Expand Down Expand Up @@ -161,6 +167,7 @@ describe('GenericFileService', () => {

await service.delete('db5f69fa-e8f6-42a6-a305-d2555d7d4d08');

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/dummy/db5f69fa-e8f6-42a6-a305-d2555d7d4d08', {
headers: {},
method: 'DELETE'
Expand Down
4 changes: 2 additions & 2 deletions src/service/ImageFileService/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ImageFile from '../../model/ImageFile';
import { getCsrfTokenHeader } from '../../security/getCsrfTokenHeader';
import { getBearerTokenHeader } from '../../security/getBearerTokenHeader';
import GenericFileService, { GenericFileServiceOpts } from '../GenericFileService';

export class ImageFileService<T extends ImageFile> extends GenericFileService<T> {
Expand All @@ -15,7 +15,7 @@ export class ImageFileService<T extends ImageFile> extends GenericFileService<T>
const response = await fetch(`${this.basePath}/${fileUuid}/thumbnail`, {
method: 'GET',
headers: {
...getCsrfTokenHeader()
...getBearerTokenHeader(this.keycloak),
},
...fetchOpts
});
Expand Down
54 changes: 36 additions & 18 deletions src/service/PermissionService/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import fetchSpy, {
successResponse
} from '../../spec/fetchSpy';
import PermissionService from '.';
import CsrfUtil from '@terrestris/base-util/dist/CsrfUtil/CsrfUtil';

describe('PermissionService', () => {
let fetchMock: jest.SpyInstance;
Expand Down Expand Up @@ -482,10 +483,12 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.setUserInstancePermission(1909, 10, 'ADMIN');
const csrfHeaderValue = CsrfUtil.getCsrfValue();

expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/instance/user/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue,
'Content-Type': 'application/json'
},
body: '{\"permission\":\"ADMIN\"}',
Expand All @@ -511,11 +514,12 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.setGroupInstancePermission(1909, 10, 'ADMIN');

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/instance/group/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'X-XSRF-TOKEN': csrfHeaderValue
},
body: '{\"permission\":\"ADMIN\"}',
method: 'POST'
Expand All @@ -540,11 +544,12 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.setUserClassPermission(1909, 10, 'ADMIN');

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/class/user/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'X-XSRF-TOKEN': csrfHeaderValue
},
body: '{\"permission\":\"ADMIN\"}',
method: 'POST'
Expand All @@ -569,11 +574,12 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.setGroupClassPermission(1909, 10, 'ADMIN');

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/class/group/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'X-XSRF-TOKEN': csrfHeaderValue
},
body: '{\"permission\":\"ADMIN\"}',
method: 'POST'
Expand All @@ -599,9 +605,11 @@ describe('PermissionService', () => {

await service.deleteUserInstancePermission(1909, 10);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/instance/user/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand All @@ -626,9 +634,11 @@ describe('PermissionService', () => {

await service.deleteGroupInstancePermission(1909, 10);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/instance/group/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand All @@ -652,10 +662,11 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.deleteUserClassPermission(1909, 10);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/class/user/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand All @@ -680,9 +691,11 @@ describe('PermissionService', () => {

await service.deleteGroupClassPermission(1909, 10);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/class/group/10', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand All @@ -706,10 +719,11 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.deleteUserInstancePermissions(1909);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/instance/user', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand All @@ -733,10 +747,11 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.deleteGroupInstancePermissions(1909);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/instance/group', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand All @@ -760,10 +775,11 @@ describe('PermissionService', () => {
fetchMock = fetchSpy(successResponse([]));

await service.deleteUserClassPermissions(1909);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/class/user', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand All @@ -788,9 +804,11 @@ describe('PermissionService', () => {

await service.deleteGroupClassPermissions(1909);

const csrfHeaderValue = CsrfUtil.getCsrfValue();
expect(fetchMock).toHaveBeenCalledWith('/1909/permissions/class/group', {
headers: {
Authorization: 'Bearer ThisIsNotAValidBearerToken'
Authorization: 'Bearer ThisIsNotAValidBearerToken',
'X-XSRF-TOKEN': csrfHeaderValue
},
method: 'DELETE'
});
Expand Down
Loading