Skip to content

Commit

Permalink
Merge branch 'main' into N21-1319-ctl-showing-tool-usage
Browse files Browse the repository at this point in the history
  • Loading branch information
mrikallab committed Nov 20, 2023
2 parents 9e29367 + 912f489 commit dab99dd
Show file tree
Hide file tree
Showing 20 changed files with 82 additions and 35 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ COPY scripts/ldapSync.sh /schulcloud-server/scripts/
RUN npm run build

ENV NODE_ENV=production
ENV NO_COLOR="true"
CMD npm run start
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ metadata:
labels:
app: preview-generator
data:
NEST_LOG_LEVEL: "info"
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RabbitPayload, RabbitRPC } from '@golevelup/nestjs-rabbitmq';
import { FilesPreviewEvents, FilesPreviewExchange } from '@infra/rabbitmq';
import { Injectable } from '@nestjs/common';
import { Logger } from '@src/core/logger';
import { FilesPreviewEvents, FilesPreviewExchange } from '@infra/rabbitmq';
import { PreviewFileOptions } from './interface';
import { PreviewActionsLoggable } from './loggable/preview-actions.loggable';
import { PreviewGeneratorService } from './preview-generator.service';
Expand All @@ -18,10 +18,12 @@ export class PreviewGeneratorConsumer {
queue: FilesPreviewEvents.GENERATE_PREVIEW,
})
public async generatePreview(@RabbitPayload() payload: PreviewFileOptions) {
this.logger.debug(new PreviewActionsLoggable('PreviewGeneratorConsumer.generatePreview', payload));
this.logger.info(new PreviewActionsLoggable('PreviewGeneratorConsumer.generatePreview:start', payload));

const response = await this.previewGeneratorService.generatePreview(payload);

this.logger.info(new PreviewActionsLoggable('PreviewGeneratorConsumer.generatePreview:end', payload));

return { message: response };
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { GetFile, S3ClientAdapter } from '@infra/s3-client';
import { Injectable } from '@nestjs/common';
import { Logger } from '@src/core/logger';
import { subClass } from 'gm';
import { PassThrough } from 'stream';
Expand All @@ -16,7 +16,7 @@ export class PreviewGeneratorService {
}

public async generatePreview(params: PreviewFileOptions): Promise<PreviewResponseMessage> {
this.logger.debug(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:start', params));
this.logger.info(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:start', params));
const { originFilePath, previewFilePath, previewOptions } = params;

const original = await this.downloadOriginFile(originFilePath);
Expand All @@ -26,7 +26,7 @@ export class PreviewGeneratorService {

await this.storageClient.create(previewFilePath, file);

this.logger.debug(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:end', params));
this.logger.info(new PreviewActionsLoggable('PreviewGeneratorService.generatePreview:end', params));

return {
previewFilePath,
Expand Down
7 changes: 4 additions & 3 deletions apps/server/src/infra/preview-generator/preview.producer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
import { FilesPreviewEvents, FilesPreviewExchange, RpcMessageProducer } from '@infra/rabbitmq';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { FilesPreviewEvents, FilesPreviewExchange, RpcMessageProducer } from '@infra/rabbitmq';
import { Logger } from '@src/core/logger';
import { PreviewFileOptions, PreviewResponseMessage } from './interface';
import { PreviewModuleConfig } from './interface/preview-consumer-config';
Expand All @@ -21,10 +21,11 @@ export class PreviewProducer extends RpcMessageProducer {
}

async generate(payload: PreviewFileOptions): Promise<PreviewResponseMessage> {
this.logger.debug(new PreviewActionsLoggable('PreviewProducer.generate:started', payload));
this.logger.info(new PreviewActionsLoggable('PreviewProducer.generate:started', payload));

const response = await this.request<PreviewResponseMessage>(FilesPreviewEvents.GENERATE_PREVIEW, payload);

this.logger.debug(new PreviewActionsLoggable('PreviewProducer.generate:finished', payload));
this.logger.info(new PreviewActionsLoggable('PreviewProducer.generate:finished', payload));

return response;
}
Expand Down
26 changes: 13 additions & 13 deletions apps/server/src/infra/s3-client/s3-client.adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class S3ClientAdapter {
// is public but only used internally
public async createBucket() {
try {
this.logger.log({ action: 'create bucket', params: { bucket: this.config.bucket } });
this.logger.debug({ action: 'create bucket', params: { bucket: this.config.bucket } });

const req = new CreateBucketCommand({ Bucket: this.config.bucket });
await this.client.send(req);
Expand All @@ -50,7 +50,7 @@ export class S3ClientAdapter {

public async get(path: string, bytesRange?: string): Promise<GetFile> {
try {
this.logger.log({ action: 'get', params: { path, bucket: this.config.bucket } });
this.logger.debug({ action: 'get', params: { path, bucket: this.config.bucket } });

const req = new GetObjectCommand({
Bucket: this.config.bucket,
Expand All @@ -73,8 +73,8 @@ export class S3ClientAdapter {
} catch (err) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (err?.Code === 'NoSuchKey') {
this.logger.log(`could not find one of the files for deletion with id ${path}`);
throw new NotFoundException('NoSuchKey');
this.logger.warn(`could not find one of the files for deletion with id ${path}`);
throw new NotFoundException('NoSuchKey', ErrorUtils.createHttpExceptionOptions(err));
} else {
throw new InternalServerErrorException('S3ClientAdapter:get', ErrorUtils.createHttpExceptionOptions(err));
}
Expand All @@ -83,7 +83,7 @@ export class S3ClientAdapter {

public async create(path: string, file: File): Promise<ServiceOutputTypes> {
try {
this.logger.log({ action: 'create', params: { path, bucket: this.config.bucket } });
this.logger.debug({ action: 'create', params: { path, bucket: this.config.bucket } });

const req = {
Body: file.data,
Expand Down Expand Up @@ -126,7 +126,7 @@ export class S3ClientAdapter {
} catch (err) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (err?.cause?.name === 'NoSuchKey') {
this.logger.log(`could not find one of the files for deletion with ids ${paths.join(',')}`);
this.logger.warn(`could not find one of the files for deletion with ids ${paths.join(',')}`);
return [];
}
throw new InternalServerErrorException('S3ClientAdapter:delete', ErrorUtils.createHttpExceptionOptions(err));
Expand All @@ -135,7 +135,7 @@ export class S3ClientAdapter {

public async restore(paths: string[]): Promise<CopyObjectCommandOutput[]> {
try {
this.logger.log({ action: 'restore', params: { paths, bucket: this.config.bucket } });
this.logger.debug({ action: 'restore', params: { paths, bucket: this.config.bucket } });

const copyPaths = paths.map((path) => {
return { sourcePath: `${this.deletedFolderName}/${path}`, targetPath: path };
Expand All @@ -156,7 +156,7 @@ export class S3ClientAdapter {

public async copy(paths: CopyFiles[]) {
try {
this.logger.log({ action: 'copy', params: { paths, bucket: this.config.bucket } });
this.logger.debug({ action: 'copy', params: { paths, bucket: this.config.bucket } });

const copyRequests = paths.map(async (path) => {
const req = new CopyObjectCommand({
Expand All @@ -180,7 +180,7 @@ export class S3ClientAdapter {

public async delete(paths: string[]) {
try {
this.logger.log({ action: 'delete', params: { paths, bucket: this.config.bucket } });
this.logger.debug({ action: 'delete', params: { paths, bucket: this.config.bucket } });

const pathObjects = paths.map((p) => {
return { Key: p };
Expand All @@ -200,7 +200,7 @@ export class S3ClientAdapter {

public async list(params: ListFiles): Promise<ObjectKeysRecursive> {
try {
this.logger.log({ action: 'list', params });
this.logger.debug({ action: 'list', params });

const result = await this.listObjectKeysRecursive(params);

Expand Down Expand Up @@ -242,7 +242,7 @@ export class S3ClientAdapter {

public async head(path: string): Promise<HeadObjectCommandOutput> {
try {
this.logger.log({ action: 'head', params: { path, bucket: this.config.bucket } });
this.logger.debug({ action: 'head', params: { path, bucket: this.config.bucket } });

const req = new HeadObjectCommand({
Bucket: this.config.bucket,
Expand All @@ -255,7 +255,7 @@ export class S3ClientAdapter {
} catch (err) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (err.message && err.message === 'NoSuchKey') {
this.logger.log(`could not find the file for head with id ${path}`);
this.logger.warn(`could not find the file for head with id ${path}`);
throw new NotFoundException(null, ErrorUtils.createHttpExceptionOptions(err, 'NoSuchKey'));
}
throw new InternalServerErrorException(null, ErrorUtils.createHttpExceptionOptions(err, 'S3ClientAdapter:head'));
Expand All @@ -264,7 +264,7 @@ export class S3ClientAdapter {

public async deleteDirectory(path: string) {
try {
this.logger.log({ action: 'deleteDirectory', params: { path, bucket: this.config.bucket } });
this.logger.debug({ action: 'deleteDirectory', params: { path, bucket: this.config.bucket } });

const req = new ListObjectsV2Command({
Bucket: this.config.bucket,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { Module } from '@nestjs/common';
import { PreviewGeneratorConsumerModule } from '@infra/preview-generator';
import { Module } from '@nestjs/common';
import { CoreModule } from '@src/core';
import { defaultConfig, s3Config } from './files-storage.config';

@Module({
imports: [PreviewGeneratorConsumerModule.register({ storageConfig: s3Config, serverConfig: defaultConfig })],
imports: [
PreviewGeneratorConsumerModule.register({ storageConfig: s3Config, serverConfig: defaultConfig }),
CoreModule,
],
})
export class PreviewGeneratorAMQPModule {}
3 changes: 3 additions & 0 deletions apps/server/src/modules/provisioning/dto/external-user.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ export class ExternalUserDto {

roles?: RoleName[];

birthday?: Date;

constructor(props: ExternalUserDto) {
this.externalId = props.externalId;
this.firstName = props.firstName;
this.lastName = props.lastName;
this.email = props.email;
this.roles = props.roles;
this.birthday = props.birthday;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -518,13 +518,15 @@ describe('OidcProvisioningService', () => {
const setupUser = () => {
const systemId = 'systemId';
const schoolId = 'schoolId';
const birthday = new Date('2023-11-17');
const existingUser: UserDO = userDoFactory.withRoles([{ id: 'existingRoleId', name: RoleName.USER }]).buildWithId(
{
firstName: 'existingFirstName',
lastName: 'existingLastName',
email: 'existingEmail',
schoolId: 'existingSchoolId',
externalId: 'externalUserId',
birthday: new Date('2023-11-16'),
},
'userId'
);
Expand All @@ -535,6 +537,7 @@ describe('OidcProvisioningService', () => {
email: 'email',
schoolId,
externalId: 'externalUserId',
birthday,
},
'userId'
);
Expand All @@ -544,6 +547,7 @@ describe('OidcProvisioningService', () => {
lastName: 'lastName',
email: 'email',
roles: [RoleName.USER],
birthday,
});
const userRole: RoleDto = new RoleDto({
id: 'roleId',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export class OidcProvisioningService {
user.email = externalUser.email ?? existingUser.email;
user.roles = roleRefs ?? existingUser.roles;
user.schoolId = schoolId ?? existingUser.schoolId;
user.birthday = externalUser.birthday ?? existingUser.birthday;
} else {
createNewAccount = true;

Expand All @@ -108,6 +109,7 @@ export class OidcProvisioningService {
email: externalUser.email ?? '',
roles: roleRefs ?? [],
schoolId,
birthday: externalUser.birthday,
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface SanisGeburtResponse {
datum?: string;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface SanisNameResponse {
familienname: string;
familienname?: string;

vorname: string;
vorname?: string;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { SanisGeburtResponse } from './sanis-geburt-response';
import { SanisNameResponse } from './sanis-name-response';

export interface SanisPersonResponse {
name: SanisNameResponse;
name?: SanisNameResponse;

geschlecht: string;
geburt?: SanisGeburtResponse;

lokalisierung: string;
geschlecht?: string;

vertrauensstufe: string;
lokalisierung?: string;

vertrauensstufe?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ describe('SanisResponseMapper', () => {
const setupSanisResponse = () => {
const externalUserId = 'aef1f4fd-c323-466e-962b-a84354c0e713';
const externalSchoolId = 'df66c8e6-cfac-40f7-b35b-0da5d8ee680e';

const sanisResponse: SanisResponse = {
pid: externalUserId,
person: {
name: {
vorname: 'firstName',
familienname: 'lastName',
},
geburt: {
datum: '2023-11-17',
},
geschlecht: 'x',
lokalisierung: 'de-de',
vertrauensstufe: '',
Expand Down Expand Up @@ -124,6 +128,7 @@ describe('SanisResponseMapper', () => {
firstName: 'firstName',
lastName: 'lastName',
roles: [RoleName.STUDENT],
birthday: new Date('2023-11-17'),
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ export class SanisResponseMapper {

mapToExternalUserDto(source: SanisResponse): ExternalUserDto {
const mapped = new ExternalUserDto({
firstName: source.person.name.vorname,
lastName: source.person.name.familienname,
firstName: source.person.name?.vorname,
lastName: source.person.name?.familienname,
roles: [this.mapSanisRoleToRoleName(source)],
externalId: source.pid,
birthday: source.person.geburt?.datum ? new Date(source.person.geburt?.datum) : undefined,
});

return mapped;
Expand Down
3 changes: 3 additions & 0 deletions apps/server/src/shared/domain/domainobject/user.do.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export class UserDO extends BaseDO {

previousExternalId?: string;

birthday?: Date;

constructor(domainObject: UserDO) {
super(domainObject.id);

Expand All @@ -64,5 +66,6 @@ export class UserDO extends BaseDO {
this.lastLoginSystemChange = domainObject.lastLoginSystemChange;
this.outdatedSince = domainObject.outdatedSince;
this.previousExternalId = domainObject.previousExternalId;
this.birthday = domainObject.birthday;
}
}
5 changes: 5 additions & 0 deletions apps/server/src/shared/domain/entity/user.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface IUserProperties {
lastLoginSystemChange?: Date;
outdatedSince?: Date;
previousExternalId?: string;
birthday?: Date;
}

@Entity({ tableName: 'users' })
Expand Down Expand Up @@ -96,6 +97,9 @@ export class User extends BaseEntityWithTimestamps implements IEntityWithSchool
@Property({ nullable: true })
outdatedSince?: Date;

@Property({ nullable: true })
birthday?: Date;

constructor(props: IUserProperties) {
super();
this.firstName = props.firstName;
Expand All @@ -112,6 +116,7 @@ export class User extends BaseEntityWithTimestamps implements IEntityWithSchool
this.lastLoginSystemChange = props.lastLoginSystemChange;
this.outdatedSince = props.outdatedSince;
this.previousExternalId = props.previousExternalId;
this.birthday = props.birthday;
}

public resolvePermissions(): string[] {
Expand Down
Loading

0 comments on commit dab99dd

Please sign in to comment.