Skip to content

Commit

Permalink
Merge pull request hngprojects#487 from masterchief-Dave/feature/api-…
Browse files Browse the repository at this point in the history
…get-org-roles

feat: get all roles in organisation
  • Loading branch information
AdeGneus authored Aug 8, 2024
2 parents 95369e6 + 6048600 commit 5e10f86
Show file tree
Hide file tree
Showing 14 changed files with 323 additions and 54 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ package-lock.json

.mail.ts.bk
src/bk
swagger.json
swagger.json
todo.txt
43 changes: 42 additions & 1 deletion src/controllers/OrgController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Request, Response, NextFunction } from "express";
import { NextFunction, Request, Response } from "express";
import { ResourceNotFound, ServerError } from "../middleware";
import { OrgService } from "../services/org.services";
import log from "../utils/logger";

Expand Down Expand Up @@ -1071,4 +1072,44 @@ export class OrgController {
next(error);
}
}

async getSingleRole(req: Request, res: Response, next: NextFunction) {
try {
const organizationId = req.params.org_id;
const roleId = req.params.role_id;
const response = await this.orgService.fetchSingleRole(
organizationId,
roleId,
);

return res.status(200).json({
status_code: 200,
data: response,
});
} catch (error) {
next(error);
}
}

async getAllOrganizationRoles(
req: Request,
res: Response,
next: NextFunction,
) {
try {
const organizationId = req.params.org_id;
const response =
await this.orgService.fetchAllRolesInOrganization(organizationId);

return res.status(200).json({
status_code: 200,
data: response,
});
} catch (error) {
if (error instanceof ResourceNotFound) {
next(error);
}
next(new ServerError("Error fetching all roles in organization"));
}
}
}
9 changes: 9 additions & 0 deletions src/enums/permission-category.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export enum PermissionCategory {
CanViewTransactions = "canViewTransactions",
CanViewRefunds = "canViewRefunds",
CanLogRefunds = "canLogRefunds",
CanViewUsers = "canViewUsers",
CanCreateUsers = "canCreateUsers",
CanEditUsers = "canEditUsers",
CanBlacklistWhitelistUsers = "canBlacklistWhitelistUsers",
}
27 changes: 27 additions & 0 deletions src/models/organization-member.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import ExtendedBaseEntity from "./extended-base-entity";
import { Organization } from "./organization";
import { OrganizationRole } from "./organization-role.entity";
import { Profile } from "./profile";
import { User } from "./user";

@Entity()
export class OrganizationMember extends ExtendedBaseEntity {
@PrimaryGeneratedColumn("uuid")
id: string;

@ManyToOne(() => User, (user) => user.organizationMembers)
user_id: User;

@ManyToOne(
() => Organization,
(organization) => organization.organizationMembers,
)
organization_id: Organization;

@ManyToOne(() => OrganizationRole, (role) => role.organizationMembers)
role: OrganizationRole;

@ManyToOne(() => Profile)
profile_id: Profile;
}
36 changes: 36 additions & 0 deletions src/models/organization-role.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
Column,
Entity,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
} from "typeorm";
import ExtendedBaseEntity from "./extended-base-entity";
import { Organization } from "./organization";
import { OrganizationMember } from "./organization-member";
import { Permissions } from "./permissions.entity";

@Entity("roles")
export class OrganizationRole extends ExtendedBaseEntity {
@PrimaryGeneratedColumn("uuid")
id: string;

@Column({ length: 50, nullable: false })
name: string;

@Column({ length: 200, nullable: true })
description: string;

@OneToMany(() => Permissions, (permission) => permission.role, {
eager: false,
})
permissions: Permissions[];

@ManyToOne(() => Organization, (organization) => organization.role, {
eager: false,
})
organization: Organization;

@OneToMany(() => OrganizationMember, (member) => member.role)
organizationMembers: OrganizationMember[];
}
27 changes: 20 additions & 7 deletions src/models/organization.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import {
Entity,
PrimaryGeneratedColumn,
BeforeInsert,
Column,
OneToMany,
Entity,
ManyToMany,
BeforeInsert,
OneToMany,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from "typeorm";
import { User } from ".";
import { v4 as uuidv4 } from "uuid";
import { UserOrganization } from "./user-organisation";
import ExtendedBaseEntity from "./extended-base-entity";
import { User } from ".";
import { BillingPlan } from "./billing-plan";
import ExtendedBaseEntity from "./extended-base-entity";
import { OrganizationMember } from "./organization-member";
import { OrganizationRole } from "./organization-role.entity";
import { Payment } from "./payment";
import { Product } from "./product";
import { UserOrganization } from "./user-organisation";

@Entity()
export class Organization extends ExtendedBaseEntity {
Expand Down Expand Up @@ -74,6 +76,17 @@ export class Organization extends ExtendedBaseEntity {
@OneToMany(() => Product, (product) => product.org, { cascade: true })
products: Product[];

@OneToMany(() => OrganizationRole, (role) => role.organization, {
eager: false,
})
role: OrganizationRole;

@OneToMany(
() => OrganizationMember,
(organizationMember) => organizationMember.organization_id,
)
organizationMembers: OrganizationMember[];

@BeforeInsert()
generateSlug() {
this.slug = uuidv4();
Expand Down
23 changes: 23 additions & 0 deletions src/models/permissions.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import { PermissionCategory } from "../enums/permission-category.enum";
import ExtendedBaseEntity from "./extended-base-entity";
import { OrganizationRole } from "./organization-role.entity";

@Entity()
export class Permissions extends ExtendedBaseEntity {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({
type: "enum",
enum: PermissionCategory,
})
category: PermissionCategory;

@Column({ type: "boolean", nullable: false })
permission_list: boolean;

@ManyToOne(() => OrganizationRole, (role) => role.permissions, {
eager: false,
})
role: OrganizationRole;
}
7 changes: 7 additions & 0 deletions src/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { UserRole } from "../enums/userRoles";
import { getIsInvalidMessage } from "../utils";
import ExtendedBaseEntity from "./extended-base-entity";
import { Like } from "./like";
import { OrganizationMember } from "./organization-member";
import { UserOrganization } from "./user-organisation";

@Entity()
Expand Down Expand Up @@ -105,6 +106,12 @@ export class User extends ExtendedBaseEntity {
@Column({ nullable: true, type: "bigint" })
passwordResetExpires: number;

@OneToMany(
() => OrganizationMember,
(organizationMember) => organizationMember.organization_id,
)
organizationMembers: OrganizationMember[];

createPasswordResetToken(): string {
const resetToken = crypto.randomBytes(32).toString("hex");

Expand Down
12 changes: 12 additions & 0 deletions src/routes/organisation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,16 @@ orgRouter.put(
checkPermissions([UserRole.SUPER_ADMIN, UserRole.USER]),
orgController.updateOrganisation.bind(orgController),
);

orgRouter.get(
"/organizations/:org_id/roles/:role_id",
authMiddleware,
orgController.getSingleRole,
);

orgRouter.get(
"/organizations/:org_id/roles",
authMiddleware,
orgController.getAllOrganizationRoles,
);
export { orgRouter };
43 changes: 38 additions & 5 deletions src/services/org.services.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { Repository } from "typeorm";
import { v4 as uuidv4 } from "uuid";
import config from "../config/index";
import AppDataSource from "../data-source";
import { UserRole } from "../enums/userRoles";
import { BadRequest } from "../middleware";
import { Conflict, ResourceNotFound } from "../middleware/error";
import { Invitation, OrgInviteToken, UserOrganization } from "../models";
import { Organization } from "../models/organization";
import { OrganizationRole } from "../models/organization-role.entity";
import { User } from "../models/user";
import { ICreateOrganisation, IOrgService } from "../types";
import log from "../utils/logger";
import { UserOrganization, Invitation, OrgInviteToken } from "../models";
import { v4 as uuidv4 } from "uuid";
import { addEmailToQueue } from "../utils/queue";
import renderTemplate from "../views/email/renderTemplate";
import { Conflict, ResourceNotFound } from "../middleware/error";
import config from "../config/index";
const frontendBaseUrl = config.BASE_URL;

export class OrgService implements IOrgService {
private organizationRepository: Repository<Organization>;
private organizationRoleRepository: Repository<OrganizationRole>;
constructor() {
this.organizationRepository = AppDataSource.getRepository(Organization);
this.organizationRoleRepository =
AppDataSource.getRepository(OrganizationRole);
}
public async createOrganisation(
payload: ICreateOrganisation,
userId: string,
Expand Down Expand Up @@ -340,4 +348,29 @@ export class OrgService implements IOrgService {

return [];
}

public async fetchSingleRole(organizationId: string, roleId: string) {
// const orgRoles = await this.
}

public async fetchAllRolesInOrganization(organizationId: string) {
try {
const organization = await this.organizationRepository.findOne({
where: { id: organizationId },
});

if (!organization) {
throw new ResourceNotFound("Organization not found");
}

const roles = await this.organizationRoleRepository.find({
where: { organization: { id: organizationId } },
select: ["id", "name", "description"],
});

return roles;
} catch (error) {
throw error;
}
}
}
9 changes: 4 additions & 5 deletions src/services/user.services.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// src/services/UserService.ts
import { User } from "../models/user";
import { Profile } from "../models/profile";
import { IUserService } from "../types";
import { HttpError } from "../middleware";
import { Repository, UpdateResult } from "typeorm";
import AppDataSource from "../data-source";
import { cloudinary } from "../config/multer";
import AppDataSource from "../data-source";
import { HttpError } from "../middleware";
import { Profile } from "../models/profile";
import { User } from "../models/user";

interface IUserProfileUpdate {
first_name: string;
Expand Down
2 changes: 2 additions & 0 deletions src/test/blog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ jest.mock("../data-source", () => ({
},
}));

jest.mock("../models");

describe("BlogService", () => {
let blogService: BlogService;
let blogRepositoryMock: jest.Mocked<Repository<Blog>>;
Expand Down
Loading

0 comments on commit 5e10f86

Please sign in to comment.