Skip to content

Commit

Permalink
BC-7902 - change logic of authorization (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
SevenWaysDP committed Sep 9, 2024
1 parent 3bd6e5a commit 6a7e1fc
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 53 deletions.
21 changes: 21 additions & 0 deletions jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
useESM: true,
},
],
},
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: 'src',
testRegex: '.*\\.spec\\.ts$',
collectCoverageFrom: ['**/*.(t|j)s'],
coverageDirectory: '../coverage',
testEnvironment: 'node',
};
42 changes: 20 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 4 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"start:worker:dev": "nest start worker --watch",
"start:worker:debug": "nest start worker --debug --watch",
"start:worker:prod": "node dist/apps/tldraw-worker.js",
"lint": "eslint \"src/**/*.ts\" --fix",
"lint": "eslint \"src/**/*.ts\" ",
"lint:fix": "eslint \"src/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
Expand All @@ -31,7 +32,7 @@
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.4.1",
"@nestjs/platform-express": "^10.4.1",
"@y/redis": "github:hpi-schul-cloud/y-redis#9933ff3abd948bff33c540f07b0671fe657ecd41",
"@y/redis": "github:hpi-schul-cloud/y-redis#a5e141466a759a1d4b2876d5d5af52bc9ec4930d",
"ioredis": "^5.4.1",
"prom-client": "^15.1.3",
"reflect-metadata": "^0.2.2",
Expand All @@ -40,6 +41,7 @@
"y-protocols": "^1.0.6"
},
"devDependencies": {
"@golevelup/ts-jest": "^0.5.5",
"@nestjs/cli": "^10.4.4",
"@nestjs/schematics": "^10.1.3",
"@nestjs/testing": "^10.4.1",
Expand All @@ -61,22 +63,5 @@
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.5.4"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
2 changes: 2 additions & 0 deletions src/infra/authorization/authorization.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Module } from '@nestjs/common';
import { LoggerModule } from '../logging/logger.module.js';
import { AuthorizationService } from './authorization.service.js';

@Module({
imports: [LoggerModule],
providers: [AuthorizationService],
exports: [AuthorizationService],
})
Expand Down
189 changes: 189 additions & 0 deletions src/infra/authorization/authorization.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { HttpRequest } from 'uws';
import { Logger } from '../logging/logger.js';
import { AuthorizationService } from './authorization.service.js';

describe(AuthorizationService.name, () => {
let module: TestingModule;
let service: AuthorizationService;
let configService: DeepMocked<ConfigService>;

beforeAll(async () => {
module = await Test.createTestingModule({
providers: [
AuthorizationService,
{
provide: ConfigService,
useValue: createMock<ConfigService>(),
},
{
provide: Logger,
useValue: createMock<Logger>(),
},
],
}).compile();

service = module.get<AuthorizationService>(AuthorizationService);
configService = module.get(ConfigService);
});

afterAll(async () => {
await module.close();
});

afterEach(() => {
jest.resetAllMocks();
});

const setupRequest = (roomId = 'roomId', cookies = 'other=ABC;jwt=eyJhbGciOiJIU') => {
const req: DeepMocked<HttpRequest> = createMock<HttpRequest>();
jest.spyOn(req, 'getParameter').mockReturnValue(roomId);
jest.spyOn(req, 'getHeader').mockReturnValue(cookies);
configService.getOrThrow.mockReturnValue('API_HOST');
const fetchSpy = jest.spyOn(global, 'fetch');

return { req, fetchSpy };
};

describe('hasPermission', () => {
describe('when the user request has permission', () => {
const setup = () => {
const { req, fetchSpy } = setupRequest();

fetchSpy.mockResolvedValue({
ok: true,
json: () => Promise.resolve({ isAuthorized: true, userId: '123' }),
} as any);

const expectedResult = { error: null, hasWriteAccess: true, room: 'roomId', userid: '123' };

return { req, expectedResult };
};

it('should return an expectedResult response payload', async () => {
const { req, expectedResult } = setup();

const response = await service.hasPermission(req);

expect(response).toEqual(expectedResult);
});
});

describe('when the user has no permission', () => {
const setup = () => {
const { req, fetchSpy } = setupRequest();

fetchSpy.mockResolvedValue({
ok: true,
json: () => Promise.resolve({ isAuthorized: false, userId: '123' }),
} as any);

const expectedResult = {
error: {
code: 4401,
reason: 'Unauthorized',
},
hasWriteAccess: false,
room: null,
userid: null,
};

return { req, expectedResult };
};

it('should return an expectedResult response payload', async () => {
const { req, expectedResult } = setup();

const response = await service.hasPermission(req);

expect(response).toEqual(expectedResult);
});
});

describe('when the roomId is not in request params', () => {
const setup = () => {
const { req } = setupRequest('');

const expectedResult = {
error: {
code: 4500,
reason: 'RoomId not found',
},
hasWriteAccess: false,
room: null,
userid: null,
};

return { req, expectedResult };
};

it('should return an expectedResult response payload', async () => {
const { req, expectedResult } = setup();

const response = await service.hasPermission(req);

expect(response).toEqual(expectedResult);
});
});

describe('when the jwtToken is not in request cookies', () => {
const setup = () => {
const { req } = setupRequest('roomId', 'other=ABC');
const expectedResult = {
error: {
code: 4500,
reason: 'JWT token not found',
},
hasWriteAccess: false,
room: null,
userid: null,
};

return { req, expectedResult };
};

it('should return an expectedResult response payload', async () => {
const { req, expectedResult } = setup();

const response = await service.hasPermission(req);

expect(response).toEqual(expectedResult);
});
});

describe('when the roomId not found on server', () => {
const setup = () => {
const { req, fetchSpy } = setupRequest();

fetchSpy.mockResolvedValue({
ok: false,
status: 404,
statusText: 'Not Found',
json: () => Promise.resolve({}),
} as any);

const expectedResult = {
error: {
code: 4404,
reason: 'Not Found',
},
hasWriteAccess: false,
room: null,
userid: null,
};

return { req, expectedResult };
};

it('should return an expectedResult response payload', async () => {
const { req, expectedResult } = setup();

const response = await service.hasPermission(req);

expect(response).toEqual(expectedResult);
});
});
});
});
Loading

0 comments on commit 6a7e1fc

Please sign in to comment.