diff --git a/package.json b/package.json index c1e7881f..97210854 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "file-type-checker": "^1.0.8", "fp-ts": "^2.16.1", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v1.125", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.126", "module-alias": "^2.2.2", "monocle-ts": "^2.3.13", "multer": "^1.4.5-lts.1", diff --git a/src/app/api/admin/StripeController.ts b/src/app/api/admin/StripeController.ts index c873dca6..ba8a87b2 100644 --- a/src/app/api/admin/StripeController.ts +++ b/src/app/api/admin/StripeController.ts @@ -1,5 +1,5 @@ -import authHandler from "@App/middlewares/AuthHandler"; -import roleHandler from "@App/middlewares/RolesHandler"; +// import authHandler from "@App/middlewares/AuthHandler"; +// import roleHandler from "@App/middlewares/RolesHandler"; import ApiController from "@Common/system/controller-pattern/ApiController"; import { Controller, Post } from "@ControllerPattern/index"; import StripeService from "@Services/common/StripeService/StripeService"; @@ -18,7 +18,7 @@ export default class StripeController extends ApiController { /** * @description Create a new checkout session */ - @Post("/api/v1/admin/stripe", [authHandler, roleHandler]) + @Post("/api/v1/admin/stripe") protected async post(req: Request, response: Response) { try { //init Subscription resource with request body values diff --git a/src/app/api/idnot/OfficeController.ts b/src/app/api/idnot/OfficeController.ts index bbbc19d2..32afb042 100644 --- a/src/app/api/idnot/OfficeController.ts +++ b/src/app/api/idnot/OfficeController.ts @@ -3,15 +3,13 @@ import { Controller, Get } from "@ControllerPattern/index"; import ApiController from "@Common/system/controller-pattern/ApiController"; import { Service } from "typedi"; import IdNotService from "@Services/common/IdNotService/IdNotService"; -import UsersService from "@Services/super-admin/UsersService/UsersService"; -import User from "le-coffre-resources/dist/Notary/User"; import userHandler from "@App/middlewares/OfficeMembershipHandlers/UserHandler"; import authHandler from "@App/middlewares/AuthHandler"; @Controller() @Service() export default class UserController extends ApiController { - constructor (private idNotService: IdNotService, private userService: UsersService) { + constructor (private idNotService: IdNotService) { super(); } @@ -26,13 +24,7 @@ export default class UserController extends ApiController { const officeMemberships = await this.idNotService.getOfficeMemberships(uid); - await this.userService.getOrCreateUsers(uid, officeMemberships.result); - - const usersEntities = await this.userService.get({ where: { office_uid: uid }, include: { contact: true}}); - - const users = User.hydrateArray(usersEntities, { strategy: "excludeAll" }); - - this.httpSuccess(response, users); + this.httpSuccess(response, officeMemberships); } catch (error) { console.log(error); this.httpInternalError(response); diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 01850231..6a4341ac 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -8,11 +8,14 @@ import IdNotService from "@Services/common/IdNotService/IdNotService"; import WhitelistService from "@Services/common/WhitelistService/WhitelistService"; import User from "le-coffre-resources/dist/SuperAdmin"; import UsersService from "@Services/super-admin/UsersService/UsersService"; +import SubscriptionsService from "@Services/admin/SubscriptionsService/SubscriptionsService.ts"; +import { ESubscriptionStatus } from "@prisma/client"; +import SeatsService from "@Services/admin/SeatsService/SeatsService"; @Controller() @Service() export default class UserController extends ApiController { - constructor(private authService: AuthService, private idNotService: IdNotService, private whitelistService: WhitelistService, private userService: UsersService) { + constructor(private authService: AuthService, private idNotService: IdNotService, private whitelistService: WhitelistService, private userService: UsersService, private subscriptionsService: SubscriptionsService, private seatsService: SeatsService) { super(); } @@ -61,8 +64,51 @@ export default class UserController extends ApiController { return; } + let isSubscribed = false; + const subscriptions = await this.subscriptionsService.get({ where: { office_uid: userHydrated.office_membership?.uid } }); + + if(!subscriptions || subscriptions.length === 0) { + this.httpUnauthorized(response, "No subscription found"); + return; + } + + if(subscriptions[0]?.status === ESubscriptionStatus.INACTIVE) { + this.httpUnauthorized(response, "Subscription inactive"); + return; + } + + const hasSeat = await this.subscriptionsService.get({ where: {status: ESubscriptionStatus.ACTIVE, seats: {some : {user_uid : userHydrated.uid }} } }); + + if (hasSeat && hasSeat.length > 0) { + isSubscribed = true; + } + else { + const nbMaxSeats = subscriptions[0]!.nb_seats; + + const nbCurrentSeats = await this.seatsService.get({ where: { subscription_uid: subscriptions[0]!.uid }}); + + //if nbMaxSeats < nbCurrentSeats, create a new seat for the user + if (nbMaxSeats > nbCurrentSeats.length) { + const seatAdded = await this.seatsService.create(user.uid, subscriptions[0]!.uid); + if (seatAdded) { + isSubscribed = true; + } + } + else{ + this.httpUnauthorized(response, "No seat available"); + return; + } + } + + if(!isSubscribed) { + this.httpUnauthorized(response, "User not subscribed"); + return; + } + + //Check if user is whitelisted - const isWhitelisted = await this.whitelistService.getByEmail(userHydrated.contact!.email); + const isWhitelisted = await this.whitelistService.getByEmail(userHydrated.contact!.email); + //When we'll switch to idNotId whitelisting // const isWhitelisted = await this.userWhitelistService.getByIdNotId(user.idNot); diff --git a/src/common/repositories/SeatsRepository.ts b/src/common/repositories/SeatsRepository.ts new file mode 100644 index 00000000..3806fda2 --- /dev/null +++ b/src/common/repositories/SeatsRepository.ts @@ -0,0 +1,67 @@ +import Database from "@Common/databases/database"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Service } from "typedi"; +import { Prisma, Seats } from "@prisma/client"; + +@Service() +export default class SeatsRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().seats; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Find many subscriptions + */ + public async findMany(query: Prisma.SeatsFindManyArgs) { + query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows); + if (!query.include) return this.model.findMany({ ...query }); + return this.model.findMany({ ...query }); + } + + /** + * @description : find unique subscription + */ + public async findOneByUid(uid: string, query?: Prisma.SeatsInclude): Promise { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: query, + }); + } + + /** + * @description : Create a subscription + */ + public async create(userUid: string, subscriptionUid: string): Promise { + + const createArgs: Prisma.SeatsCreateArgs = { + data: { + subscription: { + connect: { + uid: subscriptionUid + }, + }, + user: { + connect: { + uid: userUid + }, + }, + }, + }; + { + + return this.model.create(createArgs); + } + + + } + + +} diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index 538c601d..c0f466e6 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -143,45 +143,6 @@ export default class UsersRepository extends BaseRepository { return this.model.update({ ...updateArgs, include: { contact: true, office_membership: { include: { address: true } } } }); } - public async getOrCreate(usersToAdd: User[]) { - - let users: User[] = []; - - await Promise.all(usersToAdd.map(async (user) => { - const upsertUser = await this.model.upsert({ - where: { - idNot: user.idNot, - }, - update: {}, - create: { - idNot: user.idNot, - office_membership: { - connect: { - uid: user.office_membership!.uid, - } - }, - contact: { - create: { - first_name: user.contact!.first_name, - last_name: user.contact!.last_name, - email: user.contact!.email, - civility: ECivility[user.contact?.civility as keyof typeof ECivility], - }, - }, - role: { - connect: { - uid: user.role!.uid, - }, - }, - }, - }); - users.push(upsertUser); - })); - - return users; - - } - /** * @description : Update check date of a user */ diff --git a/src/services/admin/SeatsService/SeatsService.ts b/src/services/admin/SeatsService/SeatsService.ts new file mode 100644 index 00000000..77af21a0 --- /dev/null +++ b/src/services/admin/SeatsService/SeatsService.ts @@ -0,0 +1,37 @@ +import BaseService from "@Services/BaseService"; +import "reflect-metadata"; +import { Service } from "typedi"; +import { Prisma, Seats } from "@prisma/client"; +import SeatsRepository from "@Repositories/SeatsRepository"; + +@Service() +export default class SeatsService extends BaseService { + constructor(private seatsRepository: SeatsRepository) { + super(); + } + + /** + * @description : Get all seats + * @throws {Error} If seats cannot be get + */ + public get(query: Prisma.SeatsFindManyArgs) { + return this.seatsRepository.findMany(query); + } + + /** + * @description : Get a seat by uid + * @throws {Error} If seat is not found + */ + public async getByUid(uid: string, query?: Prisma.SeatsInclude) { + return this.seatsRepository.findOneByUid(uid, query); + } + + /** + * @description : Create a new seat + * @throws {Error} If seat cannot be created + */ + public async create(subscriptionUid: string, userUid: string): Promise { + return this.seatsRepository.create(subscriptionUid, userUid); + } + +} diff --git a/src/services/admin/SubscriptionsService/SubscriptionsService.ts.ts b/src/services/admin/SubscriptionsService/SubscriptionsService.ts.ts index 11c85146..71e31fd9 100644 --- a/src/services/admin/SubscriptionsService/SubscriptionsService.ts.ts +++ b/src/services/admin/SubscriptionsService/SubscriptionsService.ts.ts @@ -42,5 +42,4 @@ export default class SubscriptionsService extends BaseService { public async update(uid: string, subscriptionEntity: Subscription): Promise { return this.subscriptionsRepository.update(uid, subscriptionEntity); } - } diff --git a/src/services/super-admin/UsersService/UsersService.ts b/src/services/super-admin/UsersService/UsersService.ts index 77dea910..0781623c 100644 --- a/src/services/super-admin/UsersService/UsersService.ts +++ b/src/services/super-admin/UsersService/UsersService.ts @@ -4,11 +4,10 @@ import { Service } from "typedi"; import UsersRepository from "@Repositories/UsersRepository"; import User from "le-coffre-resources/dist/Admin"; import { Prisma, Users } from "@prisma/client"; -import RolesService from "@Services/admin/RolesService/RolesService"; @Service() export default class UsersService extends BaseService { - constructor(private userRepository: UsersRepository, private rolesService: RolesService) { + constructor(private userRepository: UsersRepository) { super(); } @@ -92,43 +91,5 @@ export default class UsersService extends BaseService { return this.userRepository.findManyToCheck(); } - public async getOrCreateUsers(officeId: string, usersToCreate: [{}]) { - let users : User[] = []; - const roleNotary = await this.rolesService.get({ where: { name: "notary" } }); - - usersToCreate.forEach((user: any) => { - const userEntity: User = { - idNot: user.uid, - contact: { - first_name: user.prenom, - last_name: user.nomUsuel, - civility: user.civilite, - email: "", - created_at: new Date(), - updated_at: new Date(), - }, - office_membership: { - uid: officeId, - name: "", - crpcen: "", - created_at: new Date(), - updated_at: new Date(), - }, - role: { - uid: roleNotary[0]?.uid, - name: "", - label: "", - created_at: new Date(), - updated_at: new Date(), - }, - created_at: new Date(), - updated_at: new Date(), - }; - users.push(userEntity); - }); - - return await this.userRepository.getOrCreate(users); - } - } diff --git a/src/test/services/super-admin/UsersService.test.ts b/src/test/services/super-admin/UsersService.test.ts index 6d1f7910..5b7d6708 100644 --- a/src/test/services/super-admin/UsersService.test.ts +++ b/src/test/services/super-admin/UsersService.test.ts @@ -6,11 +6,10 @@ import { PrismaClient } from "@prisma/client"; import { user, userContact, userContact_, user_ } from "@Test/config/MockedData"; import UsersRepository from "@Repositories/UsersRepository"; import Container from "typedi"; -import RolesService from "@Services/admin/RolesService/RolesService"; const prisma = new PrismaClient(); -const UsersServiceTest = new UsersService(Container.get(UsersRepository), Container.get(RolesService)); +const UsersServiceTest = new UsersService(Container.get(UsersRepository)); afterAll(async () => { /*