From 9d0e4b0ea3306f66b06ebb2705a1cb813700fca2 Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Sat, 25 Jan 2025 16:09:19 -0500 Subject: [PATCH 01/13] add employee field throughout files Co-authored-by: Gayatri Kondabathini --- apps/server/prisma/seed.ts | 6 ++++++ apps/server/src/app.controller.ts | 1 + apps/server/src/auth/dto/register-employee.dto.ts | 13 ++++++++++++- .../server/src/employees/dto/create-employee.dto.ts | 6 ++++++ apps/server/src/employees/employees.service.ts | 1 + apps/server/src/metadata.ts | 1 + apps/web/src/client/models/CreateEmployeeDto.ts | 1 + 7 files changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/server/prisma/seed.ts b/apps/server/prisma/seed.ts index 3c2666d7..0eee0067 100644 --- a/apps/server/prisma/seed.ts +++ b/apps/server/prisma/seed.ts @@ -49,6 +49,7 @@ type EmployeeData = { email: string; positionId: string; signatureLink: string; + isAdmin: boolean; }; // update or insert employee to database based on the employee id @@ -65,6 +66,7 @@ async function upsertEmployee(empData: EmployeeData) { position: { connect: { id: empData.positionId }, }, + isAdmin: empData.isAdmin, }, }); } @@ -387,6 +389,7 @@ async function main() { email: 'zhang.iri@northeastern.edu', positionId: CHIEF_OF_STAFF_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, { id: KAI_ZHENG_UUID, @@ -395,6 +398,7 @@ async function main() { email: 'zheng.kaiy@northeastern.edu', positionId: CHIEF_FIN_OFFICER_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, { id: ANGELA_WEIGL_UUID, @@ -403,6 +407,7 @@ async function main() { email: 'weigl.a@northeastern.edu', positionId: AGG_DIR_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, { id: ANSHUL_SHIRUDE_UUID, @@ -411,6 +416,7 @@ async function main() { email: 'shirude.a@northeastern.edu', positionId: CHIEF_LEARNING_ENGAGEMENT_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, ]; diff --git a/apps/server/src/app.controller.ts b/apps/server/src/app.controller.ts index 9a141f3d..bb479eb3 100644 --- a/apps/server/src/app.controller.ts +++ b/apps/server/src/app.controller.ts @@ -135,6 +135,7 @@ export class AppController { password: employeeDto.password, signatureLink: employeeDto.signatureLink, positionId: '', + isAdmin: employeeDto.isAdmin, }; const newEmployee = await this.authService.register( diff --git a/apps/server/src/auth/dto/register-employee.dto.ts b/apps/server/src/auth/dto/register-employee.dto.ts index c742ad41..91463c73 100644 --- a/apps/server/src/auth/dto/register-employee.dto.ts +++ b/apps/server/src/auth/dto/register-employee.dto.ts @@ -1,5 +1,11 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsString, MinLength, IsEmail } from 'class-validator'; +import { + IsNotEmpty, + IsString, + MinLength, + IsEmail, + IsBoolean, +} from 'class-validator'; export class RegisterEmployeeDto { @IsString() @@ -37,4 +43,9 @@ export class RegisterEmployeeDto { @IsNotEmpty() @ApiProperty() signatureLink: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty() + isAdmin: boolean; } diff --git a/apps/server/src/employees/dto/create-employee.dto.ts b/apps/server/src/employees/dto/create-employee.dto.ts index 8f705560..17ea039f 100644 --- a/apps/server/src/employees/dto/create-employee.dto.ts +++ b/apps/server/src/employees/dto/create-employee.dto.ts @@ -1,5 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { + IsBoolean, IsEmail, IsNotEmpty, IsString, @@ -38,4 +39,9 @@ export class CreateEmployeeDto { @IsNotEmpty() @ApiProperty() signatureLink: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty() + isAdmin: boolean; } diff --git a/apps/server/src/employees/employees.service.ts b/apps/server/src/employees/employees.service.ts index b888e54d..30254f8e 100644 --- a/apps/server/src/employees/employees.service.ts +++ b/apps/server/src/employees/employees.service.ts @@ -25,6 +25,7 @@ export class EmployeesService { createEmployeeDto.password, await bcrypt.genSalt(), ), + isAdmin: createEmployeeDto.isAdmin, }, include: { position: { diff --git a/apps/server/src/metadata.ts b/apps/server/src/metadata.ts index 7b8a176a..31725647 100644 --- a/apps/server/src/metadata.ts +++ b/apps/server/src/metadata.ts @@ -107,6 +107,7 @@ export default async () => { positionId: { required: true, type: () => String }, email: { required: true, type: () => String }, password: { required: true, type: () => String, minLength: 5 }, + isAdmin: { required: true, type: () => Boolean }, }, }, ], diff --git a/apps/web/src/client/models/CreateEmployeeDto.ts b/apps/web/src/client/models/CreateEmployeeDto.ts index 8cc762d1..bf077091 100644 --- a/apps/web/src/client/models/CreateEmployeeDto.ts +++ b/apps/web/src/client/models/CreateEmployeeDto.ts @@ -10,5 +10,6 @@ export type CreateEmployeeDto = { email: string; password: string; signatureLink: string; + isAdmin: boolean; }; From 0aa033c24f6a38183e29e8e8298727825accb3fd Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Sun, 2 Feb 2025 21:27:03 -0500 Subject: [PATCH 02/13] replace isAdmin with scope --- apps/server/prisma/schema.prisma | 7 ++++++- apps/server/prisma/seed.ts | 14 +++++++------- apps/server/src/app.controller.ts | 2 +- apps/server/src/auth/auth.service.spec.ts | 7 ++++--- apps/server/src/auth/auth.service.ts | 2 +- apps/server/src/auth/dto/register-employee.dto.ts | 13 ++++--------- apps/server/src/auth/guards/admin-auth.guard.ts | 3 ++- .../src/employees/dto/create-employee.dto.ts | 4 +--- .../src/employees/employees.controller.spec.ts | 9 +++++---- apps/server/src/employees/employees.service.ts | 2 +- .../src/employees/entities/employee.entity.ts | 6 +++--- apps/server/src/metadata.ts | 4 +++- apps/web/src/client/models/CreateEmployeeDto.ts | 2 +- apps/web/src/client/models/EmployeeBaseEntity.ts | 2 +- apps/web/src/client/models/EmployeeEntity.ts | 2 +- apps/web/src/client/models/RegisterEmployeeDto.ts | 1 + apps/web/src/client/models/UpdateEmployeeDto.ts | 1 + apps/web/src/context/AuthContext.tsx | 7 +++++-- apps/web/src/context/types.ts | 5 +++-- 19 files changed, 51 insertions(+), 42 deletions(-) diff --git a/apps/server/prisma/schema.prisma b/apps/server/prisma/schema.prisma index 09fa4057..6d08a66f 100644 --- a/apps/server/prisma/schema.prisma +++ b/apps/server/prisma/schema.prisma @@ -18,6 +18,11 @@ enum SignerType { USER_LIST } +enum EmployeeScope { + BASE_USER + ADMIN +} + // `Departments` represent the various departments that employees could work in. model Department { id String @id @default(uuid()) @db.Uuid @@ -39,7 +44,7 @@ model Employee { lastName String @db.VarChar(255) email String @unique @db.VarChar(255) signatureLink String @db.VarChar(255) - isAdmin Boolean @default(false) @db.Boolean + scope EmployeeScope @default(BASE_USER) // TODO @db tag pswdHash String? @db.VarChar(255) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/apps/server/prisma/seed.ts b/apps/server/prisma/seed.ts index 0eee0067..f918d3c5 100644 --- a/apps/server/prisma/seed.ts +++ b/apps/server/prisma/seed.ts @@ -1,4 +1,4 @@ -import { PrismaClient } from '@prisma/client'; +import { EmployeeScope, PrismaClient } from '@prisma/client'; import { v4 as uuidv4 } from 'uuid'; const prisma = new PrismaClient(); @@ -49,7 +49,7 @@ type EmployeeData = { email: string; positionId: string; signatureLink: string; - isAdmin: boolean; + scope: EmployeeScope; }; // update or insert employee to database based on the employee id @@ -66,7 +66,7 @@ async function upsertEmployee(empData: EmployeeData) { position: { connect: { id: empData.positionId }, }, - isAdmin: empData.isAdmin, + scope: empData.scope, }, }); } @@ -389,7 +389,7 @@ async function main() { email: 'zhang.iri@northeastern.edu', positionId: CHIEF_OF_STAFF_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, { id: KAI_ZHENG_UUID, @@ -398,7 +398,7 @@ async function main() { email: 'zheng.kaiy@northeastern.edu', positionId: CHIEF_FIN_OFFICER_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, { id: ANGELA_WEIGL_UUID, @@ -407,7 +407,7 @@ async function main() { email: 'weigl.a@northeastern.edu', positionId: AGG_DIR_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, { id: ANSHUL_SHIRUDE_UUID, @@ -416,7 +416,7 @@ async function main() { email: 'shirude.a@northeastern.edu', positionId: CHIEF_LEARNING_ENGAGEMENT_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, ]; diff --git a/apps/server/src/app.controller.ts b/apps/server/src/app.controller.ts index bb479eb3..8f48612c 100644 --- a/apps/server/src/app.controller.ts +++ b/apps/server/src/app.controller.ts @@ -135,7 +135,7 @@ export class AppController { password: employeeDto.password, signatureLink: employeeDto.signatureLink, positionId: '', - isAdmin: employeeDto.isAdmin, + scope: employeeDto.scope, }; const newEmployee = await this.authService.register( diff --git a/apps/server/src/auth/auth.service.spec.ts b/apps/server/src/auth/auth.service.spec.ts index 540b95e3..95bfab96 100644 --- a/apps/server/src/auth/auth.service.spec.ts +++ b/apps/server/src/auth/auth.service.spec.ts @@ -8,6 +8,7 @@ import { EmployeeEntity } from '../employees/entities/employee.entity'; import { PositionBaseEntity } from '../positions/entities/position.entity'; import { DepartmentsService } from '../departments/departments.service'; import { PositionsService } from '../positions/positions.service'; +import { EmployeeScope } from '@prisma/client'; describe('AuthService', () => { let service: AuthService; @@ -60,7 +61,7 @@ describe('AuthService', () => { updatedAt: new Date(1672531200), }, email: 'info@mfa.org', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'password', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -89,7 +90,7 @@ describe('AuthService', () => { updatedAt: new Date(1672531200), }, email: 'info@mfa.org', - isAdmin: false, + scope: EmployeeScope.BASE_USER, createdAt: new Date(1672531200), updatedAt: new Date(1672531200), refreshToken: null, @@ -147,7 +148,7 @@ describe('AuthService', () => { firstName: 'First', lastName: 'Last', positionId: 'position-id', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: null, createdAt: new Date(0), updatedAt: new Date(0), diff --git a/apps/server/src/auth/auth.service.ts b/apps/server/src/auth/auth.service.ts index f0ecc831..7decae5c 100644 --- a/apps/server/src/auth/auth.service.ts +++ b/apps/server/src/auth/auth.service.ts @@ -50,7 +50,7 @@ export class AuthService { sub: user.id, positionId: user.positionId, departmentId: user.position.departmentId, - isAdmin: user.isAdmin, + scope: user.scope, }; const [accessToken, refreshToken] = await Promise.all([ diff --git a/apps/server/src/auth/dto/register-employee.dto.ts b/apps/server/src/auth/dto/register-employee.dto.ts index 91463c73..7d50ffdd 100644 --- a/apps/server/src/auth/dto/register-employee.dto.ts +++ b/apps/server/src/auth/dto/register-employee.dto.ts @@ -1,11 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { - IsNotEmpty, - IsString, - MinLength, - IsEmail, - IsBoolean, -} from 'class-validator'; +import { EmployeeScope } from '@prisma/client'; +import { IsNotEmpty, IsString, MinLength, IsEmail } from 'class-validator'; export class RegisterEmployeeDto { @IsString() @@ -44,8 +39,8 @@ export class RegisterEmployeeDto { @ApiProperty() signatureLink: string; - @IsBoolean() + @IsString() @IsNotEmpty() @ApiProperty() - isAdmin: boolean; + scope: EmployeeScope; } diff --git a/apps/server/src/auth/guards/admin-auth.guard.ts b/apps/server/src/auth/guards/admin-auth.guard.ts index d75f4128..fe0e97dd 100644 --- a/apps/server/src/auth/guards/admin-auth.guard.ts +++ b/apps/server/src/auth/guards/admin-auth.guard.ts @@ -4,6 +4,7 @@ import { UnauthorizedException, } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; +import { EmployeeScope } from '@prisma/client'; import { Request } from 'express'; @Injectable() @@ -23,7 +24,7 @@ export class AdminAuthGuard extends AuthGuard('jwt') { handleRequest(err: any, user: any, info: any) { // You can throw an exception based on either "info" or "err" arguments - if (err || !user || !user.isAdmin) { + if (err || !user || !(user.scope == EmployeeScope.ADMIN)) { console.log(info); throw err || new UnauthorizedException(); } diff --git a/apps/server/src/employees/dto/create-employee.dto.ts b/apps/server/src/employees/dto/create-employee.dto.ts index 17ea039f..a72048dc 100644 --- a/apps/server/src/employees/dto/create-employee.dto.ts +++ b/apps/server/src/employees/dto/create-employee.dto.ts @@ -1,6 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; import { - IsBoolean, IsEmail, IsNotEmpty, IsString, @@ -40,8 +39,7 @@ export class CreateEmployeeDto { @ApiProperty() signatureLink: string; - @IsBoolean() @IsNotEmpty() @ApiProperty() - isAdmin: boolean; + scope: any; } diff --git a/apps/server/src/employees/employees.controller.spec.ts b/apps/server/src/employees/employees.controller.spec.ts index b5fa6fdc..b54661ea 100644 --- a/apps/server/src/employees/employees.controller.spec.ts +++ b/apps/server/src/employees/employees.controller.spec.ts @@ -4,6 +4,7 @@ import { EmployeesService } from './employees.service'; import { PrismaService } from '../prisma/prisma.service'; import { EmployeeEntity } from './entities/employee.entity'; import { LoggerServiceImpl } from '../logger/logger.service'; +import { EmployeeScope } from '@prisma/client'; describe('EmployeesController', () => { let controller: EmployeesController; @@ -47,7 +48,7 @@ describe('EmployeesController', () => { }, }, email: 'john.doe@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -74,7 +75,7 @@ describe('EmployeesController', () => { }, }, email: 'bilbo.baggins@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -104,7 +105,7 @@ describe('EmployeesController', () => { }, }, email: 'john.doe@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -131,7 +132,7 @@ describe('EmployeesController', () => { }, }, email: 'bilbo.baggins@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), diff --git a/apps/server/src/employees/employees.service.ts b/apps/server/src/employees/employees.service.ts index 30254f8e..6e5f457f 100644 --- a/apps/server/src/employees/employees.service.ts +++ b/apps/server/src/employees/employees.service.ts @@ -25,7 +25,7 @@ export class EmployeesService { createEmployeeDto.password, await bcrypt.genSalt(), ), - isAdmin: createEmployeeDto.isAdmin, + scope: createEmployeeDto.scope, }, include: { position: { diff --git a/apps/server/src/employees/entities/employee.entity.ts b/apps/server/src/employees/entities/employee.entity.ts index 227fc3e6..7137b9ce 100644 --- a/apps/server/src/employees/entities/employee.entity.ts +++ b/apps/server/src/employees/entities/employee.entity.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { Employee } from '@prisma/client'; +import { Employee, EmployeeScope } from '@prisma/client'; import { PositionBaseEntity } from './../../positions/entities/position.entity'; import { Exclude } from 'class-transformer'; @@ -20,10 +20,10 @@ export class EmployeeBaseEntity implements Employee { email: string; @ApiProperty() - isAdmin: boolean; + signatureLink: string; @ApiProperty() - signatureLink: string; + scope: EmployeeScope; @Exclude() pswdHash: string | null; diff --git a/apps/server/src/metadata.ts b/apps/server/src/metadata.ts index 31725647..24609201 100644 --- a/apps/server/src/metadata.ts +++ b/apps/server/src/metadata.ts @@ -1,3 +1,5 @@ +import { EmployeeScope } from '@prisma/client'; + /* eslint-disable */ export default async () => { const t = { @@ -107,7 +109,7 @@ export default async () => { positionId: { required: true, type: () => String }, email: { required: true, type: () => String }, password: { required: true, type: () => String, minLength: 5 }, - isAdmin: { required: true, type: () => Boolean }, + scope: { required: true, type: () => EmployeeScope }, }, }, ], diff --git a/apps/web/src/client/models/CreateEmployeeDto.ts b/apps/web/src/client/models/CreateEmployeeDto.ts index bf077091..522abba9 100644 --- a/apps/web/src/client/models/CreateEmployeeDto.ts +++ b/apps/web/src/client/models/CreateEmployeeDto.ts @@ -10,6 +10,6 @@ export type CreateEmployeeDto = { email: string; password: string; signatureLink: string; - isAdmin: boolean; + scope: Record; }; diff --git a/apps/web/src/client/models/EmployeeBaseEntity.ts b/apps/web/src/client/models/EmployeeBaseEntity.ts index 2b2929f0..e2903d53 100644 --- a/apps/web/src/client/models/EmployeeBaseEntity.ts +++ b/apps/web/src/client/models/EmployeeBaseEntity.ts @@ -8,8 +8,8 @@ export type EmployeeBaseEntity = { firstName: string; lastName: string; email: string; - isAdmin: boolean; signatureLink: string; + scope: Record; positionId: string; pswdHash: string | null; createdAt: string; diff --git a/apps/web/src/client/models/EmployeeEntity.ts b/apps/web/src/client/models/EmployeeEntity.ts index 31b406b8..eb563a4c 100644 --- a/apps/web/src/client/models/EmployeeEntity.ts +++ b/apps/web/src/client/models/EmployeeEntity.ts @@ -10,8 +10,8 @@ export type EmployeeEntity = { firstName: string; lastName: string; email: string; - isAdmin: boolean; signatureLink: string; + scope: Record; position: PositionBaseEntity; positionId: string; pswdHash: string | null; diff --git a/apps/web/src/client/models/RegisterEmployeeDto.ts b/apps/web/src/client/models/RegisterEmployeeDto.ts index e59989c6..9b756239 100644 --- a/apps/web/src/client/models/RegisterEmployeeDto.ts +++ b/apps/web/src/client/models/RegisterEmployeeDto.ts @@ -11,5 +11,6 @@ export type RegisterEmployeeDto = { positionName: string; departmentName: string; signatureLink: string; + scope: Record; }; diff --git a/apps/web/src/client/models/UpdateEmployeeDto.ts b/apps/web/src/client/models/UpdateEmployeeDto.ts index 49d78104..6ccbd431 100644 --- a/apps/web/src/client/models/UpdateEmployeeDto.ts +++ b/apps/web/src/client/models/UpdateEmployeeDto.ts @@ -8,5 +8,6 @@ export type UpdateEmployeeDto = { lastName?: string; positionId?: string; signatureLink?: string; + scope?: Record; }; diff --git a/apps/web/src/context/AuthContext.tsx b/apps/web/src/context/AuthContext.tsx index 554cb249..21160f86 100644 --- a/apps/web/src/context/AuthContext.tsx +++ b/apps/web/src/context/AuthContext.tsx @@ -13,6 +13,8 @@ import { loginRequest } from '@web/authConfig'; import { callMsGraph } from '@web/graph'; import { useMutation } from '@tanstack/react-query'; import { RegisterEmployeeDto } from '@web/client'; +import { EmployeeScope } from '@prisma/client'; + // Reference: https://blog.finiam.com/blog/predictable-react-authentication-with-the-context-api export const AuthContext = createContext( @@ -54,7 +56,7 @@ export const AuthProvider = ({ children }: any) => { email: decoded.email, firstName: decoded.firstName, lastName: decoded.lastName, - isAdmin: decoded.isAdmin, + scope: decoded.scope, }; setUser(user); @@ -89,7 +91,7 @@ export const AuthProvider = ({ children }: any) => { email: employee.email, firstName: employee.firstName, lastName: employee.lastName, - isAdmin: employee.isAdmin, + scope: EmployeeScope.BASE_USER, }); }) .catch(async (_error) => { @@ -194,6 +196,7 @@ export const AuthProvider = ({ children }: any) => { departmentName: department, positionName: position, signatureLink: signatureLink, + scope: EmployeeScope, }; registerEmployeeMutation.mutate(employee, { diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index c26361c8..4dcd726d 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -3,6 +3,7 @@ import { FormFields, FieldGroups, } from '@web/components/createFormTemplate/createFormTemplateEditor/FormEditor'; +import { EmployeeScope } from '@prisma/client'; // for storage in context export type User = { @@ -12,7 +13,7 @@ export type User = { email: string; firstName: string; lastName: string; - isAdmin: boolean; + scope: EmployeeScope; }; // jwt payload returned from server export type jwtPayload = { @@ -22,7 +23,7 @@ export type jwtPayload = { email: string; firstName: string; lastName: string; - isAdmin: boolean; + scope: EmployeeScope; }; export interface AuthContextType { From 0cbc900c7bf549d7fe12adfda741f9d16617d192 Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Sun, 2 Feb 2025 21:54:07 -0500 Subject: [PATCH 03/13] create migration for employee scope field --- .../migration.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql diff --git a/apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql b/apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql new file mode 100644 index 00000000..b329601b --- /dev/null +++ b/apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `isAdmin` on the `Employee` table. All the data in the column will be lost. + +*/ +-- CreateEnum +CREATE TYPE "EmployeeScope" AS ENUM ('BASE_USER', 'ADMIN'); + +-- AlterTable +ALTER TABLE "Employee" DROP COLUMN "isAdmin", +ADD COLUMN "scope" "EmployeeScope" NOT NULL DEFAULT 'BASE_USER'; From bb336294abb04dfa1cb219810cbc9c9d5e8a5957 Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:00:34 -0500 Subject: [PATCH 04/13] add scope to completeRegistration signature --- apps/web/src/context/AuthContext.tsx | 3 ++- apps/web/src/context/types.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/context/AuthContext.tsx b/apps/web/src/context/AuthContext.tsx index 21160f86..b35fbef4 100644 --- a/apps/web/src/context/AuthContext.tsx +++ b/apps/web/src/context/AuthContext.tsx @@ -187,6 +187,7 @@ export const AuthProvider = ({ children }: any) => { position: string, department: string, signatureLink: string, + scope: EmployeeScope, ) => { const employee: RegisterEmployeeDto = { email: email, @@ -196,7 +197,7 @@ export const AuthProvider = ({ children }: any) => { departmentName: department, positionName: position, signatureLink: signatureLink, - scope: EmployeeScope, + scope: scope.valueOf, // Record }; registerEmployeeMutation.mutate(employee, { diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index 4dcd726d..a6a7f783 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -39,6 +39,7 @@ export interface AuthContextType { position: string, department: string, signatureLink: string, + scope: EmployeeScope ) => void; logout: () => void; } From 21af3ec640cbd235bda6d052904edeeb63a5ffea Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:23:50 -0500 Subject: [PATCH 05/13] fix format and tsc checks --- apps/web/src/context/types.ts | 2 +- apps/web/src/pages/register.tsx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index a6a7f783..fd3788ab 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -39,7 +39,7 @@ export interface AuthContextType { position: string, department: string, signatureLink: string, - scope: EmployeeScope + scope: EmployeeScope, ) => void; logout: () => void; } diff --git a/apps/web/src/pages/register.tsx b/apps/web/src/pages/register.tsx index 16e1ae9b..39c9b3a6 100644 --- a/apps/web/src/pages/register.tsx +++ b/apps/web/src/pages/register.tsx @@ -7,6 +7,7 @@ import { useAuth } from '@web/hooks/useAuth'; import { useQuery } from '@tanstack/react-query'; import { useBlob } from '@web/hooks/useBlob'; import { SignaturePad } from './../components/SignaturePad'; +import { EmployeeScope } from '@prisma/client'; export default function Register() { const { completeRegistration, userData } = useAuth(); @@ -106,6 +107,7 @@ export default function Register() { currentDepartmentName, currentPositionName, uploadedBlob?.url || 'http://localhost:3002/signature.png', + EmployeeScope.BASE_USER, ); }; From 99b7afacefa74b3cbbc7cb43024913627d303f0d Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Sat, 25 Jan 2025 16:09:19 -0500 Subject: [PATCH 06/13] add employee field throughout files Co-authored-by: Gayatri Kondabathini --- apps/server/prisma/seed.ts | 6 ++++++ apps/server/src/app.controller.ts | 1 + apps/server/src/auth/dto/register-employee.dto.ts | 13 ++++++++++++- .../server/src/employees/dto/create-employee.dto.ts | 6 ++++++ apps/server/src/employees/employees.service.ts | 1 + apps/server/src/metadata.ts | 1 + apps/web/src/client/models/CreateEmployeeDto.ts | 1 + 7 files changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/server/prisma/seed.ts b/apps/server/prisma/seed.ts index 3c2666d7..0eee0067 100644 --- a/apps/server/prisma/seed.ts +++ b/apps/server/prisma/seed.ts @@ -49,6 +49,7 @@ type EmployeeData = { email: string; positionId: string; signatureLink: string; + isAdmin: boolean; }; // update or insert employee to database based on the employee id @@ -65,6 +66,7 @@ async function upsertEmployee(empData: EmployeeData) { position: { connect: { id: empData.positionId }, }, + isAdmin: empData.isAdmin, }, }); } @@ -387,6 +389,7 @@ async function main() { email: 'zhang.iri@northeastern.edu', positionId: CHIEF_OF_STAFF_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, { id: KAI_ZHENG_UUID, @@ -395,6 +398,7 @@ async function main() { email: 'zheng.kaiy@northeastern.edu', positionId: CHIEF_FIN_OFFICER_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, { id: ANGELA_WEIGL_UUID, @@ -403,6 +407,7 @@ async function main() { email: 'weigl.a@northeastern.edu', positionId: AGG_DIR_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, { id: ANSHUL_SHIRUDE_UUID, @@ -411,6 +416,7 @@ async function main() { email: 'shirude.a@northeastern.edu', positionId: CHIEF_LEARNING_ENGAGEMENT_UUID, signatureLink: DEV_SIGNATURE_LINK, + isAdmin: true, }, ]; diff --git a/apps/server/src/app.controller.ts b/apps/server/src/app.controller.ts index 9a141f3d..bb479eb3 100644 --- a/apps/server/src/app.controller.ts +++ b/apps/server/src/app.controller.ts @@ -135,6 +135,7 @@ export class AppController { password: employeeDto.password, signatureLink: employeeDto.signatureLink, positionId: '', + isAdmin: employeeDto.isAdmin, }; const newEmployee = await this.authService.register( diff --git a/apps/server/src/auth/dto/register-employee.dto.ts b/apps/server/src/auth/dto/register-employee.dto.ts index c742ad41..91463c73 100644 --- a/apps/server/src/auth/dto/register-employee.dto.ts +++ b/apps/server/src/auth/dto/register-employee.dto.ts @@ -1,5 +1,11 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsString, MinLength, IsEmail } from 'class-validator'; +import { + IsNotEmpty, + IsString, + MinLength, + IsEmail, + IsBoolean, +} from 'class-validator'; export class RegisterEmployeeDto { @IsString() @@ -37,4 +43,9 @@ export class RegisterEmployeeDto { @IsNotEmpty() @ApiProperty() signatureLink: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty() + isAdmin: boolean; } diff --git a/apps/server/src/employees/dto/create-employee.dto.ts b/apps/server/src/employees/dto/create-employee.dto.ts index 8f705560..17ea039f 100644 --- a/apps/server/src/employees/dto/create-employee.dto.ts +++ b/apps/server/src/employees/dto/create-employee.dto.ts @@ -1,5 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { + IsBoolean, IsEmail, IsNotEmpty, IsString, @@ -38,4 +39,9 @@ export class CreateEmployeeDto { @IsNotEmpty() @ApiProperty() signatureLink: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty() + isAdmin: boolean; } diff --git a/apps/server/src/employees/employees.service.ts b/apps/server/src/employees/employees.service.ts index b888e54d..30254f8e 100644 --- a/apps/server/src/employees/employees.service.ts +++ b/apps/server/src/employees/employees.service.ts @@ -25,6 +25,7 @@ export class EmployeesService { createEmployeeDto.password, await bcrypt.genSalt(), ), + isAdmin: createEmployeeDto.isAdmin, }, include: { position: { diff --git a/apps/server/src/metadata.ts b/apps/server/src/metadata.ts index 7b8a176a..31725647 100644 --- a/apps/server/src/metadata.ts +++ b/apps/server/src/metadata.ts @@ -107,6 +107,7 @@ export default async () => { positionId: { required: true, type: () => String }, email: { required: true, type: () => String }, password: { required: true, type: () => String, minLength: 5 }, + isAdmin: { required: true, type: () => Boolean }, }, }, ], diff --git a/apps/web/src/client/models/CreateEmployeeDto.ts b/apps/web/src/client/models/CreateEmployeeDto.ts index 8cc762d1..bf077091 100644 --- a/apps/web/src/client/models/CreateEmployeeDto.ts +++ b/apps/web/src/client/models/CreateEmployeeDto.ts @@ -10,5 +10,6 @@ export type CreateEmployeeDto = { email: string; password: string; signatureLink: string; + isAdmin: boolean; }; From f341f4903a05c9d9212a765eb21302e9de30e062 Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Sun, 2 Feb 2025 21:27:03 -0500 Subject: [PATCH 07/13] replace isAdmin with scope --- apps/server/prisma/schema.prisma | 7 ++++++- apps/server/prisma/seed.ts | 14 +++++++------- apps/server/src/app.controller.ts | 2 +- apps/server/src/auth/auth.service.spec.ts | 7 ++++--- apps/server/src/auth/auth.service.ts | 2 +- apps/server/src/auth/dto/register-employee.dto.ts | 13 ++++--------- apps/server/src/auth/guards/admin-auth.guard.ts | 3 ++- .../src/employees/dto/create-employee.dto.ts | 4 +--- .../src/employees/employees.controller.spec.ts | 9 +++++---- apps/server/src/employees/employees.service.ts | 2 +- .../src/employees/entities/employee.entity.ts | 6 +++--- apps/server/src/metadata.ts | 4 +++- apps/web/src/client/models/CreateEmployeeDto.ts | 2 +- apps/web/src/client/models/EmployeeBaseEntity.ts | 2 +- apps/web/src/client/models/EmployeeEntity.ts | 2 +- apps/web/src/client/models/RegisterEmployeeDto.ts | 1 + apps/web/src/client/models/UpdateEmployeeDto.ts | 1 + apps/web/src/context/AuthContext.tsx | 7 +++++-- apps/web/src/context/types.ts | 5 +++-- 19 files changed, 51 insertions(+), 42 deletions(-) diff --git a/apps/server/prisma/schema.prisma b/apps/server/prisma/schema.prisma index 09fa4057..6d08a66f 100644 --- a/apps/server/prisma/schema.prisma +++ b/apps/server/prisma/schema.prisma @@ -18,6 +18,11 @@ enum SignerType { USER_LIST } +enum EmployeeScope { + BASE_USER + ADMIN +} + // `Departments` represent the various departments that employees could work in. model Department { id String @id @default(uuid()) @db.Uuid @@ -39,7 +44,7 @@ model Employee { lastName String @db.VarChar(255) email String @unique @db.VarChar(255) signatureLink String @db.VarChar(255) - isAdmin Boolean @default(false) @db.Boolean + scope EmployeeScope @default(BASE_USER) // TODO @db tag pswdHash String? @db.VarChar(255) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/apps/server/prisma/seed.ts b/apps/server/prisma/seed.ts index 0eee0067..f918d3c5 100644 --- a/apps/server/prisma/seed.ts +++ b/apps/server/prisma/seed.ts @@ -1,4 +1,4 @@ -import { PrismaClient } from '@prisma/client'; +import { EmployeeScope, PrismaClient } from '@prisma/client'; import { v4 as uuidv4 } from 'uuid'; const prisma = new PrismaClient(); @@ -49,7 +49,7 @@ type EmployeeData = { email: string; positionId: string; signatureLink: string; - isAdmin: boolean; + scope: EmployeeScope; }; // update or insert employee to database based on the employee id @@ -66,7 +66,7 @@ async function upsertEmployee(empData: EmployeeData) { position: { connect: { id: empData.positionId }, }, - isAdmin: empData.isAdmin, + scope: empData.scope, }, }); } @@ -389,7 +389,7 @@ async function main() { email: 'zhang.iri@northeastern.edu', positionId: CHIEF_OF_STAFF_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, { id: KAI_ZHENG_UUID, @@ -398,7 +398,7 @@ async function main() { email: 'zheng.kaiy@northeastern.edu', positionId: CHIEF_FIN_OFFICER_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, { id: ANGELA_WEIGL_UUID, @@ -407,7 +407,7 @@ async function main() { email: 'weigl.a@northeastern.edu', positionId: AGG_DIR_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, { id: ANSHUL_SHIRUDE_UUID, @@ -416,7 +416,7 @@ async function main() { email: 'shirude.a@northeastern.edu', positionId: CHIEF_LEARNING_ENGAGEMENT_UUID, signatureLink: DEV_SIGNATURE_LINK, - isAdmin: true, + scope: EmployeeScope.BASE_USER, }, ]; diff --git a/apps/server/src/app.controller.ts b/apps/server/src/app.controller.ts index bb479eb3..8f48612c 100644 --- a/apps/server/src/app.controller.ts +++ b/apps/server/src/app.controller.ts @@ -135,7 +135,7 @@ export class AppController { password: employeeDto.password, signatureLink: employeeDto.signatureLink, positionId: '', - isAdmin: employeeDto.isAdmin, + scope: employeeDto.scope, }; const newEmployee = await this.authService.register( diff --git a/apps/server/src/auth/auth.service.spec.ts b/apps/server/src/auth/auth.service.spec.ts index 540b95e3..95bfab96 100644 --- a/apps/server/src/auth/auth.service.spec.ts +++ b/apps/server/src/auth/auth.service.spec.ts @@ -8,6 +8,7 @@ import { EmployeeEntity } from '../employees/entities/employee.entity'; import { PositionBaseEntity } from '../positions/entities/position.entity'; import { DepartmentsService } from '../departments/departments.service'; import { PositionsService } from '../positions/positions.service'; +import { EmployeeScope } from '@prisma/client'; describe('AuthService', () => { let service: AuthService; @@ -60,7 +61,7 @@ describe('AuthService', () => { updatedAt: new Date(1672531200), }, email: 'info@mfa.org', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'password', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -89,7 +90,7 @@ describe('AuthService', () => { updatedAt: new Date(1672531200), }, email: 'info@mfa.org', - isAdmin: false, + scope: EmployeeScope.BASE_USER, createdAt: new Date(1672531200), updatedAt: new Date(1672531200), refreshToken: null, @@ -147,7 +148,7 @@ describe('AuthService', () => { firstName: 'First', lastName: 'Last', positionId: 'position-id', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: null, createdAt: new Date(0), updatedAt: new Date(0), diff --git a/apps/server/src/auth/auth.service.ts b/apps/server/src/auth/auth.service.ts index f0ecc831..7decae5c 100644 --- a/apps/server/src/auth/auth.service.ts +++ b/apps/server/src/auth/auth.service.ts @@ -50,7 +50,7 @@ export class AuthService { sub: user.id, positionId: user.positionId, departmentId: user.position.departmentId, - isAdmin: user.isAdmin, + scope: user.scope, }; const [accessToken, refreshToken] = await Promise.all([ diff --git a/apps/server/src/auth/dto/register-employee.dto.ts b/apps/server/src/auth/dto/register-employee.dto.ts index 91463c73..7d50ffdd 100644 --- a/apps/server/src/auth/dto/register-employee.dto.ts +++ b/apps/server/src/auth/dto/register-employee.dto.ts @@ -1,11 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { - IsNotEmpty, - IsString, - MinLength, - IsEmail, - IsBoolean, -} from 'class-validator'; +import { EmployeeScope } from '@prisma/client'; +import { IsNotEmpty, IsString, MinLength, IsEmail } from 'class-validator'; export class RegisterEmployeeDto { @IsString() @@ -44,8 +39,8 @@ export class RegisterEmployeeDto { @ApiProperty() signatureLink: string; - @IsBoolean() + @IsString() @IsNotEmpty() @ApiProperty() - isAdmin: boolean; + scope: EmployeeScope; } diff --git a/apps/server/src/auth/guards/admin-auth.guard.ts b/apps/server/src/auth/guards/admin-auth.guard.ts index d75f4128..fe0e97dd 100644 --- a/apps/server/src/auth/guards/admin-auth.guard.ts +++ b/apps/server/src/auth/guards/admin-auth.guard.ts @@ -4,6 +4,7 @@ import { UnauthorizedException, } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; +import { EmployeeScope } from '@prisma/client'; import { Request } from 'express'; @Injectable() @@ -23,7 +24,7 @@ export class AdminAuthGuard extends AuthGuard('jwt') { handleRequest(err: any, user: any, info: any) { // You can throw an exception based on either "info" or "err" arguments - if (err || !user || !user.isAdmin) { + if (err || !user || !(user.scope == EmployeeScope.ADMIN)) { console.log(info); throw err || new UnauthorizedException(); } diff --git a/apps/server/src/employees/dto/create-employee.dto.ts b/apps/server/src/employees/dto/create-employee.dto.ts index 17ea039f..a72048dc 100644 --- a/apps/server/src/employees/dto/create-employee.dto.ts +++ b/apps/server/src/employees/dto/create-employee.dto.ts @@ -1,6 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; import { - IsBoolean, IsEmail, IsNotEmpty, IsString, @@ -40,8 +39,7 @@ export class CreateEmployeeDto { @ApiProperty() signatureLink: string; - @IsBoolean() @IsNotEmpty() @ApiProperty() - isAdmin: boolean; + scope: any; } diff --git a/apps/server/src/employees/employees.controller.spec.ts b/apps/server/src/employees/employees.controller.spec.ts index b5fa6fdc..b54661ea 100644 --- a/apps/server/src/employees/employees.controller.spec.ts +++ b/apps/server/src/employees/employees.controller.spec.ts @@ -4,6 +4,7 @@ import { EmployeesService } from './employees.service'; import { PrismaService } from '../prisma/prisma.service'; import { EmployeeEntity } from './entities/employee.entity'; import { LoggerServiceImpl } from '../logger/logger.service'; +import { EmployeeScope } from '@prisma/client'; describe('EmployeesController', () => { let controller: EmployeesController; @@ -47,7 +48,7 @@ describe('EmployeesController', () => { }, }, email: 'john.doe@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -74,7 +75,7 @@ describe('EmployeesController', () => { }, }, email: 'bilbo.baggins@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -104,7 +105,7 @@ describe('EmployeesController', () => { }, }, email: 'john.doe@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), @@ -131,7 +132,7 @@ describe('EmployeesController', () => { }, }, email: 'bilbo.baggins@example.com', - isAdmin: false, + scope: EmployeeScope.BASE_USER, pswdHash: 'thisIsASecureHash', createdAt: new Date(1672531200), updatedAt: new Date(1672531200), diff --git a/apps/server/src/employees/employees.service.ts b/apps/server/src/employees/employees.service.ts index 30254f8e..6e5f457f 100644 --- a/apps/server/src/employees/employees.service.ts +++ b/apps/server/src/employees/employees.service.ts @@ -25,7 +25,7 @@ export class EmployeesService { createEmployeeDto.password, await bcrypt.genSalt(), ), - isAdmin: createEmployeeDto.isAdmin, + scope: createEmployeeDto.scope, }, include: { position: { diff --git a/apps/server/src/employees/entities/employee.entity.ts b/apps/server/src/employees/entities/employee.entity.ts index 227fc3e6..7137b9ce 100644 --- a/apps/server/src/employees/entities/employee.entity.ts +++ b/apps/server/src/employees/entities/employee.entity.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { Employee } from '@prisma/client'; +import { Employee, EmployeeScope } from '@prisma/client'; import { PositionBaseEntity } from './../../positions/entities/position.entity'; import { Exclude } from 'class-transformer'; @@ -20,10 +20,10 @@ export class EmployeeBaseEntity implements Employee { email: string; @ApiProperty() - isAdmin: boolean; + signatureLink: string; @ApiProperty() - signatureLink: string; + scope: EmployeeScope; @Exclude() pswdHash: string | null; diff --git a/apps/server/src/metadata.ts b/apps/server/src/metadata.ts index 31725647..24609201 100644 --- a/apps/server/src/metadata.ts +++ b/apps/server/src/metadata.ts @@ -1,3 +1,5 @@ +import { EmployeeScope } from '@prisma/client'; + /* eslint-disable */ export default async () => { const t = { @@ -107,7 +109,7 @@ export default async () => { positionId: { required: true, type: () => String }, email: { required: true, type: () => String }, password: { required: true, type: () => String, minLength: 5 }, - isAdmin: { required: true, type: () => Boolean }, + scope: { required: true, type: () => EmployeeScope }, }, }, ], diff --git a/apps/web/src/client/models/CreateEmployeeDto.ts b/apps/web/src/client/models/CreateEmployeeDto.ts index bf077091..522abba9 100644 --- a/apps/web/src/client/models/CreateEmployeeDto.ts +++ b/apps/web/src/client/models/CreateEmployeeDto.ts @@ -10,6 +10,6 @@ export type CreateEmployeeDto = { email: string; password: string; signatureLink: string; - isAdmin: boolean; + scope: Record; }; diff --git a/apps/web/src/client/models/EmployeeBaseEntity.ts b/apps/web/src/client/models/EmployeeBaseEntity.ts index 2b2929f0..e2903d53 100644 --- a/apps/web/src/client/models/EmployeeBaseEntity.ts +++ b/apps/web/src/client/models/EmployeeBaseEntity.ts @@ -8,8 +8,8 @@ export type EmployeeBaseEntity = { firstName: string; lastName: string; email: string; - isAdmin: boolean; signatureLink: string; + scope: Record; positionId: string; pswdHash: string | null; createdAt: string; diff --git a/apps/web/src/client/models/EmployeeEntity.ts b/apps/web/src/client/models/EmployeeEntity.ts index 31b406b8..eb563a4c 100644 --- a/apps/web/src/client/models/EmployeeEntity.ts +++ b/apps/web/src/client/models/EmployeeEntity.ts @@ -10,8 +10,8 @@ export type EmployeeEntity = { firstName: string; lastName: string; email: string; - isAdmin: boolean; signatureLink: string; + scope: Record; position: PositionBaseEntity; positionId: string; pswdHash: string | null; diff --git a/apps/web/src/client/models/RegisterEmployeeDto.ts b/apps/web/src/client/models/RegisterEmployeeDto.ts index e59989c6..9b756239 100644 --- a/apps/web/src/client/models/RegisterEmployeeDto.ts +++ b/apps/web/src/client/models/RegisterEmployeeDto.ts @@ -11,5 +11,6 @@ export type RegisterEmployeeDto = { positionName: string; departmentName: string; signatureLink: string; + scope: Record; }; diff --git a/apps/web/src/client/models/UpdateEmployeeDto.ts b/apps/web/src/client/models/UpdateEmployeeDto.ts index 49d78104..6ccbd431 100644 --- a/apps/web/src/client/models/UpdateEmployeeDto.ts +++ b/apps/web/src/client/models/UpdateEmployeeDto.ts @@ -8,5 +8,6 @@ export type UpdateEmployeeDto = { lastName?: string; positionId?: string; signatureLink?: string; + scope?: Record; }; diff --git a/apps/web/src/context/AuthContext.tsx b/apps/web/src/context/AuthContext.tsx index 554cb249..21160f86 100644 --- a/apps/web/src/context/AuthContext.tsx +++ b/apps/web/src/context/AuthContext.tsx @@ -13,6 +13,8 @@ import { loginRequest } from '@web/authConfig'; import { callMsGraph } from '@web/graph'; import { useMutation } from '@tanstack/react-query'; import { RegisterEmployeeDto } from '@web/client'; +import { EmployeeScope } from '@prisma/client'; + // Reference: https://blog.finiam.com/blog/predictable-react-authentication-with-the-context-api export const AuthContext = createContext( @@ -54,7 +56,7 @@ export const AuthProvider = ({ children }: any) => { email: decoded.email, firstName: decoded.firstName, lastName: decoded.lastName, - isAdmin: decoded.isAdmin, + scope: decoded.scope, }; setUser(user); @@ -89,7 +91,7 @@ export const AuthProvider = ({ children }: any) => { email: employee.email, firstName: employee.firstName, lastName: employee.lastName, - isAdmin: employee.isAdmin, + scope: EmployeeScope.BASE_USER, }); }) .catch(async (_error) => { @@ -194,6 +196,7 @@ export const AuthProvider = ({ children }: any) => { departmentName: department, positionName: position, signatureLink: signatureLink, + scope: EmployeeScope, }; registerEmployeeMutation.mutate(employee, { diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index c26361c8..4dcd726d 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -3,6 +3,7 @@ import { FormFields, FieldGroups, } from '@web/components/createFormTemplate/createFormTemplateEditor/FormEditor'; +import { EmployeeScope } from '@prisma/client'; // for storage in context export type User = { @@ -12,7 +13,7 @@ export type User = { email: string; firstName: string; lastName: string; - isAdmin: boolean; + scope: EmployeeScope; }; // jwt payload returned from server export type jwtPayload = { @@ -22,7 +23,7 @@ export type jwtPayload = { email: string; firstName: string; lastName: string; - isAdmin: boolean; + scope: EmployeeScope; }; export interface AuthContextType { From fac877d4c6a7f39b37aba8de44c83b113ee23277 Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Sun, 2 Feb 2025 21:54:07 -0500 Subject: [PATCH 08/13] create migration for employee scope field --- .../migration.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql diff --git a/apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql b/apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql new file mode 100644 index 00000000..b329601b --- /dev/null +++ b/apps/server/prisma/migrations/20250203024748_add_user_scope_field/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `isAdmin` on the `Employee` table. All the data in the column will be lost. + +*/ +-- CreateEnum +CREATE TYPE "EmployeeScope" AS ENUM ('BASE_USER', 'ADMIN'); + +-- AlterTable +ALTER TABLE "Employee" DROP COLUMN "isAdmin", +ADD COLUMN "scope" "EmployeeScope" NOT NULL DEFAULT 'BASE_USER'; From fd1ae143d24f0b4df857900dbac3008c2412804b Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:00:34 -0500 Subject: [PATCH 09/13] add scope to completeRegistration signature --- apps/web/src/context/AuthContext.tsx | 3 ++- apps/web/src/context/types.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/context/AuthContext.tsx b/apps/web/src/context/AuthContext.tsx index 21160f86..b35fbef4 100644 --- a/apps/web/src/context/AuthContext.tsx +++ b/apps/web/src/context/AuthContext.tsx @@ -187,6 +187,7 @@ export const AuthProvider = ({ children }: any) => { position: string, department: string, signatureLink: string, + scope: EmployeeScope, ) => { const employee: RegisterEmployeeDto = { email: email, @@ -196,7 +197,7 @@ export const AuthProvider = ({ children }: any) => { departmentName: department, positionName: position, signatureLink: signatureLink, - scope: EmployeeScope, + scope: scope.valueOf, // Record }; registerEmployeeMutation.mutate(employee, { diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index 4dcd726d..a6a7f783 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -39,6 +39,7 @@ export interface AuthContextType { position: string, department: string, signatureLink: string, + scope: EmployeeScope ) => void; logout: () => void; } From a1ccbdd238e15770484b5342e2be7b152beba3e3 Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:23:50 -0500 Subject: [PATCH 10/13] fix format and tsc checks --- apps/web/src/context/types.ts | 2 +- apps/web/src/pages/register.tsx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index a6a7f783..fd3788ab 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -39,7 +39,7 @@ export interface AuthContextType { position: string, department: string, signatureLink: string, - scope: EmployeeScope + scope: EmployeeScope, ) => void; logout: () => void; } diff --git a/apps/web/src/pages/register.tsx b/apps/web/src/pages/register.tsx index 16e1ae9b..39c9b3a6 100644 --- a/apps/web/src/pages/register.tsx +++ b/apps/web/src/pages/register.tsx @@ -7,6 +7,7 @@ import { useAuth } from '@web/hooks/useAuth'; import { useQuery } from '@tanstack/react-query'; import { useBlob } from '@web/hooks/useBlob'; import { SignaturePad } from './../components/SignaturePad'; +import { EmployeeScope } from '@prisma/client'; export default function Register() { const { completeRegistration, userData } = useAuth(); @@ -106,6 +107,7 @@ export default function Register() { currentDepartmentName, currentPositionName, uploadedBlob?.url || 'http://localhost:3002/signature.png', + EmployeeScope.BASE_USER, ); }; From 980a5adfad841f3163fe0b0d9837ddb61c6ac7e1 Mon Sep 17 00:00:00 2001 From: Lauren Brissette <168485735+laurenbrissette@users.noreply.github.com> Date: Sat, 8 Feb 2025 16:12:13 -0500 Subject: [PATCH 11/13] change api properties to enum and update completeRegistration signature --- .../src/auth/dto/register-employee.dto.ts | 3 +-- .../src/employees/dto/create-employee.dto.ts | 5 ++-- .../src/employees/entities/employee.entity.ts | 2 +- .../signatures/signatures.controller.spec.ts | 4 +-- .../src/signatures/signatures.service.spec.ts | 14 +++++----- .../src/signatures/signatures.service.ts | 2 +- apps/web/src/client/index.ts | 11 ++++---- .../src/client/models/CreateEmployeeDto.ts | 12 ++++++++- .../src/client/models/EmployeeBaseEntity.ts | 12 ++++++++- apps/web/src/client/models/EmployeeEntity.ts | 12 ++++++++- .../src/client/models/RegisterEmployeeDto.ts | 12 ++++++++- .../src/client/models/UpdateEmployeeDto.ts | 12 ++++++++- .../client/models/UpdateSignatureSignerDto.ts | 27 +++++++++++++++++++ .../web/src/client/services/DefaultService.ts | 22 +++++++++++++++ apps/web/src/context/AuthContext.tsx | 4 +-- apps/web/src/context/types.ts | 3 ++- apps/web/src/pages/register.tsx | 8 ++++-- 17 files changed, 135 insertions(+), 30 deletions(-) create mode 100644 apps/web/src/client/models/UpdateSignatureSignerDto.ts diff --git a/apps/server/src/auth/dto/register-employee.dto.ts b/apps/server/src/auth/dto/register-employee.dto.ts index 7d50ffdd..9c5619da 100644 --- a/apps/server/src/auth/dto/register-employee.dto.ts +++ b/apps/server/src/auth/dto/register-employee.dto.ts @@ -39,8 +39,7 @@ export class RegisterEmployeeDto { @ApiProperty() signatureLink: string; - @IsString() @IsNotEmpty() - @ApiProperty() + @ApiProperty({ enum: EmployeeScope }) scope: EmployeeScope; } diff --git a/apps/server/src/employees/dto/create-employee.dto.ts b/apps/server/src/employees/dto/create-employee.dto.ts index a72048dc..48035749 100644 --- a/apps/server/src/employees/dto/create-employee.dto.ts +++ b/apps/server/src/employees/dto/create-employee.dto.ts @@ -1,4 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; +import { EmployeeScope } from '@prisma/client'; import { IsEmail, IsNotEmpty, @@ -40,6 +41,6 @@ export class CreateEmployeeDto { signatureLink: string; @IsNotEmpty() - @ApiProperty() - scope: any; + @ApiProperty({ enum: EmployeeScope }) + scope: EmployeeScope; } diff --git a/apps/server/src/employees/entities/employee.entity.ts b/apps/server/src/employees/entities/employee.entity.ts index 7137b9ce..8ea65a4f 100644 --- a/apps/server/src/employees/entities/employee.entity.ts +++ b/apps/server/src/employees/entities/employee.entity.ts @@ -22,7 +22,7 @@ export class EmployeeBaseEntity implements Employee { @ApiProperty() signatureLink: string; - @ApiProperty() + @ApiProperty({ enum: EmployeeScope }) scope: EmployeeScope; @Exclude() diff --git a/apps/server/src/signatures/signatures.controller.spec.ts b/apps/server/src/signatures/signatures.controller.spec.ts index 074ccd72..d48194d2 100644 --- a/apps/server/src/signatures/signatures.controller.spec.ts +++ b/apps/server/src/signatures/signatures.controller.spec.ts @@ -8,7 +8,7 @@ import { PositionsService } from '../positions/positions.service'; import { UpdateSignatureSignerDto } from './dto/update-signature-signer.dto'; import { SignerType } from '@prisma/client'; -let mockSignatureService = { +const mockSignatureService = { updateSigner: async ( signatureId: string, updateSignatureSignerDto: UpdateSignatureSignerDto, @@ -57,7 +57,7 @@ describe('SignaturesController', () => { }); it('should update signer', async () => { - let response = await controller.updateSignatureSigner('signature-id', { + const response = await controller.updateSignatureSigner('signature-id', { signerType: 'DEPARTMENT', signerDepartmentId: 'department-id', }); diff --git a/apps/server/src/signatures/signatures.service.spec.ts b/apps/server/src/signatures/signatures.service.spec.ts index da202cc0..a2593f21 100644 --- a/apps/server/src/signatures/signatures.service.spec.ts +++ b/apps/server/src/signatures/signatures.service.spec.ts @@ -7,7 +7,7 @@ import { ConnectEmployeeDto } from './dto/create-signature.dto'; import { DepartmentsService } from '../departments/departments.service'; import { PositionsService } from '../positions/positions.service'; -let signaturePositionSigner = { +const signaturePositionSigner = { id: 'signature-id', formInstanceId: 'form-instance-id', signerType: 'POSITION', @@ -19,7 +19,7 @@ let signaturePositionSigner = { updatedAt: new Date(1672531200), }; -let signatureDepartmentSigner = { +const signatureDepartmentSigner = { id: 'signature-id', formInstanceId: 'form-instance-id', signerType: 'DEPARTMENT', @@ -35,7 +35,7 @@ const db = { signature: { findFirstOrThrow: jest.fn().mockResolvedValue(signaturePositionSigner), update: jest.fn().mockImplementation((args) => { - let val = { + const val = { ...signaturePositionSigner, ...args.data, }; @@ -127,7 +127,7 @@ describe('SignaturesService', () => { signerDepartmentId: null, signerEmployeeId: null, }; - let updatedSignature = await service.updateSigner( + const updatedSignature = await service.updateSigner( 'signature-id', updateSignatureSignerDto, ); @@ -149,7 +149,7 @@ describe('SignaturesService', () => { signerDepartmentId: 'department-id', signerEmployeeId: null, }; - let updatedSignature = await service.updateSigner( + const updatedSignature = await service.updateSigner( 'signature-id', updateSignatureSignerDto, ); @@ -171,7 +171,7 @@ describe('SignaturesService', () => { signerDepartmentId: null, signerEmployeeId: 'employee-id', }; - let updatedSignature = await service.updateSigner( + const updatedSignature = await service.updateSigner( 'signature-id', updateSignatureSignerDto, ); @@ -197,7 +197,7 @@ describe('SignaturesService', () => { { id: 'employee-id-2' }, ], }; - let updatedSignature = await service.updateSigner( + const updatedSignature = await service.updateSigner( 'signature-id', updateSignatureSignerDto, ); diff --git a/apps/server/src/signatures/signatures.service.ts b/apps/server/src/signatures/signatures.service.ts index 5cf07faa..ddc4cd97 100644 --- a/apps/server/src/signatures/signatures.service.ts +++ b/apps/server/src/signatures/signatures.service.ts @@ -161,7 +161,7 @@ export class SignaturesService { } } async findOne(id: string) { - let signature = await this.prisma.signature.findFirstOrThrow({ + const signature = await this.prisma.signature.findFirstOrThrow({ where: { id: id, }, diff --git a/apps/web/src/client/index.ts b/apps/web/src/client/index.ts index 6a50354b..8edbd257 100644 --- a/apps/web/src/client/index.ts +++ b/apps/web/src/client/index.ts @@ -9,30 +9,31 @@ export type { OpenAPIConfig } from './core/OpenAPI'; export type { ConnectEmployeeDto } from './models/ConnectEmployeeDto'; export type { CreateDepartmentDto } from './models/CreateDepartmentDto'; -export type { CreateEmployeeDto } from './models/CreateEmployeeDto'; +export { CreateEmployeeDto } from './models/CreateEmployeeDto'; export type { CreateFormInstanceDto } from './models/CreateFormInstanceDto'; export type { CreateFormTemplateDto } from './models/CreateFormTemplateDto'; export type { CreatePositionDto } from './models/CreatePositionDto'; export { CreateSignatureDto } from './models/CreateSignatureDto'; export type { CreateSignatureFieldDto } from './models/CreateSignatureFieldDto'; export type { DepartmentEntity } from './models/DepartmentEntity'; -export type { EmployeeBaseEntity } from './models/EmployeeBaseEntity'; -export type { EmployeeEntity } from './models/EmployeeEntity'; +export { EmployeeBaseEntity } from './models/EmployeeBaseEntity'; +export { EmployeeEntity } from './models/EmployeeEntity'; export type { FormInstanceEntity } from './models/FormInstanceEntity'; export type { FormTemplateBaseEntity } from './models/FormTemplateBaseEntity'; export type { FormTemplateEntity } from './models/FormTemplateEntity'; export type { JwtEntity } from './models/JwtEntity'; export type { PositionBaseEntity } from './models/PositionBaseEntity'; export type { PositionEntity } from './models/PositionEntity'; -export type { RegisterEmployeeDto } from './models/RegisterEmployeeDto'; +export { RegisterEmployeeDto } from './models/RegisterEmployeeDto'; export { SignatureEntity } from './models/SignatureEntity'; export type { SignatureFieldEntity } from './models/SignatureFieldEntity'; export type { UpdateDepartmentDto } from './models/UpdateDepartmentDto'; -export type { UpdateEmployeeDto } from './models/UpdateEmployeeDto'; +export { UpdateEmployeeDto } from './models/UpdateEmployeeDto'; export type { UpdateFormInstanceDto } from './models/UpdateFormInstanceDto'; export type { UpdateFormTemplateDto } from './models/UpdateFormTemplateDto'; export type { UpdatePositionDto } from './models/UpdatePositionDto'; export type { UpdateSignatureFieldDto } from './models/UpdateSignatureFieldDto'; +export { UpdateSignatureSignerDto } from './models/UpdateSignatureSignerDto'; export { DefaultService } from './services/DefaultService'; export { DepartmentsService } from './services/DepartmentsService'; diff --git a/apps/web/src/client/models/CreateEmployeeDto.ts b/apps/web/src/client/models/CreateEmployeeDto.ts index 522abba9..e6cdc6cc 100644 --- a/apps/web/src/client/models/CreateEmployeeDto.ts +++ b/apps/web/src/client/models/CreateEmployeeDto.ts @@ -10,6 +10,16 @@ export type CreateEmployeeDto = { email: string; password: string; signatureLink: string; - scope: Record; + scope: CreateEmployeeDto.scope; }; +export namespace CreateEmployeeDto { + + export enum scope { + BASE_USER = 'BASE_USER', + ADMIN = 'ADMIN', + } + + +} + diff --git a/apps/web/src/client/models/EmployeeBaseEntity.ts b/apps/web/src/client/models/EmployeeBaseEntity.ts index e2903d53..0dccdd45 100644 --- a/apps/web/src/client/models/EmployeeBaseEntity.ts +++ b/apps/web/src/client/models/EmployeeBaseEntity.ts @@ -9,7 +9,7 @@ export type EmployeeBaseEntity = { lastName: string; email: string; signatureLink: string; - scope: Record; + scope: EmployeeBaseEntity.scope; positionId: string; pswdHash: string | null; createdAt: string; @@ -17,3 +17,13 @@ export type EmployeeBaseEntity = { refreshToken: string | null; }; +export namespace EmployeeBaseEntity { + + export enum scope { + BASE_USER = 'BASE_USER', + ADMIN = 'ADMIN', + } + + +} + diff --git a/apps/web/src/client/models/EmployeeEntity.ts b/apps/web/src/client/models/EmployeeEntity.ts index eb563a4c..01f691f1 100644 --- a/apps/web/src/client/models/EmployeeEntity.ts +++ b/apps/web/src/client/models/EmployeeEntity.ts @@ -11,7 +11,7 @@ export type EmployeeEntity = { lastName: string; email: string; signatureLink: string; - scope: Record; + scope: EmployeeEntity.scope; position: PositionBaseEntity; positionId: string; pswdHash: string | null; @@ -20,3 +20,13 @@ export type EmployeeEntity = { refreshToken: string | null; }; +export namespace EmployeeEntity { + + export enum scope { + BASE_USER = 'BASE_USER', + ADMIN = 'ADMIN', + } + + +} + diff --git a/apps/web/src/client/models/RegisterEmployeeDto.ts b/apps/web/src/client/models/RegisterEmployeeDto.ts index 9b756239..c2749e45 100644 --- a/apps/web/src/client/models/RegisterEmployeeDto.ts +++ b/apps/web/src/client/models/RegisterEmployeeDto.ts @@ -11,6 +11,16 @@ export type RegisterEmployeeDto = { positionName: string; departmentName: string; signatureLink: string; - scope: Record; + scope: RegisterEmployeeDto.scope; }; +export namespace RegisterEmployeeDto { + + export enum scope { + BASE_USER = 'BASE_USER', + ADMIN = 'ADMIN', + } + + +} + diff --git a/apps/web/src/client/models/UpdateEmployeeDto.ts b/apps/web/src/client/models/UpdateEmployeeDto.ts index 6ccbd431..364d547e 100644 --- a/apps/web/src/client/models/UpdateEmployeeDto.ts +++ b/apps/web/src/client/models/UpdateEmployeeDto.ts @@ -8,6 +8,16 @@ export type UpdateEmployeeDto = { lastName?: string; positionId?: string; signatureLink?: string; - scope?: Record; + scope?: UpdateEmployeeDto.scope; }; +export namespace UpdateEmployeeDto { + + export enum scope { + BASE_USER = 'BASE_USER', + ADMIN = 'ADMIN', + } + + +} + diff --git a/apps/web/src/client/models/UpdateSignatureSignerDto.ts b/apps/web/src/client/models/UpdateSignatureSignerDto.ts new file mode 100644 index 00000000..8a9e7849 --- /dev/null +++ b/apps/web/src/client/models/UpdateSignatureSignerDto.ts @@ -0,0 +1,27 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { ConnectEmployeeDto } from './ConnectEmployeeDto'; + +export type UpdateSignatureSignerDto = { + signerEmployeeId?: string | null; + signerPositionId?: string | null; + signerDepartmentId?: string | null; + signerEmployeeList?: Array; + signerType?: UpdateSignatureSignerDto.signerType; +}; + +export namespace UpdateSignatureSignerDto { + + export enum signerType { + POSITION = 'POSITION', + DEPARTMENT = 'DEPARTMENT', + USER = 'USER', + USER_LIST = 'USER_LIST', + } + + +} + diff --git a/apps/web/src/client/services/DefaultService.ts b/apps/web/src/client/services/DefaultService.ts index 5fb849cc..5f999227 100644 --- a/apps/web/src/client/services/DefaultService.ts +++ b/apps/web/src/client/services/DefaultService.ts @@ -5,6 +5,7 @@ import type { EmployeeEntity } from '../models/EmployeeEntity'; import type { JwtEntity } from '../models/JwtEntity'; import type { RegisterEmployeeDto } from '../models/RegisterEmployeeDto'; +import type { UpdateSignatureSignerDto } from '../models/UpdateSignatureSignerDto'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; @@ -93,4 +94,25 @@ export class DefaultService { }); } + /** + * @param id + * @param requestBody + * @returns any + * @throws ApiError + */ + public static signaturesControllerUpdateSignatureSigner( + id: string, + requestBody: UpdateSignatureSignerDto, + ): CancelablePromise> { + return __request(OpenAPI, { + method: 'PATCH', + url: '/api/signatures/{id}/signer', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + }); + } + } diff --git a/apps/web/src/context/AuthContext.tsx b/apps/web/src/context/AuthContext.tsx index b35fbef4..df74258f 100644 --- a/apps/web/src/context/AuthContext.tsx +++ b/apps/web/src/context/AuthContext.tsx @@ -187,7 +187,7 @@ export const AuthProvider = ({ children }: any) => { position: string, department: string, signatureLink: string, - scope: EmployeeScope, + scope: RegisterEmployeeDto.scope, ) => { const employee: RegisterEmployeeDto = { email: email, @@ -197,7 +197,7 @@ export const AuthProvider = ({ children }: any) => { departmentName: department, positionName: position, signatureLink: signatureLink, - scope: scope.valueOf, // Record + scope: scope, }; registerEmployeeMutation.mutate(employee, { diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index fd3788ab..a0742d23 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -4,6 +4,7 @@ import { FieldGroups, } from '@web/components/createFormTemplate/createFormTemplateEditor/FormEditor'; import { EmployeeScope } from '@prisma/client'; +import { RegisterEmployeeDto } from '@web/client'; // for storage in context export type User = { @@ -39,7 +40,7 @@ export interface AuthContextType { position: string, department: string, signatureLink: string, - scope: EmployeeScope, + scope: RegisterEmployeeDto.scope, ) => void; logout: () => void; } diff --git a/apps/web/src/pages/register.tsx b/apps/web/src/pages/register.tsx index 39c9b3a6..bd87150b 100644 --- a/apps/web/src/pages/register.tsx +++ b/apps/web/src/pages/register.tsx @@ -1,5 +1,9 @@ import { Flex, Box, Text, Select, Button } from '@chakra-ui/react'; -import { DepartmentsService, PositionsService } from '@web/client'; +import { + DepartmentsService, + PositionsService, + RegisterEmployeeDto, +} from '@web/client'; import { DepartmentEntity } from '@web/client/models/DepartmentEntity'; import { PositionEntity } from '@web/client/models/PositionEntity'; import { useEffect, useState, useRef } from 'react'; @@ -107,7 +111,7 @@ export default function Register() { currentDepartmentName, currentPositionName, uploadedBlob?.url || 'http://localhost:3002/signature.png', - EmployeeScope.BASE_USER, + RegisterEmployeeDto.scope.BASE_USER, ); }; From 8e0a1c530c0fc7230bb975db16ab9d915a7c3823 Mon Sep 17 00:00:00 2001 From: Kaiyang Zheng Date: Sun, 9 Feb 2025 00:30:21 -0500 Subject: [PATCH 12/13] use correct scope type from client --- apps/server/prisma/schema.prisma | 2 +- .../src/employees/dto/create-employee.dto.ts | 1 + apps/web/src/context/AuthContext.tsx | 18 +++++++++--------- apps/web/src/pages/register.tsx | 10 +++------- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/apps/server/prisma/schema.prisma b/apps/server/prisma/schema.prisma index 6d08a66f..1510271e 100644 --- a/apps/server/prisma/schema.prisma +++ b/apps/server/prisma/schema.prisma @@ -44,7 +44,7 @@ model Employee { lastName String @db.VarChar(255) email String @unique @db.VarChar(255) signatureLink String @db.VarChar(255) - scope EmployeeScope @default(BASE_USER) // TODO @db tag + scope EmployeeScope @default(BASE_USER) pswdHash String? @db.VarChar(255) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/apps/server/src/employees/dto/create-employee.dto.ts b/apps/server/src/employees/dto/create-employee.dto.ts index 48035749..b4f69b28 100644 --- a/apps/server/src/employees/dto/create-employee.dto.ts +++ b/apps/server/src/employees/dto/create-employee.dto.ts @@ -40,6 +40,7 @@ export class CreateEmployeeDto { @ApiProperty() signatureLink: string; + @IsString() @IsNotEmpty() @ApiProperty({ enum: EmployeeScope }) scope: EmployeeScope; diff --git a/apps/web/src/context/AuthContext.tsx b/apps/web/src/context/AuthContext.tsx index 403efad8..3e1e0d6a 100644 --- a/apps/web/src/context/AuthContext.tsx +++ b/apps/web/src/context/AuthContext.tsx @@ -6,7 +6,7 @@ import { useMsal } from '@azure/msal-react'; import { loginRequest } from '@web/authConfig'; import { callMsGraph } from '@web/graph'; import { useMutation } from '@tanstack/react-query'; -import { EmployeeScope } from '@prisma/client'; +import { Scope } from '@web/client'; import { appControllerLogin, @@ -101,13 +101,13 @@ export const AuthProvider = ({ children }: any) => { } setUser({ - id: employee.id, - positionId: employee.position.id, - departmentId: position.department.id, - email: employee.email, - firstName: employee.firstName, - lastName: employee.lastName, - scope: EmployeeScope.BASE_USER, + id: employee.data.id, + positionId: employee.data.position.id, + departmentId: position.data.department.id, + email: employee.data.email, + firstName: employee.data.firstName, + lastName: employee.data.lastName, + scope: Scope.BASE_USER, }); }) .catch(async (_error) => { @@ -209,7 +209,7 @@ export const AuthProvider = ({ children }: any) => { position: string, department: string, signatureLink: string, - scope: RegisterEmployeeDto.scope, + scope: RegisterEmployeeDto['scope'], ) => { const employee: RegisterEmployeeDto = { email: email, diff --git a/apps/web/src/pages/register.tsx b/apps/web/src/pages/register.tsx index c2851bdf..3f4dc2ce 100644 --- a/apps/web/src/pages/register.tsx +++ b/apps/web/src/pages/register.tsx @@ -4,16 +4,12 @@ import { useAuth } from '@web/hooks/useAuth'; import { useQuery } from '@tanstack/react-query'; import { useBlob } from '@web/hooks/useBlob'; import { SignaturePad } from './../components/SignaturePad'; -import { - departmentsControllerFindAll, - positionsControllerFindAllInDepartmentName, - DepartmentEntity, - PositionEntity, -} from '@web/client'; +import { DepartmentEntity, PositionEntity } from '@web/client'; import { departmentsControllerFindAllOptions, positionsControllerFindAllInDepartmentNameOptions, } from '@web/client/@tanstack/react-query.gen'; +import { Scope } from '@web/client'; export default function Register() { const { completeRegistration, userData } = useAuth(); @@ -116,7 +112,7 @@ export default function Register() { currentDepartmentName, currentPositionName, uploadedBlob?.url || 'http://localhost:3002/signature.png', - RegisterEmployeeDto.scope.BASE_USER, + Scope.BASE_USER, ); }; From 8d5d7a5fb753625342f36fa29dcba03da1b30d5f Mon Sep 17 00:00:00 2001 From: Kaiyang Zheng Date: Sun, 9 Feb 2025 00:38:50 -0500 Subject: [PATCH 13/13] fix tsc type in context type --- apps/web/src/context/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/context/types.ts b/apps/web/src/context/types.ts index a0742d23..79902f77 100644 --- a/apps/web/src/context/types.ts +++ b/apps/web/src/context/types.ts @@ -40,7 +40,7 @@ export interface AuthContextType { position: string, department: string, signatureLink: string, - scope: RegisterEmployeeDto.scope, + scope: RegisterEmployeeDto['scope'], ) => void; logout: () => void; }