Skip to content

Commit e13b4e0

Browse files
More work
1 parent 20dd95d commit e13b4e0

File tree

15 files changed

+3771
-2891
lines changed

15 files changed

+3771
-2891
lines changed

package-lock.json

Lines changed: 3632 additions & 2748 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,99 +30,92 @@
3030
},
3131
"dependencies": {
3232
"@chirpstack/chirpstack-api": "4.6.0",
33-
"@grpc/grpc-js": "^1.9.13",
34-
"@nestjs/axios": "^3.0.2",
35-
"@nestjs/common": "^9.1.2",
36-
"@nestjs/config": "^2.2.0",
37-
"@nestjs/core": "^9.4.3",
38-
"@nestjs/jwt": "^9.0.0",
39-
"@nestjs/mapped-types": "^1.2.2",
40-
"@nestjs/passport": "^9.0.0",
41-
"@nestjs/platform-express": "^9.1.2",
42-
"@nestjs/schedule": "^2.1.0",
43-
"@nestjs/swagger": "^6.1.2",
44-
"@nestjs/typeorm": "^9.0.1",
33+
"@grpc/grpc-js": "^1.14.0",
34+
"@nestjs/axios": "^4.0.1",
35+
"@nestjs/cache-manager": "^3.0.1",
36+
"@nestjs/common": "^11.1.6",
37+
"@nestjs/config": "^4.0.2",
38+
"@nestjs/core": "^11.1.6",
39+
"@nestjs/jwt": "^11.0.0",
40+
"@nestjs/mapped-types": "^2.1.0",
41+
"@nestjs/passport": "^11.0.5",
42+
"@nestjs/platform-express": "^11.1.6",
43+
"@nestjs/schedule": "^6.0.1",
44+
"@nestjs/swagger": "^11.2.0",
45+
"@nestjs/typeorm": "^11.0.0",
46+
"@node-saml/passport-saml": "^5.1.0",
4547
"@types/bcryptjs": "^2.4.2",
4648
"@types/geojson": "^7946.0.13",
47-
"@types/kafkajs": "^1.9.0",
48-
"@types/passport-saml": "^1.1.3",
49-
"@types/pem": "^1.9.6",
50-
"@types/uuid": "^8.3.0",
51-
"@types/ws": "^8.5.3",
49+
"@types/pem": "^1.14.4",
50+
"@types/ws": "^8.18.1",
5251
"@types/xml2js": "^0.4.14",
53-
"ajv": "^6.12.6",
54-
"axios": "^1.6.1",
55-
"axios-cache-adapter": "^2.7.3",
52+
"ajv": "^8.17.1",
53+
"axios": "^1.12.2",
54+
"axios-cache-interceptor": "^1.8.3",
5655
"bcryptjs": "^2.4.3",
5756
"bluebird": "^3.7.2",
58-
"cache-manager": "^4.0.1",
5957
"class-transformer": "^0.5.1",
60-
"class-validator": "^0.14.0",
61-
"compression": "^1.7.4",
62-
"cookie-parser": "^1.4.5",
58+
"class-validator": "^0.14.2",
59+
"compression": "^1.8.1",
60+
"cookie-parser": "^1.4.7",
6361
"crypto-js": "^4.2.0",
64-
"dayjs": "^1.11.13",
62+
"dayjs": "^1.11.18",
6563
"helmet": "^8.1.0",
6664
"kafkajs": "^2.2.4",
67-
"lodash": "^4.17.20",
68-
"mqtt": "^4.3.7",
65+
"lodash": "^4.17.21",
66+
"mqtt": "^5.14.1",
6967
"njwt": "^1.0.0",
70-
"nodemailer": "^6.7.2",
71-
"passport": "^0.6.0",
68+
"nodemailer": "^7.0.9",
69+
"passport": "^0.7.0",
7270
"passport-headerapikey": "^1.2.2",
73-
"passport-jwt": "^4.0.0",
71+
"passport-jwt": "^4.0.1",
7472
"passport-local": "^1.0.0",
75-
"passport-saml": "^3.2.4",
76-
"pem": "^1.14.7",
77-
"pg": "^8.5.1",
78-
"protobufjs": "^6.11.4",
79-
"reflect-metadata": "^0.1.13",
80-
"rimraf": "^3.0.2",
81-
"rxjs": "^7.5.7",
82-
"swagger-ui-express": "^4.1.5",
83-
"typeorm": "^0.3.10",
84-
"uuid": "^8.3.2",
73+
"pem": "^1.14.8",
74+
"pg": "^8.16.3",
75+
"protobufjs": "^7.5.4",
76+
"reflect-metadata": "^0.2.2",
77+
"rimraf": "^6.0.1",
78+
"rxjs": "^7.8.2",
79+
"swagger-ui-express": "^5.0.1",
80+
"typeorm": "^0.3.27",
81+
"uuid": "^13.0.0",
8582
"wait-for-expect": "^3.0.2"
8683
},
8784
"devDependencies": {
88-
"@nestjs/cli": "^9.3.0",
89-
"@nestjs/testing": "^9.1.2",
85+
"@nestjs/cli": "^11.0.10",
86+
"@nestjs/testing": "^11.1.6",
9087
"@types/bcryptjs": "^2.4.2",
91-
"@types/bluebird": "^3.5.33",
92-
"@types/cache-manager": "^4.0.1",
93-
"@types/compression": "^1.7.0",
94-
"@types/cookie-parser": "^1.4.2",
95-
"@types/cron": "^1.7.2",
96-
"@types/crypto-js": "^4.1.1",
88+
"@types/bluebird": "^3.5.42",
89+
"@types/compression": "^1.8.1",
90+
"@types/cookie-parser": "^1.4.9",
91+
"@types/cron": "^2.4.3",
92+
"@types/crypto-js": "^4.2.2",
9793
"@types/express": "^4.17.9",
9894
"@types/geojson": "^7946.0.13",
9995
"@types/jest": "^30.0.0",
100-
"@types/kafkajs": "^1.9.0",
101-
"@types/lodash": "^4.14.165",
96+
"@types/lodash": "^4.17.20",
10297
"@types/node": "^14.14.14",
10398
"@types/nodemailer": "^6.4.4",
10499
"@types/passport-jwt": "^3.0.3",
105100
"@types/passport-local": "^1.0.33",
106-
"@types/passport-saml": "^1.1.2",
107101
"@types/supertest": "^2.0.10",
108102
"@types/uuid": "^8.3.0",
109103
"@types/validator": "^13.7.1",
110104
"@types/ws": "^8.5.3",
111105
"@types/xml2js": "^0.4.14",
112-
"@typescript-eslint/eslint-plugin": "^6.10.0",
113-
"@typescript-eslint/parser": "^6.10.0",
114-
"eslint": "^8.24.0",
115-
"eslint-config-prettier": "^7.0.0",
106+
"@typescript-eslint/eslint-plugin": "^8.46.0",
107+
"@typescript-eslint/parser": "^8.46.0",
108+
"eslint": "^9.37.0",
109+
"eslint-config-prettier": "^10.1.8",
116110
"jest": "^29.7.0",
117111
"prettier": "^2.2.1",
118-
"supertest": "^6.0.1",
112+
"supertest": "^7.1.4",
119113
"ts-jest": "^29.1.1",
120114
"ts-node": "^10.9.1",
121115
"typescript": "~5.4.5"
122116
},
123117
"overrides": {
124118
"@babel/traverse": "^7.23.2",
125-
"axios": "^1.6.1",
126119
"xml2js": "^0.6.2",
127120
"jsonwebtoken": "^9.0.0",
128121
"debug": "^4.3.4",

src/auth/kombit.strategy.ts

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,37 @@ import { ErrorCodes } from "@enum/error-codes.enum";
44
import { Injectable, Logger } from "@nestjs/common";
55
import { PassportStrategy } from "@nestjs/passport";
66
import { AuthService } from "@services/user-management/auth.service";
7-
import { Profile, Strategy } from "passport-saml";
7+
import { Strategy as SamlStrategy } from "@node-saml/passport-saml";
8+
import { Profile } from "@node-saml/node-saml";
89

910
@Injectable()
10-
export class KombitStrategy extends PassportStrategy(Strategy, "kombit") {
11-
constructor(private readonly authService: AuthService) {
12-
super({
13-
issuer: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/metadata`,
14-
audience: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/metadata`,
11+
export class KombitStrategy extends PassportStrategy(SamlStrategy, "kombit") {
12+
private readonly logger = new Logger(KombitStrategy.name);
1513

16-
callbackUrl: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/login/callback`,
17-
logoutCallbackUrl: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/logout/callback`,
18-
logoutUrl: configuration()["kombit"]["entryPoint"],
19-
entryPoint: configuration()["kombit"]["entryPoint"],
20-
identifierFormat: "",
21-
cert: configuration()["kombit"]["certificatePublicKey"],
22-
privateCert: configuration()["kombit"]["certificatePrivateKey"],
23-
decryptionPvk: configuration()["kombit"]["certificatePrivateKey"],
24-
signatureAlgorithm: "sha256",
25-
disableRequestedAuthnContext: true,
26-
authnRequestBinding: "HTTP-Redirect",
27-
acceptedClockSkewMs: 1000, // Allow some slack in clock sync
28-
});
14+
constructor(private readonly authService: AuthService) {
15+
super(
16+
{
17+
issuer: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/metadata`,
18+
callbackUrl: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/login/callback`,
19+
publicCert: configuration()["kombit"]["certificatePublicKey"],
20+
idpCert: configuration()["kombit"]["certificatePublicKey"],
21+
audience: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/metadata`,
22+
logoutCallbackUrl: `${configuration()["backend"]["baseurl"]}/api/v1/auth/kombit/logout/callback`,
23+
logoutUrl: configuration()["kombit"]["entryPoint"],
24+
entryPoint: configuration()["kombit"]["entryPoint"],
25+
identifierFormat: "",
26+
decryptionPvk: configuration()["kombit"]["certificatePrivateKey"],
27+
signatureAlgorithm: "sha256",
28+
disableRequestedAuthnContext: true,
29+
authnRequestBinding: "HTTP-Redirect",
30+
acceptedClockSkewMs: 1000, // Allow some slack in clock sync
31+
},
32+
(req, profile, done) => {
33+
return this.validate(profile, done);
34+
}
35+
);
2936
}
3037

31-
private readonly logger = new Logger(KombitStrategy.name);
32-
3338
// eslint-disable-next-line @typescript-eslint/ban-types
3439
async validate(profile: Profile, done: Function): Promise<UserResponseDto> {
3540
try {

src/config/configuration.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { GetLogLevels, formatEmail } from "@helpers/env-variable-helper";
1+
import { formatEmail, GetLogLevels } from "@helpers/env-variable-helper";
22

33
export default (): any => {
44
return {
@@ -9,7 +9,7 @@ export default (): any => {
99
username: process.env.DATABASE_USERNAME || "os2iot",
1010
password: process.env.DATABASE_PASSWORD || "toi2so",
1111
ssl: process.env.DATABASE_ENABLE_SSL === "true",
12-
timezone: 'Z'
12+
timezone: "Z",
1313
},
1414
jwt: {
1515
secret: process.env.JWT_SECRET || "secretKey-os2iot-secretKey",
@@ -25,7 +25,7 @@ export default (): any => {
2525
process.env.KOMBIT_ENTRYPOINT ||
2626
"https://adgangsstyring.eksterntest-stoettesystemerne.dk/runtime/saml2/issue.idp",
2727
certificatePublicKey: process.env.KOMBIT_CERTIFICATEPUBLICKEY || "INSERT_KOMBIT_CERT", // Public certificate from Kombit Test server
28-
certificatePrivateKey: process.env.KOMBIT_CERTIFICATEPRIVATEKEY || null,
28+
certificatePrivateKey: process.env.KOMBIT_CERTIFICATEPRIVATEKEY || "",
2929
roleUri: process.env.KOMBIT_ROLE_NAME || "http://os2iot.dk/roles/usersystemrole/adgang/",
3030
},
3131
chirpstack: {

src/controllers/user-management/auth.controller.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,23 @@ import { KombitStrategy } from "@auth/kombit.strategy";
3636
import { ErrorCodes } from "@enum/error-codes.enum";
3737
import { CustomExceptionFilter } from "@auth/custom-exception-filter";
3838
import { isOrganizationPermission } from "@helpers/security-helper";
39-
import { RequestWithUser } from "passport-saml/lib/passport-saml/types";
4039
import Configuration from "@config/configuration";
4140
import { ApiAuth } from "@auth/swagger-auth-decorator";
41+
import { RequestWithUser } from "@node-saml/passport-saml/lib/types";
4242

4343
@UseFilters(new CustomExceptionFilter())
4444
@ApiTags("Auth")
4545
@Controller("auth")
4646
export class AuthController {
47+
private readonly logger = new Logger(AuthController.name);
48+
4749
constructor(
4850
private authService: AuthService,
4951
private userService: UserService,
5052
private organisationService: OrganizationService,
5153
private strategy: KombitStrategy
5254
) {}
5355

54-
private readonly logger = new Logger(AuthController.name);
55-
5656
@Get("kombit/login")
5757
@ApiOperation({ summary: "Initiate login with Kombit adgangsstyring" })
5858
@UseGuards(KombitAuthGuard)

src/helpers/fiware-token.helper.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { HttpService } from "@nestjs/axios";
2-
import { CACHE_MANAGER, Inject, Injectable, Logger } from "@nestjs/common";
3-
import { Cache } from "cache-manager";
2+
import { Inject, Injectable, Logger } from "@nestjs/common";
43
import { FiwareDataTargetConfiguration } from "../entities/interfaces/fiware-data-target-configuration.interface";
4+
import { Cache, CACHE_MANAGER } from "@nestjs/cache-manager";
55

66
type TokenEndpointResponse = {
77
data: {
@@ -38,7 +38,7 @@ export class AuthenticationTokenProvider {
3838
@Inject(CACHE_MANAGER) private cacheManager: Cache
3939
) {}
4040

41-
async clearConfig(config: FiwareDataTargetConfiguration): Promise<void> {
41+
async clearConfig(config: FiwareDataTargetConfiguration): Promise<boolean> {
4242
if (config.clientId) {
4343
this.logger.debug(`AuthenticationTokenProvider clearing token for ${config.clientId}`);
4444
const key = config.clientId + config.updatedAt.getTime();
@@ -74,7 +74,7 @@ export class AuthenticationTokenProvider {
7474
this.logger.debug(
7575
`AuthenticationTokenProvider caching token for ${config.clientId} (expires in ${ttl} seconds)`
7676
);
77-
await this.cacheManager.set(key, data.access_token, { ttl });
77+
await this.cacheManager.set(key, data.access_token, ttl);
7878
return data.access_token;
7979
} catch (err) {
8080
this.logger.error(`AuthenticationTokenProvider got error ${err}`);

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import helmet from "helmet";
1212

1313
async function bootstrap() {
1414
// Load .env file as environment before startup.
15-
dotenv.config({ path: "../.env", debug: true });
15+
dotenv.config({ path: "./.env", debug: true });
1616

1717
const config = {
1818
NEST_PORT: 3000,

src/modules/data-target/data-target-fiware-sender.module.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { HttpModule } from "@nestjs/axios";
2-
import { CacheModule, Module } from "@nestjs/common";
2+
import { Module } from "@nestjs/common";
33
import { FiwareDataTargetService } from "@services/data-targets/fiware-data-target.service";
44
import {
55
AuthenticationTokenProvider,
66
CLIENT_SECRET_PROVIDER,
77
PlainTextClientSecretProvider,
8-
} from "../../helpers/fiware-token.helper";
8+
} from "@helpers/fiware-token.helper";
9+
import { CacheModule } from "@nestjs/cache-manager";
910

1011
@Module({
1112
imports: [HttpModule, CacheModule.register()],

src/services/data-management/chirpstack-mqtt-listener.service.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,15 @@ import { ChirpstackStateTemplatePath } from "@resources/resource-paths";
1313
import { ReceiveDataService } from "@services/data-management/receive-data.service";
1414
import { IoTDeviceDownlinkService } from "@services/device-management/iot-device-downlink.service";
1515
import { IoTDeviceService } from "@services/device-management/iot-device.service";
16-
import * as mqtt from "mqtt";
17-
import { Client } from "mqtt";
16+
import mqtt, { MqttClient } from "mqtt";
1817
import * as Protobuf from "protobufjs";
1918

2019
@Injectable()
2120
export class ChirpstackMQTTListenerService implements OnApplicationBootstrap {
22-
constructor(
23-
private receiveDataService: ReceiveDataService,
24-
private iotDeviceService: IoTDeviceService,
25-
private downlinkService: IoTDeviceDownlinkService
26-
) {
27-
const connStateFullTemplate = Protobuf.loadSync(ChirpstackStateTemplatePath);
28-
this.connStateType = connStateFullTemplate.lookupType("ConnState");
29-
}
30-
21+
MQTT_URL = `mqtt://${process.env.CS_MQTT_HOSTNAME || "localhost"}:${process.env.CS_MQTT_PORT || "1883"}`;
22+
client: MqttClient;
3123
private readonly logger = new Logger(ChirpstackMQTTListenerService.name);
3224
private readonly connStateType: Protobuf.Type;
33-
34-
MQTT_URL = `mqtt://${process.env.CS_MQTT_HOSTNAME || "localhost"}:${process.env.CS_MQTT_PORT || "1883"}`;
35-
client: Client;
36-
3725
private readonly CHIRPSTACK_MQTT_DEVICE_DATA_PREFIX = "application/";
3826
private readonly CHIRPSTACK_MQTT_DEVICE_DATA_TOPIC = this.CHIRPSTACK_MQTT_DEVICE_DATA_PREFIX + "+/device/+/event/up";
3927
private readonly CHIRPSTACK_MQTT_DEVICE_DATA_TXACK_TOPIC =
@@ -45,6 +33,15 @@ export class ChirpstackMQTTListenerService implements OnApplicationBootstrap {
4533
private readonly CHIRPSTACK_MQTT_GATEWAY_PREFIX = "gateway/";
4634
private readonly CHIRPSTACK_MQTT_GATEWAY_TOPIC = this.CHIRPSTACK_MQTT_GATEWAY_PREFIX + "+/state/conn";
4735

36+
constructor(
37+
private receiveDataService: ReceiveDataService,
38+
private iotDeviceService: IoTDeviceService,
39+
private downlinkService: IoTDeviceDownlinkService
40+
) {
41+
const connStateFullTemplate = Protobuf.loadSync(ChirpstackStateTemplatePath);
42+
this.connStateType = connStateFullTemplate.lookupType("ConnState");
43+
}
44+
4845
public async onApplicationBootstrap(): Promise<void> {
4946
this.logger.debug("Pre-init");
5047

0 commit comments

Comments
 (0)