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

BC-7851 - Add tldraw-document delete api #14

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5b48a9a
Add tldraw-document controller
bischofmax Aug 30, 2024
447f00c
Add delete handling
bischofmax Sep 3, 2024
1e77f40
Encode delete message in yjs format
bischofmax Sep 4, 2024
bce795a
Simplify publish
bischofmax Sep 5, 2024
3da3208
Add service to controller
bischofmax Sep 5, 2024
fbcc394
Remove package save dev
bischofmax Sep 5, 2024
1368ee6
Add instance getter to stroage and redis service
bischofmax Sep 9, 2024
3f94e8d
Add api test
bischofmax Sep 13, 2024
0273430
Add tldraw document service test
bischofmax Sep 13, 2024
2912dd9
Rename storage service in document service
bischofmax Sep 13, 2024
9e7f4fa
Merge branch 'main' into BC-7851
bischofmax Sep 13, 2024
48bf7e2
Add redis service setup
bischofmax Sep 13, 2024
f3636c9
Fix test
bischofmax Sep 16, 2024
18d8ddb
Change delete message
bischofmax Sep 16, 2024
a665c88
remove commented out code
bischofmax Sep 16, 2024
7c4323e
Add global api prefix
bischofmax Sep 16, 2024
2a61d55
Remove hardcoded bucketname
bischofmax Sep 16, 2024
f0cb606
Merge branch 'main' into BC-7851
bischofmax Sep 17, 2024
75c111d
Publish delete message over redi pub
bischofmax Sep 18, 2024
87e5410
Merge branch 'BC-7851' of github.com:hpi-schul-cloud/tldraw-server in…
bischofmax Sep 18, 2024
1bb95e2
Add new y-redis form version to package json
bischofmax Sep 18, 2024
62f6e85
Merge remote-tracking branch 'origin/main' into BC-7851
SevenWaysDP Sep 19, 2024
47e8f8c
BC-7851 - move logic to y-redis
SevenWaysDP Sep 19, 2024
c2c57a1
Merge branch 'main' into BC-7851
Loki-Afro Sep 19, 2024
fad1da0
fix linter issues
SevenWaysDP Sep 19, 2024
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
13 changes: 13 additions & 0 deletions .env.default
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
REDIS=redis://172.18.0.5:6379
REDIS_PREFIX=y
API_HOST=http://localhost:3030
ADMIN_API__ALLOWED_API_KEYS=randomString

S3_ENDPOINT=localhost
S3_BUCKET=ydocs
S3_PORT=9000
S3_SSL=false
S3_ACCESS_KEY=miniouser
S3_SECRET_KEY=miniouser

WS_PORT="3345"
84 changes: 81 additions & 3 deletions package-lock.json

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

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand"
},
"dependencies": {
"@golevelup/ts-jest": "^0.5.4",
"@nestjs/common": "^10.4.1",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.4.1",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.4.1",
"@y/redis": "github:hpi-schul-cloud/y-redis#a5e141466a759a1d4b2876d5d5af52bc9ec4930d",
"@y/redis": "github:hpi-schul-cloud/y-redis#7d48e08d18ec78c9ab90063a7d867ec7f191319c",
"ioredis": "^5.4.1",
"passport": "^0.7.0",
"passport-headerapikey": "^1.2.2",
"prom-client": "^15.1.3",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
Expand All @@ -48,6 +52,8 @@
"@types/express": "^4.17.21",
"@types/jest": "^29.5.12",
"@types/node": "^20.3.1",
"@types/passport": "^1.0.16",
"@types/passport-strategy": "^0.2.38",
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
Expand Down
3 changes: 2 additions & 1 deletion src/apps/tldraw-server.app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { MetricsModule } from '../infra/metrics/metrics.module.js';
import { ServerModule } from '../modules/server/server.module.js';

async function bootstrap(): Promise<void> {
const httpPort = 3347;
const httpPort = 3349;
const nestApp = await NestFactory.create(ServerModule);
nestApp.setGlobalPrefix('api');
nestApp.enableCors();
await nestApp.init();

Expand Down
10 changes: 10 additions & 0 deletions src/infra/auth-guard/auth-guard.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { XApiKeyStrategy } from './strategy/index.js';

@Module({
imports: [PassportModule],
providers: [XApiKeyStrategy],
exports: [],
})
export class AuthGuardModule {}
1 change: 1 addition & 0 deletions src/infra/auth-guard/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './x-api-key.config.js';
3 changes: 3 additions & 0 deletions src/infra/auth-guard/config/x-api-key.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface XApiKeyConfig {
ADMIN_API__ALLOWED_API_KEYS: string[];
}
1 change: 1 addition & 0 deletions src/infra/auth-guard/guard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './x-api-key-auth.guard.js';
6 changes: 6 additions & 0 deletions src/infra/auth-guard/guard/x-api-key-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { StrategyType } from '../interface/index.js';

@Injectable()
export class ApiKeyGuard extends AuthGuard(StrategyType.API_KEY) {}
2 changes: 2 additions & 0 deletions src/infra/auth-guard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { AuthGuardModule } from './auth-guard.module.js';
export { ApiKeyGuard } from './guard/index.js';
1 change: 1 addition & 0 deletions src/infra/auth-guard/interface/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './strategy-type.js';
3 changes: 3 additions & 0 deletions src/infra/auth-guard/interface/strategy-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum StrategyType {
API_KEY = 'api-key',
}
1 change: 1 addition & 0 deletions src/infra/auth-guard/strategy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './x-api-key.strategy.js';
75 changes: 75 additions & 0 deletions src/infra/auth-guard/strategy/x-api-key.strategy.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { createMock } from '@golevelup/ts-jest';
import { UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { XApiKeyConfig } from '../config/x-api-key.config.js';
import { XApiKeyStrategy } from './x-api-key.strategy.js';

describe('XApiKeyStrategy', () => {
let module: TestingModule;
let strategy: XApiKeyStrategy;
let configService: ConfigService<XApiKeyConfig, true>;

beforeAll(async () => {
module = await Test.createTestingModule({
imports: [],
providers: [
XApiKeyStrategy,
{
provide: ConfigService,
useValue: createMock<ConfigService<XApiKeyConfig, true>>({
get: () => ['7ccd4e11-c6f6-48b0-81eb-cccf7922e7a4'],
}),
},
],
}).compile();

strategy = module.get(XApiKeyStrategy);
configService = module.get(ConfigService<XApiKeyConfig, true>);
});

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

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

describe('validate', () => {
const done = jest.fn(() => null);
describe('when a valid api key is provided', () => {
const setup = () => {
const CORRECT_API_KEY = '7ccd4e11-c6f6-48b0-81eb-cccf7922e7a4';

return { CORRECT_API_KEY, done };
};
it('should do nothing', () => {
const { CORRECT_API_KEY } = setup();
strategy.validate(CORRECT_API_KEY, done);
expect(done).toBeCalledWith(null, true);
});
});

describe('when a invalid api key is provided', () => {
const setup = () => {
const INVALID_API_KEY = '7ccd4e11-c6f6-48b0-81eb-cccf7922e7a4BAD';

return { INVALID_API_KEY, done };
};
it('should throw error', () => {
const { INVALID_API_KEY } = setup();
strategy.validate(INVALID_API_KEY, done);
expect(done).toBeCalledWith(new UnauthorizedException(), null);
});
});
});

describe('constructor', () => {
it('should create strategy', () => {
const ApiKeyStrategy = new XApiKeyStrategy(configService);
expect(ApiKeyStrategy).toBeDefined();
expect(ApiKeyStrategy).toBeInstanceOf(XApiKeyStrategy);
});
});
});
23 changes: 23 additions & 0 deletions src/infra/auth-guard/strategy/x-api-key.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-headerapikey/lib/Strategy.js';
import { XApiKeyConfig } from '../config/index.js';
import { StrategyType } from '../interface/index.js';

@Injectable()
export class XApiKeyStrategy extends PassportStrategy(Strategy, StrategyType.API_KEY) {
private readonly allowedApiKeys: string[];

public constructor(private readonly configService: ConfigService<XApiKeyConfig, true>) {
super({ header: 'X-API-KEY' }, false);
this.allowedApiKeys = this.configService.get<string[]>('ADMIN_API__ALLOWED_API_KEYS');
}

public validate(apiKey: string, done: (error: Error | null, data: boolean | null) => void): void {
if (this.allowedApiKeys.includes(apiKey)) {
done(null, true);
}
done(new UnauthorizedException(), null);
}
}
Loading
Loading