Skip to content

Commit

Permalink
Merge branch 'main' into N21-2285-update-media-activations-extension-1
Browse files Browse the repository at this point in the history
  • Loading branch information
sdinkov committed Jan 15, 2025
2 parents 0e5f439 + ace7342 commit afa3431
Show file tree
Hide file tree
Showing 689 changed files with 5,466 additions and 4,777 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { axiosErrorFactory } from '@shared/testing/factory';
import { axiosErrorFactory } from '@testing/factory/axios-error.factory';
import { AxiosError } from 'axios';
import { AxiosErrorLoggable } from './axios-error.loggable';

Expand Down
138 changes: 94 additions & 44 deletions apps/server/src/infra/auth-guard/decorator/jwt-auth.decorator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,49 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { ServerTestModule } from '@modules/server/server.module';
import { Controller, ExecutionContext, Get, INestApplication } from '@nestjs/common';
import { EntityManager } from '@mikro-orm/mongodb';
import { ServerTestModule } from '@modules/server';
import { Controller, Get, INestApplication } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import request from 'supertest';
import { JwtAuthGuard } from '../guard';
import { UserAndAccountTestFactory } from '@testing/factory/user-and-account.test.factory';
import { TestApiClient } from '@testing/test-api-client';
import { ICurrentUser } from '../interface';
import { CurrentUser, JWT, JwtAuthentication } from './jwt-auth.decorator';

const baseRouteName = '/test-decorator';
@JwtAuthentication()
@Controller('test_decorator_currentUser')
@Controller(baseRouteName)
export class TestDecoratorCurrentUserController {
@Get('test')
async test(@CurrentUser() currentUser: ICurrentUser): Promise<void> {
await Promise.resolve(currentUser);
@Get('currentUser')
test(@CurrentUser() currentUser: ICurrentUser): ICurrentUser {
return currentUser;
}
}

@JwtAuthentication()
@Controller('test_decorator_JWT')
@Controller(baseRouteName)
export class TestDecoratorJWTController {
@Get('test')
async test(@JWT() jwt: string): Promise<void> {
await Promise.resolve(jwt);
@Get('jwt')
test(@JWT() jwt: string): string {
return jwt;
}
}

describe('Jwt auth decorator', () => {
describe('Decorators', () => {
let app: INestApplication;
let currentUser: ICurrentUser;
let module: TestingModule;
let em: EntityManager;
let apiClient: TestApiClient;

beforeAll(async () => {
module = await Test.createTestingModule({
imports: [ServerTestModule],
controllers: [
TestDecoratorCurrentUserController,
TestDecoratorJWTController,
// TestDecoratorAuthenticateController,
],
})
.overrideGuard(JwtAuthGuard)
.useValue({
canActivate(context: ExecutionContext) {
const req: Request = context.switchToHttp().getRequest();
// @ts-expect-error Testcase
req.user = currentUser;
return true;
},
})
.compile();
controllers: [TestDecoratorCurrentUserController, TestDecoratorJWTController],
}).compile();

app = module.createNestApplication();
await app.init();

em = module.get(EntityManager);
apiClient = new TestApiClient(app, baseRouteName);
});

afterAll(async () => {
Expand All @@ -60,30 +52,88 @@ describe('Jwt auth decorator', () => {
});

describe('JwtAuthentication', () => {
it('should throw with UnauthorizedException if no jwt can be extracted from request context', async () => {
const response = await request(app.getHttpServer()).get('/test_decorator_JWT/test');
describe('when user is not logged in', () => {
it('should throw with UnauthorizedException', async () => {
const response = await apiClient.get('/jwt');

expect(response.statusCode).toEqual(401);
expect(response.statusCode).toEqual(401);
});
});

it('should succeed if it can get the jwt', async () => {
const jwt = 'example-jwt';
const response = await request(app.getHttpServer())
.get('/test_decorator_JWT/test')
.set('Authorization', `Bearer ${jwt}`);
describe('when user is logged in', () => {
const setup = async () => {
const { teacherAccount, teacherUser } = UserAndAccountTestFactory.buildTeacher();

await em.persistAndFlush([teacherAccount, teacherUser]);
em.clear();

const loggedInClient = await apiClient.login(teacherAccount);

return { loggedInClient, teacherUser };
};

it('should return status 200 for successful request.', async () => {
const { loggedInClient } = await setup();

expect(response.statusCode).toEqual(200);
const response = await loggedInClient.get('/jwt');

expect(response.statusCode).toEqual(200);
});

it('should return jwt token.', async () => {
const { loggedInClient } = await setup();

const response = await loggedInClient.get('/jwt');
// @ts-expect-error Testcase
expect(`Bearer ${response.text}`).toEqual(loggedInClient.authHeader);
});
});
});

describe('CurrentUser', () => {
it('should throw with UnauthorizedException if no jwt user data can be extracted from request context', async () => {
// @ts-expect-error Testcase
currentUser = undefined;
describe('when user is not logged in', () => {
it('should throw with UnauthorizedException', async () => {
const response = await apiClient.get('/currentUser');
expect(response.statusCode).toEqual(401);
});
});

describe('when user is logged in', () => {
const setup = async () => {
const { teacherAccount, teacherUser } = UserAndAccountTestFactory.buildTeacher();

await em.persistAndFlush([teacherAccount, teacherUser]);
em.clear();

const loggedInClient = await apiClient.login(teacherAccount);

const expectedCurrentUser = {
accountId: teacherAccount.id,
isExternalUser: teacherUser.externalId !== undefined,
roles: [teacherUser.roles[0].id],
schoolId: teacherUser.school.id,
support: false,
userId: teacherUser.id,
};

return { loggedInClient, expectedCurrentUser };
};

it('should return status 200 for successful request.', async () => {
const { loggedInClient } = await setup();

const response = await loggedInClient.get('/currentUser');

expect(response.statusCode).toEqual(200);
});

it('should return currentUser.', async () => {
const { loggedInClient, expectedCurrentUser } = await setup();

const response = await request(app.getHttpServer()).get('/test_decorator_currentUser/test');
const response = await loggedInClient.get('/currentUser');

expect(response.statusCode).toEqual(401);
expect(response.body).toEqual(expectedCurrentUser);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setupEntities } from '@shared/testing';
import { setupEntities } from '@testing/setup-entities';
import { ObjectId } from 'bson';
import { ICurrentUser } from '../interface';
import { CurrentUserBuilder } from './current-user.factory';
Expand Down
3 changes: 2 additions & 1 deletion apps/server/src/infra/auth-guard/mapper/jwt.factory.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { currentUserFactory, setupEntities } from '@shared/testing';
import { currentUserFactory } from '@testing/factory/currentuser.factory';
import { setupEntities } from '@testing/setup-entities';
import { ObjectId } from 'bson';
import { CreateJwtPayload } from '../interface';
import { JwtPayloadFactory } from './jwt.factory';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { jwtPayloadFactory } from '@shared/testing';
import { jwtPayloadFactory } from '@testing/factory/jwtpayload.factory';
import { JwtValidationAdapter } from '../adapter/jwt-validation.adapter';
import { JwtStrategy } from './jwt.strategy';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { WsException } from '@nestjs/websockets';
import { jwtPayloadFactory } from '@shared/testing';
import { jwtPayloadFactory } from '@testing/factory/jwtpayload.factory';
import { JwtValidationAdapter } from '../adapter';
import { WsJwtStrategy } from './ws-jwt.strategy';

Expand Down
18 changes: 9 additions & 9 deletions apps/server/src/infra/calendar/service/calendar.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Configuration } from '@hpi-schul-cloud/commons/lib';
import { CalendarEventDto, CalendarService } from '@infra/calendar';
import { HttpService } from '@nestjs/axios';
import { HttpStatus, InternalServerErrorException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { axiosResponseFactory } from '@shared/testing';
import { AxiosResponse } from 'axios';
import { of, throwError } from 'rxjs';
import { Logger } from '@src/core/logger';
import { EntityId } from '@shared/domain/types';
import {
DomainDeletionReportBuilder,
DomainName,
DomainOperationReportBuilder,
OperationType,
} from '@modules/deletion';
import { HttpService } from '@nestjs/axios';
import { HttpStatus, InternalServerErrorException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { EntityId } from '@shared/domain/types';
import { Logger } from '@src/core/logger';
import { axiosResponseFactory } from '@testing/factory/axios-response.factory';
import { AxiosResponse } from 'axios';
import { of, throwError } from 'rxjs';
import { CalendarEventId } from '../interface/calendar-event-id.interface';
import { CalendarEvent } from '../interface/calendar-event.interface';
import { CalendarMapper } from '../mapper/calendar.mapper';
import { CalendarEventId } from '../interface/calendar-event-id.interface';

describe('CalendarServiceSpec', () => {
let module: TestingModule;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { ObjectId } from '@mikro-orm/mongodb';
import { HttpService } from '@nestjs/axios';
import { NotFoundException, NotImplementedException, UnprocessableEntityException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { axiosResponseFactory } from '@shared/testing';
import { LegacyLogger } from '@src/core/logger';
import { axiosResponseFactory } from '@testing/factory/axios-response.factory';
import { AxiosResponse } from 'axios';
import { Observable, of } from 'rxjs';
import { NextcloudClient } from './nextcloud.client';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import { LtiToolDO } from '@shared/domain/domainobject/ltitool.do';
import { LtiPrivacyPermission, LtiRoleType, User } from '@shared/domain/entity';
import { RoleName } from '@shared/domain/interface';
import { LtiToolRepo } from '@shared/repo';
import { ltiToolDOFactory, pseudonymFactory, setupEntities, userDoFactory, userFactory } from '@shared/testing';
import { LegacyLogger } from '@src/core/logger';
import { ltiToolDOFactory, pseudonymFactory } from '@testing/factory/domainobject';
import { userDoFactory } from '@testing/factory/user.do.factory';
import { userFactory } from '@testing/factory/user.factory';
import { setupEntities } from '@testing/setup-entities';
import { TeamRolePermissionsDto } from '../../dto/team-role-permissions.dto';
import { NextcloudClient } from './nextcloud.client';
import { NextcloudStrategy } from './nextcloud.strategy';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MongoMemoryDatabaseModule } from '@infra/database';
import { MikroORM } from '@mikro-orm/core';
import { EntityManager, ObjectId } from '@mikro-orm/mongodb';
import { Test, TestingModule } from '@nestjs/testing';
import { createCollections } from '@shared/testing';
import { createCollections } from '@testing/create-collections';
import { DatabaseManagementService } from './database-management.service';

const randomChars = () => new ObjectId().toHexString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import AuthenticationFlowRepresentation from '@keycloak/keycloak-admin-client/li
import { EntityManager } from '@mikro-orm/mongodb';
import { ConfigModule } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { systemEntityFactory } from '@shared/testing/factory';
import { LoggerModule } from '@src/core/logger';
import { systemEntityFactory } from '@testing/factory/systemEntityFactory';
import { v1 } from 'uuid';
import { KeycloakAdministrationService } from '../../keycloak-administration/service/keycloak-administration.service';
import { KeycloakConfigurationModule } from '../keycloak-configuration.module';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import KeycloakAdminClient from '@keycloak/keycloak-admin-client';
import { EntityManager } from '@mikro-orm/mongodb';
import { ConfigModule } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { cleanupCollections } from '@shared/testing';
import { LoggerModule } from '@src/core/logger';
import { AccountEntity } from '@src/modules/account/domain/entity/account.entity';
import { accountFactory } from '@src/modules/account/testing';
import { cleanupCollections } from '@testing/cleanup-collections';
import { v1 } from 'uuid';
import { KeycloakAdministrationService } from '../../keycloak-administration/service/keycloak-administration.service';
import { KeycloakConfigurationModule } from '../keycloak-configuration.module';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { InternalServerErrorException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { setupEntities } from '@shared/testing';
import { Logger } from '@src/core/logger';
import { setupEntities } from '@testing/setup-entities';
import { ErrorMapper, FilesPreviewEvents, FilesPreviewExchange } from '../rabbitmq';
import { PreviewFileOptions } from './interface';
import { PreviewProducer } from './preview.producer';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { IsString } from 'class-validator';
import { IsOptional, IsString } from 'class-validator';

export class SchulconnexNameResponse {
@IsString()
familienname!: string;
public familienname!: string;

@IsString()
vorname!: string;
public vorname!: string;

@IsOptional()
@IsString()
public rufname?: string;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { OauthAdapterService, OAuthTokenDto } from '@modules/oauth';
import { HttpService } from '@nestjs/axios';
import { axiosResponseFactory } from '@shared/testing';
import { Logger } from '@src/core/logger';
import { axiosResponseFactory } from '@testing/factory/axios-response.factory';
import { of } from 'rxjs';
import { SchulconnexConfigurationMissingLoggable } from './loggable';
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const schulconnexResponseFactory = Factory.define<SchulconnexResponse>(()
person: {
name: {
vorname: 'Hans',
rufname: 'Hansi',
familienname: 'Peter',
},
geburt: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import { MediaSourceBasicAuthConfigNotFoundLoggableException } from '@modules/me
import { mediaSourceFactory } from '@modules/media-source/testing';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { axiosErrorFactory, axiosResponseFactory } from '@shared/testing';
import { AxiosErrorLoggable } from '@src/core/error/loggable';
import { axiosErrorFactory } from '@testing/factory/axios-error.factory';
import { axiosResponseFactory } from '@testing/factory/axios-response.factory';
import { AxiosResponse, RawAxiosRequestConfig } from 'axios';
import { vidisPageOfferFactory } from '../testing';
import { VidisFetchService } from './vidis-fetch.service';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { MongoMemoryDatabaseModule } from '@infra/database';
import { EntityManager } from '@mikro-orm/mongodb';
import { Test, TestingModule } from '@nestjs/testing';
import { SchoolEntity } from '@shared/domain/entity';
import { SystemProvisioningStrategy } from '@shared/domain/interface/system-provisioning.strategy';
import { SchoolFeature } from '@shared/domain/types';
import { cleanupCollections, schoolEntityFactory, systemEntityFactory } from '@shared/testing';
import { Logger } from '@src/core/logger';
import { MongoMemoryDatabaseModule } from '@src/infra/database';
import { SystemType } from '@src/modules/system';
import { cleanupCollections } from '@testing/cleanup-collections';
import { schoolEntityFactory } from '@testing/factory/school-entity.factory';
import { systemEntityFactory } from '@testing/factory/systemEntityFactory';
import { TspLegacyMigrationSystemMissingLoggable } from './loggable/tsp-legacy-migration-system-missing.loggable';
import { TspLegacyMigrationService } from './tsp-legacy-migration.service';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { UserService } from '@modules/user';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { UserSourceOptions } from '@shared/domain/domainobject/user-source-options.do';
import { userDoFactory } from '@shared/testing';
import { Logger } from '@src/core/logger';
import { accountDoFactory } from '@src/modules/account/testing';
import { userDoFactory } from '@testing/factory/user.do.factory';
import { TspSyncMigrationService } from './tsp-sync-migration.service';
import { TspSyncConfig } from './tsp-sync.config';

Expand Down
Loading

0 comments on commit afa3431

Please sign in to comment.