This commit is contained in:
Bastian Wagner
2024-10-25 12:32:26 +02:00
parent d4f1fbbf39
commit b4e264eda9
40 changed files with 538 additions and 66 deletions

77
api/package-lock.json generated
View File

@@ -10,13 +10,16 @@
"license": "UNLICENSED",
"dependencies": {
"@nestjs/axios": "^3.0.3",
"@nestjs/cache-manager": "^2.3.0",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "^2.0.5",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/typeorm": "^10.0.2",
"axios": "^1.7.7",
"cache-manager": "^5.7.6",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"mysql2": "^3.11.2",
@@ -1583,6 +1586,18 @@
"rxjs": "^6.0.0 || ^7.0.0"
}
},
"node_modules/@nestjs/cache-manager": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-2.3.0.tgz",
"integrity": "sha512-pxeBp9w/s99HaW2+pezM1P3fLiWmUEnTUoUMLa9UYViCtjj0E0A19W/vaT5JFACCzFIeNrwH4/16jkpAhQ25Vw==",
"license": "MIT",
"peerDependencies": {
"@nestjs/common": "^9.0.0 || ^10.0.0",
"@nestjs/core": "^9.0.0 || ^10.0.0",
"cache-manager": "<=5",
"rxjs": "^7.0.0"
}
},
"node_modules/@nestjs/cli": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.5.tgz",
@@ -1732,6 +1747,26 @@
"@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0"
}
},
"node_modules/@nestjs/mapped-types": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz",
"integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==",
"license": "MIT",
"peerDependencies": {
"@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
"class-transformer": "^0.4.0 || ^0.5.0",
"class-validator": "^0.13.0 || ^0.14.0",
"reflect-metadata": "^0.1.12 || ^0.2.0"
},
"peerDependenciesMeta": {
"class-transformer": {
"optional": true
},
"class-validator": {
"optional": true
}
}
},
"node_modules/@nestjs/platform-express": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.1.tgz",
@@ -3159,6 +3194,27 @@
"node": ">= 0.8"
}
},
"node_modules/cache-manager": {
"version": "5.7.6",
"resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.7.6.tgz",
"integrity": "sha512-wBxnBHjDxF1RXpHCBD6HGvKER003Ts7IIm0CHpggliHzN1RZditb7rXoduE1rplc2DEFYKxhLKgFuchXMJje9w==",
"license": "MIT",
"dependencies": {
"eventemitter3": "^5.0.1",
"lodash.clonedeep": "^4.5.0",
"lru-cache": "^10.2.2",
"promise-coalesce": "^1.1.2"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/cache-manager/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
@@ -4288,6 +4344,12 @@
"node": ">= 0.6"
}
},
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
"license": "MIT"
},
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
@@ -6365,6 +6427,12 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
"license": "MIT"
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -7262,6 +7330,15 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/promise-coalesce": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/promise-coalesce/-/promise-coalesce-1.1.2.tgz",
"integrity": "sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=16"
}
},
"node_modules/prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",

View File

@@ -21,13 +21,16 @@
},
"dependencies": {
"@nestjs/axios": "^3.0.3",
"@nestjs/cache-manager": "^2.3.0",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "^2.0.5",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/typeorm": "^10.0.2",
"axios": "^1.7.7",
"cache-manager": "^5.7.6",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"mysql2": "^3.11.2",

View File

@@ -10,6 +10,9 @@ import { RoleModule } from './modules/role/role.module';
import { KeyModule } from './modules/key/key.module';
import { CustomerModule } from './modules/customer/customer.module';
import { CylinderModule } from './modules/cylinder/cylinder.module';
import { SystemModule } from './modules/system/system.module';
import { CacheInterceptor, CacheModule } from '@nestjs/cache-manager';
import { APP_INTERCEPTOR } from '@nestjs/core';
@Module({
imports: [
@@ -17,6 +20,7 @@ import { CylinderModule } from './modules/cylinder/cylinder.module';
envFilePath: ['.env'],
isGlobal: true,
}),
CacheModule.register({ ttl: 5000, isGlobal: true }),
DatabaseModule,
AuthModule,
UserModule,
@@ -24,8 +28,16 @@ import { CylinderModule } from './modules/cylinder/cylinder.module';
KeyModule,
CustomerModule,
CylinderModule,
SystemModule,
],
controllers: [AppController],
providers: [AppService, AuthGuard],
providers: [
AppService,
AuthGuard,
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}

View File

@@ -1,4 +1,3 @@
export * from './login.dto';
export * from './auth-code.dto';
export * from './create-key-system.dto';
export * from './handover-key.dto';

View File

@@ -1,4 +1,14 @@
import { Controller, Delete, Get, Param, Req, UseGuards } from '@nestjs/common';
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
Req,
UseGuards,
} from '@nestjs/common';
import { AuthGuard } from 'src/core/guards/auth.guard';
import { CylinderService } from './cylinder.service';
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
@@ -15,7 +25,23 @@ export class CylinderController {
}
@Delete(':id')
deleteKey(@Req() req: AuthenticatedRequest, @Param() id: string) {
return this.service.deleteKey(req.user, id);
deleteKey(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
return this.service.deleteCylinder(req.user, id);
}
@Put()
updateCylinder(
@Req() req: AuthenticatedRequest,
@Body() b: Partial<Cylinder>,
) {
return this.service.updateCylinder(req.user, b);
}
@Post()
createCylinder(
@Req() req: AuthenticatedRequest,
@Body() b: Partial<Cylinder>,
) {
return this.service.createCylinder(req.user, b);
}
}

View File

@@ -19,12 +19,28 @@ export class CylinderService {
return c;
}
async deleteKey(user: User, id: string) {
async deleteCylinder(user: User, cylinderid: string) {
const cylinder = await this.cylinderRepo.findOneOrFail({
where: { id: id, system: { managers: { id: user.id } } },
where: { id: cylinderid, system: { managers: { id: user.id } } },
relations: ['keys'],
});
await this.keyRepo.softRemove(cylinder.keys);
return this.cylinderRepo.softRemove(cylinder);
}
async updateCylinder(user: User, cylinder: Partial<Cylinder>) {
const original = await this.cylinderRepo.findOneOrFail({
where: { id: cylinder.id, system: { managers: { id: user.id } } },
relations: ['keys', 'system'],
});
Object.keys(cylinder).forEach((k: string) => {
original[k] = cylinder[k];
});
return this.cylinderRepo.save(original);
}
createCylinder(user: User, cylinder: Partial<Cylinder>) {
return this.cylinderRepo.save(this.cylinderRepo.create(cylinder));
}
}

View File

@@ -13,7 +13,6 @@ import { KeyService } from './key.service';
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
import { AuthGuard } from 'src/core/guards/auth.guard';
import { Key } from 'src/model/entitites';
import { CreateKeySystemDto } from 'src/model/dto/create-key-system.dto';
@UseGuards(AuthGuard)
@Controller('key')
@@ -45,14 +44,6 @@ export class KeyController {
return this.service.deleteKey(req.user, id);
}
@Post('system')
createKeySystem(
@Req() req: AuthenticatedRequest,
@Body() body: CreateKeySystemDto,
) {
return this.service.createKeySystem(req.user, body);
}
@Post(':id/handover')
handoutKey(
@Req() req: AuthenticatedRequest,

View File

@@ -1,5 +1,4 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateKeySystemDto } from 'src/model/dto';
import { Cylinder, Key, User } from 'src/model/entitites';
import { IUser } from 'src/model/interface';
import {
@@ -68,17 +67,6 @@ export class KeyService {
});
}
async createKeySystem(user: User, systemDTO: CreateKeySystemDto) {
const sys = this.systemRepo.create(systemDTO);
sys.managers = [user];
try {
const res = await this.systemRepo.save(sys);
return res;
} catch (e) {
throw new HttpException(e.code, HttpStatus.UNPROCESSABLE_ENTITY);
}
}
async handoverKey(user: IUser, data: any, keyID: string) {
const key: Key = await this.keyrepository.findOneOrFail({
where: { id: keyID, cylinder: { system: { managers: { id: user.id } } } },

View File

@@ -1,6 +1,6 @@
import { IsNotEmpty, MaxLength, MinLength } from 'class-validator';
export class CreateKeySystemDto {
export class CreateSystemDto {
@IsNotEmpty()
@MinLength(2)
@MaxLength(255)

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateSystemDto } from './create-system.dto';
export class UpdateSystemDto extends PartialType(CreateSystemDto) {}

View File

@@ -0,0 +1,50 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
Req,
UseGuards,
} from '@nestjs/common';
import { SystemService } from './system.service';
import { CreateSystemDto } from './dto/create-system.dto';
import { UpdateSystemDto } from './dto/update-system.dto';
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
import { AuthGuard } from 'src/core/guards/auth.guard';
@UseGuards(AuthGuard)
@Controller('system')
export class SystemController {
constructor(private readonly systemService: SystemService) {}
@Post()
create(
@Req() req: AuthenticatedRequest,
@Body() createSystemDto: CreateSystemDto,
) {
return this.systemService.create(req.user, createSystemDto);
}
@Get()
findAll(@Req() req: AuthenticatedRequest) {
return this.systemService.findAll(req.user);
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.systemService.findOne(id);
}
@Patch(':id')
update(@Param('id') id: string, @Body() updateSystemDto: UpdateSystemDto) {
return this.systemService.update(id, updateSystemDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.systemService.remove(id);
}
}

View File

@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { SystemService } from './system.service';
import { SystemController } from './system.controller';
import { AuthModule } from '../auth/auth.module';
import { DatabaseModule } from 'src/shared/database/database.module';
@Module({
controllers: [SystemController],
providers: [SystemService],
imports: [AuthModule, DatabaseModule],
})
export class SystemModule {}

View File

@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { SystemService } from './system.service';
describe('SystemService', () => {
let service: SystemService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [SystemService],
}).compile();
service = module.get<SystemService>(SystemService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@@ -0,0 +1,42 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSystemDto } from './dto/create-system.dto';
import { UpdateSystemDto } from './dto/update-system.dto';
import { KeySystemRepository } from 'src/model/repositories';
import { User } from 'src/model/entitites';
@Injectable()
export class SystemService {
constructor(private systemRepo: KeySystemRepository) {}
async create(user: User, createSystemDto: CreateSystemDto) {
const sys = this.systemRepo.create(createSystemDto);
sys.managers = [user];
try {
const res = await this.systemRepo.save(sys);
return res;
} catch (e) {
throw new HttpException(e.code, HttpStatus.UNPROCESSABLE_ENTITY);
}
}
findAll(user: User) {
return this.systemRepo.find({
where: { managers: { id: user.id } },
order: { name: { direction: 'ASC' } },
});
}
findOne(id: string) {
return `This action returns a #${id} system`;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(id: string, updateSystemDto: UpdateSystemDto) {
return `This action updates a #${id} system`;
}
async remove(id: string) {
const system = await this.systemRepo.findOne({ where: { id } });
return this.systemRepo.softRemove(system);
}
}