Skip to content

Commit

Permalink
Merge branch 'main' into N21-2188-show-external-tool-context-restiction
Browse files Browse the repository at this point in the history
  • Loading branch information
MBergCap committed Sep 29, 2024
2 parents a33ac08 + ef6e61d commit 62fcf84
Show file tree
Hide file tree
Showing 200 changed files with 4,643 additions and 853 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ There is also some old documentation in the server code /apps/server/doc/*.md.

Note that not all the .md file here are up to date.

## NestJS Console Applications

### Sync console
> Find the [Documentation](./apps/server/src/infra/sync/console/README.md) here.

## Feathers application

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,17 +517,6 @@ data:

# ========== Start of the CTL seed data configuration section.
echo "Inserting ctl seed data secrets to external-tools..."
mongosh $DATABASE__URL --quiet --eval 'db.getCollection("external-tools").updateOne(
{
"name": "Moodle Fortbildung",
},
{ $set: {
"config_secret": "'$CTL_SEED_SECRET_MOODLE_FORTB'",
} },
{
"upsert": true
}
);'
mongosh $DATABASE__URL --quiet --eval 'db.getCollection("external-tools").updateOne(
{
"name": "Product Test Onlinediagnose Grundschule - Mathematik",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { InterceptorConfig } from '@shared/common';
import { LoggerConfig } from '../logger';
import { LoggerConfig } from './logger';

export interface CoreModuleConfig extends InterceptorConfig, LoggerConfig {}
2 changes: 1 addition & 1 deletion apps/server/src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { CoreModule } from './core.module';
export { DomainErrorHandler } from './error';
export * from './interfaces';
export { CoreModuleConfig } from './core.config';
1 change: 0 additions & 1 deletion apps/server/src/core/interfaces/index.ts

This file was deleted.

1 change: 1 addition & 0 deletions apps/server/src/core/logger/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './logger';
export * from './error-logger';
export * from './types';
export * from './logging.utils';
export { LoggerConfig } from './logger.config';
1 change: 0 additions & 1 deletion apps/server/src/core/logger/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './logger-config';
export * from './legacy-logger.interface';
export * from './loggable';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface LoggerConfig {
NEST_LOG_LEVEL: string;
EXIT_ON_ERROR?: boolean;
EXIT_ON_ERROR: boolean;
}
2 changes: 1 addition & 1 deletion apps/server/src/core/logger/logger.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ConfigService } from '@nestjs/config';
import { utilities, WinstonModule } from 'nest-winston';
import winston from 'winston';
import { ErrorLogger } from './error-logger';
import { LoggerConfig } from './interfaces';
import { LoggerConfig } from './logger.config';
import { LegacyLogger } from './legacy-logger.service';
import { Logger } from './logger';

Expand Down
6 changes: 6 additions & 0 deletions apps/server/src/infra/auth-guard/auth-guard.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface AuthGuardConfig {
ADMIN_API__ALLOWED_API_KEYS: string[];
JWT_AUD: string;
JWT_LIFETIME: string;
AUTHENTICATION: string;
}
1 change: 1 addition & 0 deletions apps/server/src/infra/auth-guard/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { JwtValidationAdapter } from './adapter';
export { AuthGuardModule } from './auth-guard.module';
export { AuthGuardConfig } from './auth-guard.config';
export { XApiKeyConfig, authConfig } from './config';
export { CurrentUser, JWT, JwtAuthentication } from './decorator';
// JwtAuthGuard only exported because api tests still overried this guard.
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/infra/auth-guard/interface/jwt-payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export interface CreateJwtPayload {
schoolId: string;
roles: string[];
systemId?: string; // without this the user needs to change his PW during first login
support?: boolean;
// support UserId is missed see featherJS
support: boolean;
supportUserId?: string;
isExternalUser: boolean;
}

Expand Down
4 changes: 3 additions & 1 deletion apps/server/src/infra/auth-guard/interface/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export interface ICurrentUser {
systemId?: EntityId;

/** True if a support member impersonates the user */
impersonated: boolean;
support: boolean;

supportUserId?: EntityId;

/** True if the user is an external user e.g. an oauth user or ldap user */
isExternalUser: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupEntities } from '@shared/testing';
import { ObjectId } from 'bson';
import { CurrentUserBuilder } from './current-user.factory';
import { ICurrentUser } from '../interface';
import { CurrentUserBuilder } from './current-user.factory';

describe('CurrentUserBuilder', () => {
beforeAll(async () => {
Expand Down Expand Up @@ -35,7 +35,7 @@ describe('CurrentUserBuilder', () => {
schoolId: requiredProps.schoolId,
accountId: requiredProps.accountId,
roles: requiredProps.roles,
impersonated: false,
support: false,
isExternalUser: false,
systemId: undefined,
externalIdToken: undefined,
Expand All @@ -53,7 +53,7 @@ describe('CurrentUserBuilder', () => {
schoolId: requiredProps.schoolId,
accountId: requiredProps.accountId,
roles: requiredProps.roles,
impersonated: true,
support: true,
isExternalUser: false,
systemId: undefined,
externalIdToken: undefined,
Expand All @@ -72,7 +72,7 @@ describe('CurrentUserBuilder', () => {
schoolId: requiredProps.schoolId,
accountId: requiredProps.accountId,
roles: requiredProps.roles,
impersonated: false,
support: false,
isExternalUser: true,
systemId: undefined,
externalIdToken: undefined,
Expand All @@ -92,7 +92,7 @@ describe('CurrentUserBuilder', () => {
schoolId: requiredProps.schoolId,
accountId: requiredProps.accountId,
roles: requiredProps.roles,
impersonated: false,
support: false,
isExternalUser: false,
systemId,
externalIdToken: undefined,
Expand All @@ -112,7 +112,7 @@ describe('CurrentUserBuilder', () => {
schoolId: requiredProps.schoolId,
accountId: requiredProps.accountId,
roles: requiredProps.roles,
impersonated: false,
support: false,
isExternalUser: true,
systemId: undefined,
externalIdToken,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EntityId } from '@shared/domain/types';
import { TypeGuard } from '@shared/common';
import { EntityId } from '@shared/domain/types';
import { ICurrentUser } from '../interface';

interface RequiredCurrentUserProps {
Expand Down Expand Up @@ -30,7 +30,7 @@ export class CurrentUserBuilder {
schoolId: requiredProps.schoolId,
accountId: requiredProps.accountId,
roles: requiredProps.roles,
impersonated: false,
support: false,
isExternalUser: false,
systemId: undefined,
externalIdToken: undefined,
Expand All @@ -45,7 +45,7 @@ export class CurrentUserBuilder {

public asUserSupporter(asUserSupporter?: boolean) {
if (asUserSupporter === true) {
this.props.impersonated = asUserSupporter;
this.props.support = asUserSupporter;
}

return this;
Expand Down
22 changes: 22 additions & 0 deletions 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 { ObjectId } from 'bson';
import { CreateJwtPayload } from '../interface';
import { JwtPayloadFactory } from './jwt.factory';

Expand All @@ -19,6 +20,27 @@ describe('JwtPayloadFactory', () => {
roles: currentUser.roles,
schoolId: currentUser.schoolId,
userId: currentUser.userId,
support: false,
isExternalUser: false,
});
});
});

describe('buildFromSupportUser', () => {
it('should map current user to create jwt payload', () => {
const currentUser = currentUserFactory.build();
const supportUserId = new ObjectId().toHexString();

const createJwtPayload = JwtPayloadFactory.buildFromSupportUser(currentUser, supportUserId);

expect(createJwtPayload).toMatchObject<CreateJwtPayload>({
accountId: currentUser.accountId,
systemId: currentUser.systemId,
roles: currentUser.roles,
schoolId: currentUser.schoolId,
userId: currentUser.userId,
support: true,
supportUserId,
isExternalUser: false,
});
});
Expand Down
21 changes: 20 additions & 1 deletion apps/server/src/infra/auth-guard/mapper/jwt.factory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EntityId } from '@shared/domain/types';
import { CreateJwtPayload, ICurrentUser } from '../interface';

export class JwtPayloadFactory {
Expand All @@ -12,7 +13,25 @@ export class JwtPayloadFactory {
schoolId: currentUser.schoolId,
roles: currentUser.roles,
systemId: currentUser.systemId,
support: currentUser.impersonated,
support: false,
supportUserId: undefined,
isExternalUser: currentUser.isExternalUser,
};

const createJwtPayload = JwtPayloadFactory.build(data);

return createJwtPayload;
}

public static buildFromSupportUser(currentUser: ICurrentUser, supportUserId: EntityId): CreateJwtPayload {
const data = {
accountId: currentUser.accountId,
userId: currentUser.userId,
schoolId: currentUser.schoolId,
roles: currentUser.roles,
systemId: currentUser.systemId,
support: true,
supportUserId,
isExternalUser: currentUser.isExternalUser,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ describe('jwt strategy', () => {
schoolId: mockJwtPayload.schoolId,
accountId: mockJwtPayload.accountId,
systemId: mockJwtPayload.systemId,
impersonated: mockJwtPayload.support,
support: mockJwtPayload.support,
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('jwt strategy', () => {
schoolId: mockJwtPayload.schoolId,
accountId: mockJwtPayload.accountId,
systemId: mockJwtPayload.systemId,
impersonated: mockJwtPayload.support,
support: mockJwtPayload.support,
});
});
});
Expand Down
3 changes: 3 additions & 0 deletions apps/server/src/infra/calendar/calendar.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { LoggerConfig } from '@src/core/logger';

export interface CalendarConfig extends LoggerConfig {}
3 changes: 2 additions & 1 deletion apps/server/src/infra/calendar/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './calendar.module';
export { CalendarModule } from './calendar.module';
export * from './service/calendar.service';
export * from './dto/calendar-event.dto';
export { CalendarConfig } from './calendar.config';
22 changes: 22 additions & 0 deletions apps/server/src/infra/sync/console/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Sync console
This is a console application that allows you to start the synchronization process for different sources.

## Usage
To start the synchronization process, run the following command:
```bash
npm run nest:start:console sync run <target>
```

Where `<target>` is the name of the system you want to start the synchronization for. The currently available systems are:
- `tsp` - Synchronize Thüringer schulportal.

If the target is not provided, the synchronization will not start and the available targets will be displayed in an error message.
```bash
{
message: 'Either synchronization is not activated or the target entered is invalid',
data: { enteredTarget: 'tsp', availableTargets: { TSP: 'tsp' }}
}
```
## TSP synchronization
The TSP synchronization is controlled with a feature flag `FEATURE_TSP_SYNC_ENABLED`. This is now set to `false`.
40 changes: 40 additions & 0 deletions apps/server/src/infra/tsp-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# TSP API CLIENT

> A short introduction how this module can be used and the api client is generated.
## How to use the api client

The clients for the different Tsp endpoints should be created through TspClientFactory.
Through the create methods of the factory the basic configuration will be set. Currently the
factory sets the base url and generates the JWT used for the requests. You can use the client
like this:

```typescript
export class MyNewService {
// inject the factory into the constructor
constructor(private readonly tspClientFactory: TspClientFactory) {}

public async doSomeStuff(): Promise<void> {
// this will create a fully initialized client
const exportClient = tspClientFactory.createExportClient();

// calling the api
const versionResponse = await exportClient.version();


// do other stuff...
}
}
```

## How the code generation works

We are using the openapi-generator-cli to generate apis, models and supporting files in the
`generated` directory. **DO NOT** modify anything in the `generated` folder, because it will
be deleted on the next client generation.

The client generation is done with the npm command `npm run generate-client:tsp-api`. This
will delete the old and create new files. We are using the `tsp-api` generator configuration
from the `openapitools.json` found in the repository root. You can add new endpoints by
extending the `FILTER` list in the `openapiNormalizer` section with new `operationId` entries.
New models must be added to the list of `models` in the `globalProperty` section.
4 changes: 4 additions & 0 deletions apps/server/src/infra/tsp-client/generated/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
wwwroot/*.js
node_modules
typings
dist
1 change: 1 addition & 0 deletions apps/server/src/infra/tsp-client/generated/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.gitignore
.npmignore
.openapi-generator-ignore
api.ts
api/export-api.ts
base.ts
common.ts
configuration.ts
git_push.sh
index.ts
models/index.ts
models/robj-export-klasse.ts
models/robj-export-lehrer-migration.ts
models/robj-export-lehrer.ts
models/robj-export-schueler-migration.ts
models/robj-export-schueler.ts
models/robj-export-schule.ts
models/version-response.ts
Loading

0 comments on commit 62fcf84

Please sign in to comment.