Skip to content

Commit 90aa92f

Browse files
Merge branch 'stage' for release v1.5.0
2 parents 4875876 + 81c0913 commit 90aa92f

File tree

62 files changed

+1896
-271
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1896
-271
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# compiled output
22
/dist
33
/node_modules
4-
4+
ca.crt
5+
ca.key
56
# Logs
67
logs
78
*.log

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ ENV NODE_ENV build
55

66
RUN npm install -g nest eslint jest
77

8+
RUN apk add openssl
9+
810
USER node
911

1012
# ENV NPM_CONFIG_PREFIX=/home/node/.npm-global

package-lock.json

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

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@types/geojson": "^7946.0.7",
4545
"@types/kafkajs": "^1.9.0",
4646
"@types/passport-saml": "^1.1.3",
47+
"@types/pem": "^1.9.6",
4748
"@types/uuid": "^8.3.0",
4849
"@types/ws": "^8.5.3",
4950
"@types/xml2js": "^0.4.7",
@@ -57,6 +58,7 @@
5758
"class-validator": "^0.14.0",
5859
"compression": "^1.7.4",
5960
"cookie-parser": "^1.4.5",
61+
"crypto-js": "^4.1.1",
6062
"kafkajs": "^2.2.4",
6163
"lodash": "^4.17.20",
6264
"mqtt": "^4.3.7",
@@ -67,6 +69,7 @@
6769
"passport-jwt": "^4.0.0",
6870
"passport-local": "^1.0.0",
6971
"passport-saml": "^3.2.4",
72+
"pem": "^1.14.7",
7073
"pg": "^8.5.1",
7174
"protobufjs": "^6.11.3",
7275
"reflect-metadata": "^0.1.13",
@@ -75,7 +78,7 @@
7578
"swagger-ui-express": "^4.1.5",
7679
"typeorm": "^0.3.10",
7780
"uuid": "^8.3.2",
78-
"vm2": "^3.9.11",
81+
"vm2": "^3.9.17",
7982
"wait-for-expect": "^3.0.2"
8083
},
8184
"devDependencies": {
@@ -87,6 +90,7 @@
8790
"@types/compression": "^1.7.0",
8891
"@types/cookie-parser": "^1.4.2",
8992
"@types/cron": "^1.7.2",
93+
"@types/crypto-js": "^4.1.1",
9094
"@types/express": "^4.17.9",
9195
"@types/geojson": "^7946.0.7",
9296
"@types/kafkajs": "^1.9.0",

src/config/configuration.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ export default (): any => {
3939
email: {
4040
host: process.env.EMAIL_HOST || "smtp.ethereal.email",
4141
port: process.env.EMAIL_PORT || 587,
42-
user: process.env.EMAIL_USER || "ara.kertzmann8@ethereal.email",
43-
pass: process.env.EMAIL_PASS || "KzRSyYReEygpFPPZdd",
42+
user: process.env.EMAIL_USER || "tremayne38@ethereal.email",
43+
pass: process.env.EMAIL_PASS || "UjbMtRZNkrUcVJsvTM",
4444
/**
4545
* Can be formatted to show a user-friendly name before the e-mail.
4646
* E.g. "OS2iot <[email protected]>"
4747
*/
4848
from: process.env.EMAIL_FROM
4949
? formatEmail(process.env.EMAIL_FROM)
50-
: "OS2iot ara.kertzmann8@ethereal.email",
50+
: "OS2iot tremayne38@ethereal.email",
5151
},
5252
frontend: {
5353
baseurl: process.env.FRONTEND_BASEURL || "http://localhost:8081",

src/controllers/admin-controller/data-target.controller.ts

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ import {
1313
Req,
1414
UseGuards,
1515
} from "@nestjs/common";
16-
import { UnauthorizedException } from "@nestjs/common";
1716
import {
1817
ApiBadRequestResponse,
1918
ApiBearerAuth,
2019
ApiForbiddenResponse,
20+
ApiNotFoundResponse,
2121
ApiOperation,
2222
ApiTags,
2323
ApiUnauthorizedResponse,
2424
} from "@nestjs/swagger";
2525

26-
import { ComposeAuthGuard } from '@auth/compose-auth.guard';
26+
import { ComposeAuthGuard } from "@auth/compose-auth.guard";
2727
import { Read, ApplicationAdmin } from "@auth/roles.decorator";
2828
import { RolesGuard } from "@auth/roles.guard";
2929
import { CreateDataTargetDto } from "@dto/create-data-target.dto";
@@ -41,6 +41,8 @@ import {
4141
import { DataTargetService } from "@services/data-targets/data-target.service";
4242
import { AuditLog } from "@services/audit-log.service";
4343
import { ActionType } from "@entities/audit-log-entry";
44+
import { OrganizationService } from "@services/user-management/organization.service";
45+
import { OddkMailInfo } from "@dto/oddk-mail-info.dto";
4446

4547
@ApiTags("Data Target")
4648
@Controller("data-target")
@@ -50,7 +52,10 @@ import { ActionType } from "@entities/audit-log-entry";
5052
@ApiForbiddenResponse()
5153
@ApiUnauthorizedResponse()
5254
export class DataTargetController {
53-
constructor(private dataTargetService: DataTargetService) {}
55+
constructor(
56+
private dataTargetService: DataTargetService,
57+
private organizationService: OrganizationService
58+
) {}
5459

5560
@Get()
5661
@ApiOperation({ summary: "Find all DataTargets" })
@@ -65,7 +70,11 @@ export class DataTargetController {
6570
query.applicationId = +query.applicationId;
6671
}
6772

68-
checkIfUserHasAccessToApplication(req, query.applicationId, ApplicationAccessScope.Read);
73+
checkIfUserHasAccessToApplication(
74+
req,
75+
query.applicationId,
76+
ApplicationAccessScope.Read
77+
);
6978
const allowed = req.user.permissions.getAllApplicationsWithAtLeastRead();
7079

7180
return await this.dataTargetService.findAndCountAllWithPagination(
@@ -83,7 +92,11 @@ export class DataTargetController {
8392
): Promise<DataTarget> {
8493
try {
8594
const dataTarget = await this.dataTargetService.findOne(id);
86-
checkIfUserHasAccessToApplication(req, dataTarget.application.id, ApplicationAccessScope.Read);
95+
checkIfUserHasAccessToApplication(
96+
req,
97+
dataTarget.application.id,
98+
ApplicationAccessScope.Read
99+
);
87100
return dataTarget;
88101
} catch (err) {
89102
throw new NotFoundException(ErrorCodes.IdDoesNotExists);
@@ -132,9 +145,17 @@ export class DataTargetController {
132145
): Promise<DataTarget> {
133146
const oldDataTarget = await this.dataTargetService.findOne(id);
134147
try {
135-
checkIfUserHasAccessToApplication(req, oldDataTarget.application.id, ApplicationAccessScope.Write);
148+
checkIfUserHasAccessToApplication(
149+
req,
150+
oldDataTarget.application.id,
151+
ApplicationAccessScope.Write
152+
);
136153
if (oldDataTarget.application.id !== updateDto.applicationId) {
137-
checkIfUserHasAccessToApplication(req, updateDto.applicationId, ApplicationAccessScope.Write);
154+
checkIfUserHasAccessToApplication(
155+
req,
156+
updateDto.applicationId,
157+
ApplicationAccessScope.Write
158+
);
138159
}
139160
} catch (err) {
140161
AuditLog.fail(
@@ -172,7 +193,11 @@ export class DataTargetController {
172193
): Promise<DeleteResponseDto> {
173194
try {
174195
const dt = await this.dataTargetService.findOne(id);
175-
checkIfUserHasAccessToApplication(req, dt.application.id, ApplicationAccessScope.Write);
196+
checkIfUserHasAccessToApplication(
197+
req,
198+
dt.application.id,
199+
ApplicationAccessScope.Write
200+
);
176201
const result = await this.dataTargetService.delete(id);
177202

178203
if (result.affected === 0) {
@@ -188,4 +213,47 @@ export class DataTargetController {
188213
throw new NotFoundException(err);
189214
}
190215
}
216+
217+
@Get("getOpenDataDkRegistered/:organizationId")
218+
@ApiOperation({ summary: "Get OpenDataDkRegistered-status for given OrganizationId" })
219+
@ApiNotFoundResponse()
220+
@Read()
221+
async getOpenDataDkRegistered(@Param("organizationId", new ParseIntPipe()) organizationId: number): Promise<boolean> {
222+
try {
223+
return (await this.organizationService.findById(organizationId))?.openDataDkRegistered;
224+
} catch (err) {
225+
throw new NotFoundException(ErrorCodes.IdDoesNotExists);
226+
}
227+
}
228+
229+
@Put("updateOpenDataDkRegistered/:organizationId")
230+
@ApiOperation({
231+
summary: "Update the OpenDataDkRegistered to true, for the given OrganizationId - to stop showing the dialog for sending ODDK-mail on creation of new datatargets",
232+
})
233+
@ApiNotFoundResponse()
234+
async updateOpenDataDkRegistered(
235+
@Req() req: AuthenticatedRequest,
236+
@Param("organizationId", new ParseIntPipe()) organizationId: number
237+
): Promise<boolean> {
238+
try {
239+
await this.organizationService.updateOpenDataDkRegistered(organizationId, req.user.userId);
240+
return true;
241+
} catch (err) {
242+
if (err.name == "EntityNotFound") {
243+
throw new NotFoundException();
244+
}
245+
throw err;
246+
}
247+
}
248+
249+
@Post("sendOpenDataDkMail")
250+
@ApiOperation({summary: "Send mail for registering datatargets to Open Data DK, for the given OrganizationId"})
251+
async sendOpenDataDkMail(
252+
@Req() req: AuthenticatedRequest,
253+
@Body() mailInfoDto: OddkMailInfo
254+
): Promise<boolean> {
255+
await this.dataTargetService.sendOpenDataDkMail(mailInfoDto, req.user.userId);
256+
await this.organizationService.updateOpenDataDkRegistered(mailInfoDto.organizationId, req.user.userId);
257+
return true;
258+
}
191259
}

src/controllers/admin-controller/iot-device-payload-decoder-data-target-connection.controller.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
ApiUnauthorizedResponse,
2525
} from "@nestjs/swagger";
2626

27-
import { ComposeAuthGuard } from '@auth/compose-auth.guard';
27+
import { ComposeAuthGuard } from "@auth/compose-auth.guard";
2828
import { Read, ApplicationAdmin } from "@auth/roles.decorator";
2929
import { RolesGuard } from "@auth/roles.guard";
3030
import { CreateIoTDevicePayloadDecoderDataTargetConnectionDto } from "@dto/create-iot-device-payload-decoder-data-target-connection.dto";
@@ -36,7 +36,10 @@ import { ListAllEntitiesDto } from "@dto/list-all-entities.dto";
3636
import { UpdateIoTDevicePayloadDecoderDataTargetConnectionDto as UpdateConnectionDto } from "@dto/update-iot-device-payload-decoder-data-target-connection.dto";
3737
import { IoTDevicePayloadDecoderDataTargetConnection } from "@entities/iot-device-payload-decoder-data-target-connection.entity";
3838
import { ErrorCodes } from "@enum/error-codes.enum";
39-
import { checkIfUserHasAccessToApplication, ApplicationAccessScope } from "@helpers/security-helper";
39+
import {
40+
checkIfUserHasAccessToApplication,
41+
ApplicationAccessScope,
42+
} from "@helpers/security-helper";
4043
import { IoTDevicePayloadDecoderDataTargetConnectionService } from "@services/device-management/iot-device-payload-decoder-data-target-connection.service";
4144
import { IoTDeviceService } from "@services/device-management/iot-device.service";
4245
import { AuditLog } from "@services/audit-log.service";
@@ -184,7 +187,11 @@ export class IoTDevicePayloadDecoderDataTargetConnectionController {
184187
) {
185188
const iotDevices = await this.iotDeviceService.findManyByIds(ids);
186189
iotDevices.forEach(x => {
187-
checkIfUserHasAccessToApplication(req, x.application.id, ApplicationAccessScope.Write);
190+
checkIfUserHasAccessToApplication(
191+
req,
192+
x.application.id,
193+
ApplicationAccessScope.Write
194+
);
188195
});
189196
}
190197

@@ -231,7 +238,11 @@ export class IoTDevicePayloadDecoderDataTargetConnectionController {
231238
const newIotDevice = await this.iotDeviceService.findOne(
232239
updateDto.iotDeviceIds[0]
233240
);
234-
checkIfUserHasAccessToApplication(req, newIotDevice.application.id, ApplicationAccessScope.Write);
241+
checkIfUserHasAccessToApplication(
242+
req,
243+
newIotDevice.application.id,
244+
ApplicationAccessScope.Write
245+
);
235246
const oldConnection = await this.service.findOne(id);
236247
await this.checkUserHasWriteAccessToAllIotDevices(updateDto.iotDeviceIds, req);
237248
const oldIds = oldConnection.iotDevices.map(x => x.id);

0 commit comments

Comments
 (0)