Skip to content

Commit

Permalink
refactor(api): move organization roles to authorization module
Browse files Browse the repository at this point in the history
  • Loading branch information
johanbook committed Sep 20, 2023
1 parent 3639a9f commit b5b456d
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SetMetadata } from "@nestjs/common";

import { OrganizationRole } from "../../organization-roles.enum";

export const REQUIRED_ORGANIZATION_ROLES_KEY = "required-organization-roles";

export const RequiresOrganizationPermissions = (roles: OrganizationRole[]) =>
SetMetadata(REQUIRED_ORGANIZATION_ROLES_KEY, roles);

This file was deleted.

12 changes: 6 additions & 6 deletions services/api/src/core/authorization/client/guards/roles.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";
import { Reflector } from "@nestjs/core";

import { CurrentOrganizationService } from "src/features/organizations";
import { OrganizationMembershipRole as Role } from "src/features/organizations/infrastructure/entities/organization-membership.entity";

import { ROLES_KEY } from "../decorators/roles.decorator";
import { OrganizationRole } from "../../organization-roles.enum";
import { REQUIRED_ORGANIZATION_ROLES_KEY } from "../decorators/roles.decorator";

@Injectable()
export class RolesGuard implements CanActivate {
Expand All @@ -14,10 +14,10 @@ export class RolesGuard implements CanActivate {
) {}

async canActivate(context: ExecutionContext): Promise<boolean> {
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
context.getHandler(),
context.getClass(),
]);
const requiredRoles = this.reflector.getAllAndOverride<OrganizationRole[]>(
REQUIRED_ORGANIZATION_ROLES_KEY,
[context.getHandler(), context.getClass()],
);

if (!requiredRoles) {
return true;
Expand Down
3 changes: 2 additions & 1 deletion services/api/src/core/authorization/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { RequiresPermissions } from "./client/decorators/roles.decorator";
export { RequiresOrganizationPermissions } from "./client/decorators/requires-organization-permissions.decorator";
export { RolesGuard } from "./client/guards/roles.guard";
export { OrganizationRole } from "./organization-roles.enum";
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum OrganizationRole {
Admin = "admin",
Member = "member",
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { OrganizationMembershipRole } from "../../../infrastructure/entities/organization-membership.entity";
import { OrganizationRole } from "src/core/authorization";

import { OrganizationDetails } from "./organization.dto";

export class CurrentOrganizationDetails extends OrganizationDetails {
role!: OrganizationMembershipRole;
role!: OrganizationRole;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { OrganizationMembershipRole } from "../../../infrastructure/entities/organization-membership.entity";
import { OrganizationRole } from "src/core/authorization";

export class OrganizationMemberDetails {
joinedAt!: string;
name!: string;
id!: number;
imageUrl?: string;
profileId!: number;
role!: OrganizationMembershipRole;
role!: OrganizationRole;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Body, Controller, Get, Post, Query } from "@nestjs/common";
import { CommandBus, QueryBus } from "@nestjs/cqrs";
import { ApiTags } from "@nestjs/swagger";

import { RequiresPermissions } from "src/core/authorization";
import { RequiresOrganizationPermissions } from "src/core/authorization";

import { AddMemberToOrganizationCommand } from "../../application/contracts/commands/add-member-to-organization.command";
import { UpdateMemberRoleCommand } from "../../application/contracts/commands/update-member-role.command";
Expand All @@ -11,47 +11,57 @@ import { CurrentOrganizationDetails } from "../../application/contracts/dtos/cur
import { OrganizationMemberDetails } from "../../application/contracts/dtos/organization-member.dto";
import { GetOrganizationMembersQuery } from "../../application/contracts/queries/get-organization-members.query";
import { GetOrganizationQuery } from "../../application/contracts/queries/get-organization.query";
import { permissions } from "../../permissions";
import { organizationPermissions } from "../../organization.permissions";

@Controller("organizations/current")
@ApiTags("organizations")
export class CurrentOrganizationController {
constructor(private commandBus: CommandBus, private queryBus: QueryBus) {}

@Get()
@RequiresPermissions(permissions.CurrentOrganization.Read)
@RequiresOrganizationPermissions(
organizationPermissions.CurrentOrganization.Read,
)
async getCurrentOrganization(
@Query() query: GetOrganizationQuery,
): Promise<CurrentOrganizationDetails> {
return await this.queryBus.execute(query);
}

@Get("/members")
@RequiresPermissions(permissions.CurrentOrganization.Members.Read)
@RequiresOrganizationPermissions(
organizationPermissions.CurrentOrganization.Members.Read,
)
async getCurrentOrganizationMembers(
@Query() query: GetOrganizationMembersQuery,
): Promise<OrganizationMemberDetails[]> {
return await this.queryBus.execute(query);
}

@Post("/members")
@RequiresPermissions(permissions.CurrentOrganization.Members.Add)
@RequiresOrganizationPermissions(
organizationPermissions.CurrentOrganization.Members.Add,
)
async addMemberToOrganization(
@Body() command: AddMemberToOrganizationCommand,
): Promise<null> {
return await this.commandBus.execute(command);
}

@Post("/members/role")
@RequiresPermissions(permissions.CurrentOrganization.Members.UpdateRole)
@RequiresOrganizationPermissions(
organizationPermissions.CurrentOrganization.Members.UpdateRole,
)
async changeMemberRole(
@Body() command: UpdateMemberRoleCommand,
): Promise<null> {
return await this.commandBus.execute(command);
}

@Post()
@RequiresPermissions(permissions.CurrentOrganization.Update)
@RequiresOrganizationPermissions(
organizationPermissions.CurrentOrganization.Update,
)
async updateCurrentOrganization(
@Body() command: UpdateOrganizationCommand,
): Promise<null> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@ import {
PrimaryGeneratedColumn,
} from "typeorm";

import { OrganizationRole } from "src/core/authorization";
import { Profile } from "src/features/profiles/infrastructure/entities/profile.entity";

import { Organization } from "./organization.entity";

export enum OrganizationMembershipRole {
Admin = "admin",
Member = "member",
}

@Entity()
export class OrganizationMembership {
@PrimaryGeneratedColumn()
Expand All @@ -37,8 +33,8 @@ export class OrganizationMembership {

@Column({
type: "enum",
enum: OrganizationMembershipRole,
default: OrganizationMembershipRole.Member,
enum: OrganizationRole,
default: OrganizationRole.Member,
})
role!: OrganizationMembershipRole;
role!: OrganizationRole;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { OrganizationRole } from "src/core/authorization";

export const organizationPermissions = {
CurrentOrganization: {
Read: [OrganizationRole.Admin, OrganizationRole.Member],
Members: {
Add: [OrganizationRole.Admin],
Read: [OrganizationRole.Admin, OrganizationRole.Member],
UpdateRole: [OrganizationRole.Admin],
},
Update: [OrganizationRole.Admin],
},
};
13 changes: 0 additions & 13 deletions services/api/src/features/organizations/permissions.ts

This file was deleted.

0 comments on commit b5b456d

Please sign in to comment.