Skip to content

Commit 5cfa8ee

Browse files
augusthjerrildfcv-iteratorItAugustHA-Iterator
authored
Feature/check api acces (#250)
* Partial done access check * get users on allowed organizations instead of all users. --------- Co-authored-by: Frederik Christ Vestergaard <fcv@iterator-it.dk> Co-authored-by: August Andersen <aha@iterator-it.dk>
1 parent 1a03b5d commit 5cfa8ee

File tree

8 files changed

+93
-7688
lines changed

8 files changed

+93
-7688
lines changed

package-lock.json

Lines changed: 1 addition & 7548 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ import { AuditLog } from "@services/audit-log.service";
3939
import { ActionType } from "@entities/audit-log-entry";
4040
import { ListAllEntitiesDto } from "@dto/list-all-entities.dto";
4141
import { ApiAuth } from "@auth/swagger-auth-decorator";
42+
import { checkIfUserHasAccessToOrganization, OrganizationAccessScope } from "@helpers/security-helper";
43+
import { PermissionType } from "@enum/permission-type.enum";
4244

4345
@UseGuards(JwtAuthGuard, RolesGuard)
4446
@ApiAuth()
4547
@ApiForbiddenResponse()
4648
@ApiUnauthorizedResponse()
47-
@ApiTags("User Management")
49+
@ApiTags("Organization")
4850
@Controller("organization")
4951
@GlobalAdmin()
5052
export class OrganizationController {
@@ -121,6 +123,7 @@ export class OrganizationController {
121123
@Param("id", new ParseIntPipe()) id: number
122124
): Promise<Organization> {
123125
try {
126+
checkIfUserHasAccessToOrganization(req, id, OrganizationAccessScope.UserAdministrationRead);
124127
return await this.organizationService.findByIdWithRelations(id);
125128
} catch (err) {
126129
throw new NotFoundException(ErrorCodes.IdDoesNotExists);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import { ApiAuth } from "@auth/swagger-auth-decorator";
5555
@ApiAuth()
5656
@ApiForbiddenResponse()
5757
@ApiUnauthorizedResponse()
58-
@ApiTags("User Management")
58+
@ApiTags("Permission")
5959
@Controller("permission")
6060
export class PermissionController {
6161
constructor(

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,15 @@ export class UserController {
235235

236236
@Get()
237237
@ApiOperation({ summary: "Get all users" })
238-
async findAll(@Query() query?: ListAllEntitiesDto): Promise<ListAllUsersResponseDto> {
239-
return await this.userService.findAll(query);
238+
async findAll(
239+
@Req() req: AuthenticatedRequest,
240+
@Query() query?: ListAllEntitiesDto
241+
): Promise<ListAllUsersResponseDto> {
242+
if (req.user.permissions.isGlobalAdmin) {
243+
return await this.userService.findAll(query);
244+
} else {
245+
const allowedOrganizations = req.user.permissions.getAllOrganizationsWithUserAdmin();
246+
return await this.userService.getUsersOnOrganizations(allowedOrganizations, query);
247+
}
240248
}
241249
}

src/entities/dto/list-all-applications.dto.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,16 @@
11
import { DefaultLimit, DefaultOffset } from "@config/constants/pagination-constants";
22
import { ListAllEntitiesDto } from "@dto/list-all-entities.dto";
33
import { IsSwaggerOptional } from "@helpers/optional-validator";
4-
import {
5-
NullableStringToNumber,
6-
StringToNumber,
7-
} from "@helpers/string-to-number-validator";
4+
import { NullableStringToNumber, StringToNumber } from "@helpers/string-to-number-validator";
85
import { ApiProperty, OmitType } from "@nestjs/swagger";
96
import { Transform } from "class-transformer";
107
import { IsOptional, IsNumber } from "class-validator";
118

12-
export class ListAllApplicationsDto extends OmitType(ListAllEntitiesDto, [
13-
"limit",
14-
"offset",
15-
]) {
9+
export class ListAllApplicationsDto extends OmitType(ListAllEntitiesDto, ["limit", "offset"]) {
1610
@IsSwaggerOptional({ description: "Filter to one organization" })
1711
@StringToNumber()
1812
organizationId?: number;
1913

20-
@IsSwaggerOptional({ description: "Filter to one permission" })
21-
@StringToNumber()
22-
permissionId?: number;
23-
2414
@ApiProperty({ type: Number, required: false })
2515
@IsOptional()
2616
@IsNumber()

src/services/device-management/application.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ export class ApplicationService {
427427
name: device.name,
428428
type: device.type,
429429
latestSentMessage: device.latestReceivedMessage?.sentTime,
430-
location: device.location
430+
location: device.location,
431431
};
432432
});
433433

src/services/user-management/organization.service.ts

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
import {
2-
BadRequestException,
3-
Inject,
4-
Injectable,
5-
Logger,
6-
forwardRef,
7-
NotFoundException,
8-
} from "@nestjs/common";
1+
import { BadRequestException, Inject, Injectable, Logger, forwardRef, NotFoundException } from "@nestjs/common";
92
import { InjectRepository } from "@nestjs/typeorm";
103
import { In, Repository } from "typeorm";
114

@@ -24,6 +17,7 @@ import { PermissionService } from "./permission.service";
2417
import { User } from "@entities/user.entity";
2518
import { UserService } from "./user.service";
2619
import { Permission } from "@entities/permissions/permission.entity";
20+
import { AuthenticatedRequest } from "@dto/internal/authenticated-request";
2721

2822
@Injectable()
2923
export class OrganizationService {
@@ -55,22 +49,15 @@ export class OrganizationService {
5549
}
5650
}
5751

58-
async update(
59-
id: number,
60-
dto: UpdateOrganizationDto,
61-
userId: number
62-
): Promise<Organization> {
52+
async update(id: number, dto: UpdateOrganizationDto, userId: number): Promise<Organization> {
6353
const org = await this.findByIdWithRelations(id);
6454
org.name = dto.name;
6555
org.updatedBy = userId;
6656

6757
return await this.organizationRepository.save(org);
6858
}
6959

70-
async updateOpenDataDkRegistered(
71-
id: number,
72-
userId: number
73-
): Promise<Organization> {
60+
async updateOpenDataDkRegistered(id: number, userId: number): Promise<Organization> {
7461
const org = await this.findByIdWithRelations(id);
7562
org.openDataDkRegistered = true;
7663
org.updatedBy = userId;
@@ -84,14 +71,9 @@ export class OrganizationService {
8471
return await this.organizationRepository.save(org);
8572
}
8673

87-
async rejectAwaitingUser(
88-
user: User,
89-
organization: Organization
90-
): Promise<Organization> {
74+
async rejectAwaitingUser(user: User, organization: Organization): Promise<Organization> {
9175
if (organization.awaitingUsers.find(dbUser => dbUser.id === user.id)) {
92-
const index = organization.awaitingUsers.findIndex(
93-
dbUser => dbUser.id === user.id
94-
);
76+
const index = organization.awaitingUsers.findIndex(dbUser => dbUser.id === user.id);
9577
organization.awaitingUsers.splice(index, 1);
9678
await this.userService.sendRejectionMail(user, organization);
9779
return await this.organizationRepository.save(organization);
@@ -110,9 +92,7 @@ export class OrganizationService {
11092
};
11193
}
11294

113-
mapPermissionsToOrganizations(
114-
permissions: Permission[]
115-
): Organization[] {
95+
mapPermissionsToOrganizations(permissions: Permission[]): Organization[] {
11696
const requestedOrganizations: Organization[] = [];
11797

11898
for (let index = 0; index < permissions.length; index++) {
@@ -141,14 +121,12 @@ export class OrganizationService {
141121
return requestedOrganizations;
142122
}
143123

144-
mapPermissionsToOneOrganization(
145-
permissions: Permission[]
146-
): Organization {
124+
mapPermissionsToOneOrganization(permissions: Permission[]): Organization {
147125
const org: Organization = new Organization();
148126

149127
permissions.map(permission => {
150128
org.id = permission.organization.id;
151-
org.name = permission.organization.name
129+
org.name = permission.organization.name;
152130
});
153131

154132
org.permissions = [];
@@ -163,9 +141,7 @@ export class OrganizationService {
163141
return org;
164142
}
165143

166-
async findAllPaginated(
167-
query?: ListAllEntitiesDto
168-
): Promise<ListAllOrganizationsResponseDto> {
144+
async findAllPaginated(query?: ListAllEntitiesDto): Promise<ListAllOrganizationsResponseDto> {
169145
const sorting: { [id: string]: string | number } = this.getSorting(query);
170146

171147
const [data, count] = await this.organizationRepository.findAndCount({
@@ -182,6 +158,7 @@ export class OrganizationService {
182158
}
183159

184160
async findAllMinimal(): Promise<ListAllMinimalOrganizationsResponseDto> {
161+
185162
const [data, count] = await this.organizationRepository.findAndCount({
186163
select: ["id", "name"],
187164
});
@@ -218,9 +195,7 @@ export class OrganizationService {
218195
const sorting: { [id: string]: string | number } = {};
219196
if (
220197
query?.orderOn != null &&
221-
(query.orderOn == "id" ||
222-
query.orderOn == "name" ||
223-
query.orderOn == "lastLogin")
198+
(query.orderOn == "id" || query.orderOn == "name" || query.orderOn == "lastLogin")
224199
) {
225200
sorting[query.orderOn] = query.sort.toLocaleUpperCase();
226201
} else {
@@ -230,7 +205,7 @@ export class OrganizationService {
230205
}
231206

232207
async findById(organizationId: number): Promise<Organization> {
233-
return await this.organizationRepository.findOneByOrFail({ id: organizationId});
208+
return await this.organizationRepository.findOneByOrFail({ id: organizationId });
234209
}
235210

236211
async findByIdWithRelations(organizationId: number): Promise<Organization> {

0 commit comments

Comments
 (0)