From 73a02d1a2cc0410c8c1a407d513cda12cce62fe6 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 <123148298+souravbhowmik1999@users.noreply.github.com> Date: Thu, 15 Feb 2024 12:44:17 +0530 Subject: [PATCH 001/408] Revert "Task #213841 Add authentication for bearer token" --- src/adapters/hasura/attendance.adapter.ts | 338 ++++++------- src/adapters/hasura/cohort.adapter.ts | 275 +++++----- src/adapters/hasura/cohortMembers.adapter.ts | 219 ++++---- src/adapters/hasura/fields.adapter.ts | 122 ++--- .../hasura/services/fields.service.ts | 475 ++++++++---------- src/adapters/hasura/user.adapter.ts | 5 +- src/main.ts | 2 +- 7 files changed, 646 insertions(+), 790 deletions(-) diff --git a/src/adapters/hasura/attendance.adapter.ts b/src/adapters/hasura/attendance.adapter.ts index a60ba2ae..db2b389f 100644 --- a/src/adapters/hasura/attendance.adapter.ts +++ b/src/adapters/hasura/attendance.adapter.ts @@ -124,7 +124,7 @@ export class AttendanceHasuraService implements IServicelocator { attendanceDto: AttendanceDto ) { const attendanceSchema = new AttendanceDto(attendanceDto); - + let query = ""; Object.keys(attendanceDto).forEach((e) => { if ( @@ -183,135 +183,31 @@ export class AttendanceHasuraService implements IServicelocator { request: any, attendanceSearchDto: AttendanceSearchDto ) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - - let offset = 0; - if (attendanceSearchDto.page > 1) { - offset = - parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); - } - - attendanceSearchDto.filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(attendanceSearchDto.filters).forEach((item) => { - Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - attendanceSearchDto.filters[item][`_${e}`] = - attendanceSearchDto.filters[item][e]; - delete attendanceSearchDto.filters[item][e]; - } - }); - }); - - const data = { - query: `query SearchAttendance($filters:Attendance_bool_exp,$limit:Int, $offset:Int) { - Attendance_aggregate (where:$filters, limit: $limit, offset: $offset,){ - aggregate { - count - } - } - Attendance(where:$filters, limit: $limit, offset: $offset,) { - attendance - attendanceDate - attendanceId - tenantId - userId - remark - latitude - longitude - image - metaData - remark - syncTime - session - contextId - contextType - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(attendanceSearchDto.limit) - ? parseInt(attendanceSearchDto.limit) - : 10, - offset: offset, - filters: attendanceSearchDto.filters, - }, - }; - - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await this.axios(config); - - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: response.data.errors[0].message, - }); - } - - let result = response?.data?.data?.Attendance; - - let mappedResponse = await this.mappedResponse(result); - const count = response?.data?.data?.Attendance_aggregate?.aggregate?.count; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: mappedResponse, - }); - }catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); + let offset = 0; + if (attendanceSearchDto.page > 1) { + offset = + parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); } - } - - public async attendanceByDate( - tenantId: string, - request: any, - attendanceSearchDto: AttendanceDateDto - ) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - - let offset = 0; - if (attendanceSearchDto.page > 1) { - offset = - parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); - } - const filters = attendanceSearchDto.filters; - - //add tenantid - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - - Object.keys(attendanceSearchDto.filters).forEach((item) => { - Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); + attendanceSearchDto.filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + Object.keys(attendanceSearchDto.filters).forEach((item) => { + Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + attendanceSearchDto.filters[item][`_${e}`] = + attendanceSearchDto.filters[item][e]; + delete attendanceSearchDto.filters[item][e]; + } }); + }); - const attendanceData = { - query: `query AttendanceFilter($fromDate: date, $toDate: date, $filters: [Attendance_bool_exp!], $limit: Int, $offset: Int) { - Attendance(where: {attendanceDate: {_gte: $fromDate, _lte: $toDate}, _and: $filters}, limit: $limit, offset: $offset) { + const data = { + query: `query SearchAttendance($filters:Attendance_bool_exp,$limit:Int, $offset:Int) { + Attendance_aggregate (where:$filters, limit: $limit, offset: $offset,){ + aggregate { + count + } + } + Attendance(where:$filters, limit: $limit, offset: $offset,) { attendance attendanceDate attendanceId @@ -322,6 +218,7 @@ export class AttendanceHasuraService implements IServicelocator { longitude image metaData + remark syncTime session contextId @@ -330,53 +227,133 @@ export class AttendanceHasuraService implements IServicelocator { updatedAt createdBy updatedBy - } - }`, - variables: { - fromDate: attendanceSearchDto.fromDate, - toDate: attendanceSearchDto.toDate, - filters: filters, - limit: parseInt(attendanceSearchDto.limit), - offset: offset, - }, - }; - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: attendanceData, - }; + } + }`, + variables: { + limit: parseInt(attendanceSearchDto.limit) + ? parseInt(attendanceSearchDto.limit) + : 10, + offset: offset, + filters: attendanceSearchDto.filters, + }, + }; + const config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await this.axios(config); + const response = await this.axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: "400", - errorMessage: response.data.errors[0].message, - }); - } + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: "500", + errorMessage: response.data.errors[0].message, + }); + } + + let result = response?.data?.data?.Attendance; + + let mappedResponse = await this.mappedResponse(result); + const count = response?.data?.data?.Attendance_aggregate?.aggregate?.count; + + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: mappedResponse, + }); + } + + public async attendanceByDate( + tenantId: string, + request: any, + attendanceSearchDto: AttendanceDateDto + ) { + let offset = 0; + if (attendanceSearchDto.page > 1) { + offset = + parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); + } - const result = response.data.data.Attendance; + const filters = attendanceSearchDto.filters; - const mappedResponse = await this.mappedResponse(result); + //add tenantid + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - return new SuccessResponse({ - statusCode: 200, - message: "Ok", - totalCount: mappedResponse?.length, - data: mappedResponse, + Object.keys(attendanceSearchDto.filters).forEach((item) => { + Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); + }); + + const attendanceData = { + query: `query AttendanceFilter($fromDate: date, $toDate: date, $filters: [Attendance_bool_exp!], $limit: Int, $offset: Int) { + Attendance(where: {attendanceDate: {_gte: $fromDate, _lte: $toDate}, _and: $filters}, limit: $limit, offset: $offset) { + attendance + attendanceDate + attendanceId + tenantId + userId + remark + latitude + longitude + image + metaData + syncTime + session + contextId + contextType + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + fromDate: attendanceSearchDto.fromDate, + toDate: attendanceSearchDto.toDate, + filters: filters, + limit: parseInt(attendanceSearchDto.limit), + offset: offset, + }, + }; + const config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: attendanceData, + }; + + const response = await this.axios(config); + + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: "400", + errorMessage: response.data.errors[0].message, }); - }catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); } + + const result = response.data.data.Attendance; + + const mappedResponse = await this.mappedResponse(result); + + return new SuccessResponse({ + statusCode: 200, + message: "Ok", + totalCount: mappedResponse?.length, + data: mappedResponse, + }); } public async checkAndAddAttendance( @@ -384,6 +361,7 @@ export class AttendanceHasuraService implements IServicelocator { attendanceDto: AttendanceDto ) { // Api Checks attendance by date and userId , that is daywise attendance + try { const decoded: any = jwt_decode(request.headers.authorization); const userId = @@ -424,7 +402,10 @@ export class AttendanceHasuraService implements IServicelocator { // Else - Create new entry return await this.createAttendance(request, attendanceDto); } - + } catch (e) { + console.error(e); + return e; + } } // bulk attendance api @@ -435,8 +416,7 @@ export class AttendanceHasuraService implements IServicelocator { ) { const responses = []; const errors = []; - - const decoded: any = jwt_decode(request.headers.authorization); + try { for (const attendance of attendanceData) { attendance.tenantId = tenantId; const attendanceRes: any = await this.checkAndAddAttendance( @@ -452,15 +432,17 @@ export class AttendanceHasuraService implements IServicelocator { }); } } - - return { - statusCode: 200, - totalCount: attendanceData.length, - successCount: responses.length, - responses, - errors, - }; - + } catch (e) { + console.error(e); + return e; + } + return { + statusCode: 200, + totalCount: attendanceData.length, + successCount: responses.length, + responses, + errors, + }; } public async mappedResponse(result: any) { diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index 1e12acd0..a5e61c60 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -4,7 +4,6 @@ import { HttpService } from "@nestjs/axios"; import { SuccessResponse } from "src/success-response"; import { ErrorResponse } from "src/error-response"; const resolvePath = require("object-resolve-path"); -import jwt_decode from "jwt-decode"; import { CohortDto } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { IServicelocatorcohort } from "../cohortservicelocator"; @@ -24,100 +23,90 @@ export class HasuraCohortService implements IServicelocatorcohort { ) {} public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - var axios = require("axios"); + var axios = require("axios"); - let query = ""; - Object.keys(cohortCreateDto).forEach((e) => { - if ( - cohortCreateDto[e] && - cohortCreateDto[e] != "" && - e != "fieldValues" - ) { - if (Array.isArray(cohortCreateDto[e])) { - query += `${e}: "${JSON.stringify(cohortCreateDto[e])}", `; - } else { - query += `${e}: "${cohortCreateDto[e]}", `; - } + let query = ""; + Object.keys(cohortCreateDto).forEach((e) => { + if ( + cohortCreateDto[e] && + cohortCreateDto[e] != "" && + e != "fieldValues" + ) { + if (Array.isArray(cohortCreateDto[e])) { + query += `${e}: "${JSON.stringify(cohortCreateDto[e])}", `; + } else { + query += `${e}: "${cohortCreateDto[e]}", `; } - }); + } + }); - var data = { - query: `mutation CreateCohort { - insert_Cohort_one(object: {${query}}) { - cohortId - } + var data = { + query: `mutation CreateCohort { + insert_Cohort_one(object: {${query}}) { + cohortId } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + } + `, + variables: {}, + }; - const response = await axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - const result = response.data.data.insert_Cohort_one; - let fieldCreate = true; - let fieldError = null; - //create fields values - let cohortId = result?.cohortId; - let field_value_array = cohortCreateDto.fieldValues.split("|"); + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - field_values.push({ - value: fieldValues[1] ? fieldValues[1] : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0] : "", - createdBy: cohortCreateDto?.createdBy, - updatedBy: cohortCreateDto?.updatedBy, - }); - } + const response = await axios(config); + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + const result = response.data.data.insert_Cohort_one; + let fieldCreate = true; + let fieldError = null; + //create fields values + let cohortId = result?.cohortId; + let field_value_array = cohortCreateDto.fieldValues.split("|"); - const response_field_values = - await this.fieldsService.createFieldValuesBulk(field_values); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError = response_field_values?.data; - } + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + let fieldValues = field_value_array[i].split(":"); + field_values.push({ + value: fieldValues[1] ? fieldValues[1] : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0] : "", + createdBy: cohortCreateDto?.createdBy, + updatedBy: cohortCreateDto?.updatedBy, + }); } - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } else { - return new ErrorResponse({ - errorCode: fieldError?.errors[0]?.extensions?.code, - errorMessage: fieldError?.errors[0]?.message, - }); + const response_field_values = + await this.fieldsService.createFieldValuesBulk(field_values); + if (response_field_values?.data?.errors) { + fieldCreate = false; + fieldError = response_field_values?.data; } } - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); + + if (fieldCreate) { + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } else { + return new ErrorResponse({ + errorCode: fieldError?.errors[0]?.extensions?.code, + errorMessage: fieldError?.errors[0]?.message, + }); + } } } @@ -274,7 +263,7 @@ export class HasuraCohortService implements IServicelocatorcohort { if (filedsFilter) { //apply filter on fields value let response_fields_value = - await this.fieldsService.searchFieldValuesFilter(request,filedsFilter); + await this.fieldsService.searchFieldValuesFilter(filedsFilter); if (response_fields_value?.data?.errors) { return res.status(200).send({ errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, @@ -311,7 +300,6 @@ export class HasuraCohortService implements IServicelocatorcohort { } if (newCohortSearchDto) { const response = await this.searchCohortQuery( - request, tenantId, newCohortSearchDto ); @@ -489,76 +477,65 @@ export class HasuraCohortService implements IServicelocatorcohort { return cohort_fields; } public async searchCohortQuery( - request:any, tenantId: string, cohortSearchDto: CohortSearchDto ) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - var axios = require("axios"); + var axios = require("axios"); - let offset = 0; - if (cohortSearchDto.page > 1) { - offset = parseInt(cohortSearchDto.limit) * (cohortSearchDto.page - 1); - } + let offset = 0; + if (cohortSearchDto.page > 1) { + offset = parseInt(cohortSearchDto.limit) * (cohortSearchDto.page - 1); + } - let temp_filters = cohortSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + let temp_filters = cohortSearchDto.filters; + //add tenantid + let filters = new Object(temp_filters); + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(cohortSearchDto.filters).forEach((item) => { - Object.keys(cohortSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); + Object.keys(cohortSearchDto.filters).forEach((item) => { + Object.keys(cohortSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } }); - var data = { - query: `query SearchCohort($filters:Cohort_bool_exp,$limit:Int, $offset:Int) { - Cohort(where:$filters, limit: $limit, offset: $offset,) { - tenantId - programId - cohortId - parentId - referenceId - name - type - status - image - metadata - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(cohortSearchDto.limit), - offset: offset, - filters: cohortSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + }); + var data = { + query: `query SearchCohort($filters:Cohort_bool_exp,$limit:Int, $offset:Int) { + Cohort(where:$filters, limit: $limit, offset: $offset,) { + tenantId + programId + cohortId + parentId + referenceId + name + type + status + image + metadata + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(cohortSearchDto.limit), + offset: offset, + filters: cohortSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } + const response = await axios(config); + return response; } } diff --git a/src/adapters/hasura/cohortMembers.adapter.ts b/src/adapters/hasura/cohortMembers.adapter.ts index 7f36d4e9..efd1616f 100644 --- a/src/adapters/hasura/cohortMembers.adapter.ts +++ b/src/adapters/hasura/cohortMembers.adapter.ts @@ -3,7 +3,6 @@ import { HttpService } from "@nestjs/axios"; import { SuccessResponse } from "src/success-response"; import { ErrorResponse } from "src/error-response"; const resolvePath = require("object-resolve-path"); -import jwt_decode from "jwt-decode"; import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-search.dto"; import { IServicelocatorcohortMembers } from "../cohortMembersservicelocator"; @@ -18,60 +17,50 @@ export class HasuraCohortMembersService request: any, cohortMembers: CohortMembersDto ) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - var axios = require("axios"); - let query = ""; - Object.keys(cohortMembers).forEach((e) => { - if (cohortMembers[e] && cohortMembers[e] != "") { - if (Array.isArray(cohortMembers[e])) { - query += `${e}: "${JSON.stringify(cohortMembers[e])}", `; - } else { - query += `${e}: "${cohortMembers[e]}", `; - } + var axios = require("axios"); + let query = ""; + Object.keys(cohortMembers).forEach((e) => { + if (cohortMembers[e] && cohortMembers[e] != "") { + if (Array.isArray(cohortMembers[e])) { + query += `${e}: "${JSON.stringify(cohortMembers[e])}", `; + } else { + query += `${e}: "${cohortMembers[e]}", `; } - }); + } + }); - var data = { - query: `mutation CreateCohortMembers { - insert_CohortMembers_one(object: {${query}}) { - cohortMembershipId - } + var data = { + query: `mutation CreateCohortMembers { + insert_CohortMembers_one(object: {${query}}) { + cohortMembershipId } - `, - variables: {}, - }; + } + `, + variables: {}, + }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - const result = response.data.data.insert_CohortMembers_one; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - } catch (e) { - console.error(e); + const response = await axios(config); + if (response?.data?.errors) { return new ErrorResponse({ - errorCode: "400", - errorMessage: e, + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + const result = response.data.data.insert_CohortMembers_one; + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, }); } } @@ -145,83 +134,73 @@ export class HasuraCohortMembersService request: any, cohortMembersSearchDto: CohortMembersSearchDto ) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - var axios = require("axios"); + var axios = require("axios"); - let offset = 0; - if (cohortMembersSearchDto.page > 1) { - offset = - parseInt(cohortMembersSearchDto.limit) * - (cohortMembersSearchDto.page - 1); - } + let offset = 0; + if (cohortMembersSearchDto.page > 1) { + offset = + parseInt(cohortMembersSearchDto.limit) * + (cohortMembersSearchDto.page - 1); + } - let temp_filters = cohortMembersSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + let temp_filters = cohortMembersSearchDto.filters; + //add tenantid + let filters = new Object(temp_filters); + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(cohortMembersSearchDto.filters).forEach((item) => { - Object.keys(cohortMembersSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); + Object.keys(cohortMembersSearchDto.filters).forEach((item) => { + Object.keys(cohortMembersSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } }); - var data = { - query: `query SearchCohortMembers($filters:CohortMembers_bool_exp,$limit:Int, $offset:Int) { - CohortMembers(where:$filters, limit: $limit, offset: $offset,) { - tenantId - cohortMembershipId - cohortId - userId - role - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(cohortMembersSearchDto.limit), - offset: offset, - filters: cohortMembersSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + }); + var data = { + query: `query SearchCohortMembers($filters:CohortMembers_bool_exp,$limit:Int, $offset:Int) { + CohortMembers(where:$filters, limit: $limit, offset: $offset,) { + tenantId + cohortMembershipId + cohortId + userId + role + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(cohortMembersSearchDto.limit), + offset: offset, + filters: cohortMembersSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response.data.data.CohortMembers; - const cohortMembersResponse = await this.mappedResponse(result); - const count = cohortMembersResponse.length; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: cohortMembersResponse, - }); - } - } catch (e) { - console.error(e); + const response = await axios(config); + if (response?.data?.errors) { return new ErrorResponse({ - errorCode: "400", - errorMessage: e, + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + let result = response.data.data.CohortMembers; + const cohortMembersResponse = await this.mappedResponse(result); + const count = cohortMembersResponse.length; + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: cohortMembersResponse, }); } } diff --git a/src/adapters/hasura/fields.adapter.ts b/src/adapters/hasura/fields.adapter.ts index 49805cc9..c195fcd1 100644 --- a/src/adapters/hasura/fields.adapter.ts +++ b/src/adapters/hasura/fields.adapter.ts @@ -23,26 +23,18 @@ export class HasuraFieldsService implements IServicelocatorfields { //fields public async createFields(request: any, fieldsDto: FieldsDto) { - try{ - const response = await this.fieldsService.createFields(request, fieldsDto); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - const result = response.data.data.insert_Fields_one; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - } catch (e) { - console.error(e); + const response = await this.fieldsService.createFields(fieldsDto); + if (response?.data?.errors) { return new ErrorResponse({ - errorCode: "400", - errorMessage: e, + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + const result = response.data.data.insert_Fields_one; + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, }); } } @@ -70,35 +62,26 @@ export class HasuraFieldsService implements IServicelocatorfields { request: any, fieldsSearchDto: FieldsSearchDto ) { - try{ - const response = await this.fieldsService.searchFields( - request, - tenantId, - fieldsSearchDto - ); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response.data.data.Fields; - const fieldsResponse = await this.mappedResponse(result); - const count = fieldsResponse.length; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: fieldsResponse, - }); - } - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } + const response = await this.fieldsService.searchFields( + tenantId, + fieldsSearchDto + ); + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + let result = response.data.data.Fields; + const fieldsResponse = await this.mappedResponse(result); + const count = fieldsResponse.length; + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: fieldsResponse, + }); + } } public async updateFields( @@ -124,7 +107,7 @@ export class HasuraFieldsService implements IServicelocatorfields { //field values public async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { - const response = await this.fieldsService.createFieldValues(request, fieldValuesDto); + const response = await this.fieldsService.createFieldValues(fieldValuesDto); if (response?.data?.errors) { return new ErrorResponse({ errorCode: response?.data?.errors[0]?.extensions?.code, @@ -162,32 +145,23 @@ export class HasuraFieldsService implements IServicelocatorfields { request: any, fieldValuesSearchDto: FieldValuesSearchDto ) { - try{ - const response = await this.fieldsService.searchFieldValues( - request, - fieldValuesSearchDto - ); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response.data.data.FieldValues; - const fieldValuesResponse = await this.mappedResponseValues(result); - const count = fieldValuesResponse.length; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: fieldValuesResponse, - }); - } - } catch (e) { - console.error(e); + const response = await this.fieldsService.searchFieldValues( + fieldValuesSearchDto + ); + if (response?.data?.errors) { return new ErrorResponse({ - errorCode: "400", - errorMessage: e, + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + let result = response.data.data.FieldValues; + const fieldValuesResponse = await this.mappedResponseValues(result); + const count = fieldValuesResponse.length; + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: fieldValuesResponse, }); } } diff --git a/src/adapters/hasura/services/fields.service.ts b/src/adapters/hasura/services/fields.service.ts index 14c450af..0da56dbf 100644 --- a/src/adapters/hasura/services/fields.service.ts +++ b/src/adapters/hasura/services/fields.service.ts @@ -3,67 +3,53 @@ import { FieldsDto } from "src/fields/dto/fields.dto"; import { FieldsSearchDto } from "src/fields/dto/fields-search.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; -import jwt_decode from "jwt-decode"; -import { ErrorResponse } from "src/error-response"; @Injectable() export class FieldsService { constructor() {} //fields - async createFields(request: any, fieldsDto: FieldsDto) { - try{ - - const decoded: any = jwt_decode(request.headers.authorization); - var axios = require("axios"); - - //add render json object - fieldsDto = await this.addRender(fieldsDto); - - let query = ""; - Object.keys(fieldsDto).forEach((e) => { - if (fieldsDto[e] && fieldsDto[e] != "") { - if (e === "render") { - query += `${e}: ${fieldsDto[e]}, `; - } else if (Array.isArray(fieldsDto[e])) { - query += `${e}: "${JSON.stringify(fieldsDto[e])}", `; - } else { - query += `${e}: "${fieldsDto[e]}", `; - } + async createFields(fieldsDto: FieldsDto) { + var axios = require("axios"); + + //add render json object + fieldsDto = await this.addRender(fieldsDto); + + let query = ""; + Object.keys(fieldsDto).forEach((e) => { + if (fieldsDto[e] && fieldsDto[e] != "") { + if (e === "render") { + query += `${e}: ${fieldsDto[e]}, `; + } else if (Array.isArray(fieldsDto[e])) { + query += `${e}: "${JSON.stringify(fieldsDto[e])}", `; + } else { + query += `${e}: "${fieldsDto[e]}", `; } - }); + } + }); - var data = { - query: `mutation CreateFields { - insert_Fields_one(object: {${query}}) { - fieldId - } + var data = { + query: `mutation CreateFields { + insert_Fields_one(object: {${query}}) { + fieldId } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } + } + `, + variables: {}, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; } public async getFields(tenantId: string, fieldsId: any) { @@ -225,80 +211,71 @@ export class FieldsService { return response; } - async searchFields(request:any, tenantId: string, fieldsSearchDto: FieldsSearchDto) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - var axios = require("axios"); + async searchFields(tenantId: string, fieldsSearchDto: FieldsSearchDto) { + var axios = require("axios"); - let offset = 0; - if (fieldsSearchDto.page > 1) { - offset = parseInt(fieldsSearchDto.limit) * (fieldsSearchDto.page - 1); - } + let offset = 0; + if (fieldsSearchDto.page > 1) { + offset = parseInt(fieldsSearchDto.limit) * (fieldsSearchDto.page - 1); + } - let temp_filters = fieldsSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + let temp_filters = fieldsSearchDto.filters; + //add tenantid + let filters = new Object(temp_filters); + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(fieldsSearchDto.filters).forEach((item) => { - Object.keys(fieldsSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchFields($filters:Fields_bool_exp,$limit:Int, $offset:Int) { - Fields(where:$filters, limit: $limit, offset: $offset,) { - tenantId - fieldId - assetId - context - contextId - render - groupId - name - label - defaultValue - type - note - description - state - required - ordering - metadata - access - onlyUseInSubform - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(fieldsSearchDto.limit), - offset: offset, - filters: fieldsSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, + Object.keys(fieldsSearchDto.filters).forEach((item) => { + Object.keys(fieldsSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } }); - } + }); + var data = { + query: `query SearchFields($filters:Fields_bool_exp,$limit:Int, $offset:Int) { + Fields(where:$filters, limit: $limit, offset: $offset,) { + tenantId + fieldId + assetId + context + contextId + render + groupId + name + label + defaultValue + type + note + description + state + required + ordering + metadata + access + onlyUseInSubform + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(fieldsSearchDto.limit), + offset: offset, + filters: fieldsSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + const response = await axios(config); return response; } @@ -466,54 +443,43 @@ export class FieldsService { } //field values - async createFieldValues(request:any, fieldValuesDto: FieldValuesDto) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - - var axios = require("axios"); - - let query = ""; - Object.keys(fieldValuesDto).forEach((e) => { - if (fieldValuesDto[e] && fieldValuesDto[e] != "") { - if (Array.isArray(fieldValuesDto[e])) { - query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; - } else { - query += `${e}: "${fieldValuesDto[e]}", `; - } + async createFieldValues(fieldValuesDto: FieldValuesDto) { + var axios = require("axios"); + + let query = ""; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; + } else { + query += `${e}: "${fieldValuesDto[e]}", `; } - }); + } + }); - var data = { - query: `mutation CreateFieldValues { - insert_FieldValues_one(object: {${query}}) { - fieldValuesId - } + var data = { + query: `mutation CreateFieldValues { + insert_FieldValues_one(object: {${query}}) { + fieldValuesId } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } + } + `, + variables: {}, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; } - async createFieldValuesBulk(field_values: any) { var axios = require("axios"); @@ -632,118 +598,97 @@ export class FieldsService { return response; } - async searchFieldValues(request:any, fieldValuesSearchDto: FieldValuesSearchDto) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - - var axios = require("axios"); + async searchFieldValues(fieldValuesSearchDto: FieldValuesSearchDto) { + var axios = require("axios"); - let offset = 0; - if (fieldValuesSearchDto.page > 1) { - offset = - parseInt(fieldValuesSearchDto.limit) * (fieldValuesSearchDto.page - 1); - } + let offset = 0; + if (fieldValuesSearchDto.page > 1) { + offset = + parseInt(fieldValuesSearchDto.limit) * (fieldValuesSearchDto.page - 1); + } - let filters = fieldValuesSearchDto.filters; + let filters = fieldValuesSearchDto.filters; - Object.keys(fieldValuesSearchDto.filters).forEach((item) => { - Object.keys(fieldValuesSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); + Object.keys(fieldValuesSearchDto.filters).forEach((item) => { + Object.keys(fieldValuesSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } }); - var data = { - query: `query SearchFieldValues($filters:FieldValues_bool_exp,$limit:Int, $offset:Int) { - FieldValues(where:$filters, limit: $limit, offset: $offset,) { - value - fieldValuesId - itemId - fieldId - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(fieldValuesSearchDto.limit), - offset: offset, - filters: fieldValuesSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, }); - } + var data = { + query: `query SearchFieldValues($filters:FieldValues_bool_exp,$limit:Int, $offset:Int) { + FieldValues(where:$filters, limit: $limit, offset: $offset,) { + value + fieldValuesId + itemId + fieldId + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(fieldValuesSearchDto.limit), + offset: offset, + filters: fieldValuesSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; } - async searchFieldValuesFilter(request:any, filter: any) { - try{ - const decoded: any = jwt_decode(request.headers.authorization); - - let obj_filter = []; - Object.keys(filter).forEach((item) => { - Object.keys(filter[item]).forEach((e) => { - let obj_val = new Object(); - obj_val[e] = filter[item][e]; - obj_filter.push({ - fieldId: { _eq: item }, - value: obj_val, - }); + async searchFieldValuesFilter(filter: any) { + let obj_filter = []; + Object.keys(filter).forEach((item) => { + Object.keys(filter[item]).forEach((e) => { + let obj_val = new Object(); + obj_val[e] = filter[item][e]; + obj_filter.push({ + fieldId: { _eq: item }, + value: obj_val, }); }); + }); - let valuefilter = new Object({ _or: obj_filter }); + let valuefilter = new Object({ _or: obj_filter }); - var axios = require("axios"); + var axios = require("axios"); - var data = { - query: `query SearchFieldValuesFilter($valuefilter:FieldValues_bool_exp) { - FieldValues( - where:$valuefilter - ){ - itemId - } - }`, - variables: { valuefilter: valuefilter }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } + var data = { + query: `query SearchFieldValuesFilter($valuefilter:FieldValues_bool_exp) { + FieldValues( + where:$valuefilter + ){ + itemId + } + }`, + variables: { valuefilter: valuefilter }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + const response = await axios(config); + return response; } async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index b546dd17..4e876a73 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -466,9 +466,10 @@ export class HasuraUserService implements IServicelocator { if (fieldsFilter) { //apply filter on fields value + // searchfieldValuesFilter returns the contexts here userId that match the fieldId and value pair const responseFieldsValue = - await this.fieldsService.searchFieldValuesFilter(request,fieldsFilter); + await this.fieldsService.searchFieldValuesFilter(fieldsFilter); if (responseFieldsValue?.data?.errors) { return response.status(400).send({ @@ -857,7 +858,6 @@ export class HasuraUserService implements IServicelocator { ) { // function to search users within the user tables try { - const decoded: any = jwt_decode(request.headers.authorization); let offset = 0; if (userSearchDto.page > 1) { offset = parseInt(userSearchDto.limit) * (userSearchDto.page - 1); @@ -914,7 +914,6 @@ export class HasuraUserService implements IServicelocator { method: "post", url: process.env.REGISTRYHASURA, headers: { - Authorization: request.headers.authorization, "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, "Content-Type": "application/json", }, diff --git a/src/main.ts b/src/main.ts index 8cf49963..1da9a93e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,7 +20,7 @@ async function bootstrap() { .setVersion("1.0") .addTag("V1") .addApiKey( - { type: "apiKey", scheme: "bearer", bearerFormat: "JWT", name: "Authorization", in: "header" }, + { type: "apiKey", name: "Authorization", in: "header" }, "access-token" ) From 8d505f742263dc992da01cf733ed6d1f6977c09e Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 16 Feb 2024 12:25:46 +0530 Subject: [PATCH 002/408] contexttype field add --- src/fields/dto/fields.dto.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/fields/dto/fields.dto.ts b/src/fields/dto/fields.dto.ts index 460bda36..083690f1 100644 --- a/src/fields/dto/fields.dto.ts +++ b/src/fields/dto/fields.dto.ts @@ -46,6 +46,15 @@ export class FieldsDto { @Expose() contextId: string; + //contexType + @ApiProperty({ + type: String, + description: "The contexType of the fields", + default: "", + }) + @Expose() + contexType: string; + //render @ApiProperty({ type: Object, From c050907231bff20c66fd8446d158b19e23bd27e8 Mon Sep 17 00:00:00 2001 From: vaishali_k Date: Fri, 16 Feb 2024 20:53:20 +0530 Subject: [PATCH 003/408] Issue #213840 chore: attendanceCaptureImage param in get API --- src/adapters/hasura/cohort.adapter.ts | 1 + src/cohort/dto/cohort-create.dto.ts | 9 +++++++++ src/cohort/dto/cohort.dto.ts | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index a5e61c60..1854852c 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -139,6 +139,7 @@ export class HasuraCohortService implements IServicelocatorcohort { type status image + attendanceCaptureImage metadata createdAt updatedAt diff --git a/src/cohort/dto/cohort-create.dto.ts b/src/cohort/dto/cohort-create.dto.ts index b3790979..5f7446e8 100644 --- a/src/cohort/dto/cohort-create.dto.ts +++ b/src/cohort/dto/cohort-create.dto.ts @@ -74,6 +74,15 @@ export class CohortCreateDto { @Expose() status: string; + //attendanceCaptureImage + @ApiProperty({ + type: Boolean, + description: "Capture image while marking the attendance", + default: false, + }) + @Expose() + attendanceCaptureImage: Boolean; + //image @Expose() @ApiPropertyOptional({ type: "string", format: "binary" }) diff --git a/src/cohort/dto/cohort.dto.ts b/src/cohort/dto/cohort.dto.ts index 463152db..40221c78 100644 --- a/src/cohort/dto/cohort.dto.ts +++ b/src/cohort/dto/cohort.dto.ts @@ -78,6 +78,15 @@ export class CohortDto { @ApiPropertyOptional({ type: "string", format: "binary" }) image: string; + //attendanceCaptureImage + @ApiProperty({ + type: Boolean, + description: "Capture image while marking the attendance", + default: false, + }) + @Expose() + attendanceCaptureImage: Boolean; + //metadata @ApiPropertyOptional({ type: String, From 0e07e3a3ad48bc3d7290551f3e0c0cbaf28ed06c Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 19 Feb 2024 10:45:26 +0530 Subject: [PATCH 004/408] Task #213841 Add authentication for bearer token --- src/adapters/hasura/attendance.adapter.ts | 474 +++++++------ src/adapters/hasura/cohort.adapter.ts | 412 ++++++----- src/adapters/hasura/cohortMembers.adapter.ts | 216 +++--- src/adapters/hasura/fields.adapter.ts | 6 +- .../hasura/services/fields.service.ts | 657 ++++++++++-------- src/adapters/hasura/user.adapter.ts | 166 ++--- 6 files changed, 1037 insertions(+), 894 deletions(-) diff --git a/src/adapters/hasura/attendance.adapter.ts b/src/adapters/hasura/attendance.adapter.ts index db2b389f..68c2b1b5 100644 --- a/src/adapters/hasura/attendance.adapter.ts +++ b/src/adapters/hasura/attendance.adapter.ts @@ -73,49 +73,55 @@ export class AttendanceHasuraService implements IServicelocator { } public async createAttendance(request: any, attendanceDto: AttendanceDto) { - let query = ""; - Object.keys(attendanceDto).forEach((e) => { - if (attendanceDto[e] && attendanceDto[e] != "") { - query += `${e}: "${attendanceDto[e]}", `; - } - }); + try{ + let query = ""; + Object.keys(attendanceDto).forEach((e) => { + if (attendanceDto[e] && attendanceDto[e] != "") { + query += `${e}: "${attendanceDto[e]}", `; + } + }); - const data = { - query: `mutation CreateAttendance { - insert_Attendance_one(object: {${query}}) { - attendanceId + const data = { + query: `mutation CreateAttendance { + insert_Attendance_one(object: {${query}}) { + attendanceId + } } - } - `, - variables: {}, - }; + `, + variables: {}, + }; - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + const config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await this.axios(config); + const response = await this.axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: "400", - errorMessage: response.data.errors[0].message, - }); - } + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: "400", + errorMessage: response.data.errors[0].message, + }); + } - const result = response.data.data.insert_Attendance_one; + const result = response.data.data.insert_Attendance_one; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + }catch (e) { + console.error(e); + return e; + } } public async updateAttendance( @@ -123,59 +129,65 @@ export class AttendanceHasuraService implements IServicelocator { request: any, attendanceDto: AttendanceDto ) { - const attendanceSchema = new AttendanceDto(attendanceDto); - - let query = ""; - Object.keys(attendanceDto).forEach((e) => { - if ( - attendanceDto[e] && - attendanceDto[e] != "" && - Object.keys(attendanceSchema).includes(e) - ) { - query += `${e}: "${attendanceDto[e]}", `; - } - }); + try{ + const attendanceSchema = new AttendanceDto(attendanceDto); + + let query = ""; + Object.keys(attendanceDto).forEach((e) => { + if ( + attendanceDto[e] && + attendanceDto[e] != "" && + Object.keys(attendanceSchema).includes(e) + ) { + query += `${e}: "${attendanceDto[e]}", `; + } + }); - const data = { - query: `mutation UpdateAttendance($attendanceId:uuid) { - update_Attendance(where: {attendanceId: {_eq: $attendanceId}}, _set: {${query}}) { - affected_rows - returning { - attendanceId + const data = { + query: `mutation UpdateAttendance($attendanceId:uuid) { + update_Attendance(where: {attendanceId: {_eq: $attendanceId}}, _set: {${query}}) { + affected_rows + returning { + attendanceId + } } - } - }`, - variables: { - attendanceId: attendanceId, - }, - }; + }`, + variables: { + attendanceId: attendanceId, + }, + }; - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + const config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await this.axios(config); + const response = await this.axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: "400", - errorMessage: response.data.errors[0].message, - }); - } + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: "400", + errorMessage: response.data.errors[0].message, + }); + } - const result = response.data.data.update_Attendance; + const result = response.data.data.update_Attendance; - return new SuccessResponse({ - statusCode: 200, - message: "Ok. Updated Successfully", - data: result, - }); + return new SuccessResponse({ + statusCode: 200, + message: "Ok. Updated Successfully", + data: result, + }); + }catch (e) { + console.error(e); + return e; + } } public async searchAttendance( @@ -183,31 +195,129 @@ export class AttendanceHasuraService implements IServicelocator { request: any, attendanceSearchDto: AttendanceSearchDto ) { - let offset = 0; - if (attendanceSearchDto.page > 1) { - offset = - parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); - } + try{ + let offset = 0; + if (attendanceSearchDto.page > 1) { + offset = + parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); + } - attendanceSearchDto.filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(attendanceSearchDto.filters).forEach((item) => { - Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - attendanceSearchDto.filters[item][`_${e}`] = - attendanceSearchDto.filters[item][e]; - delete attendanceSearchDto.filters[item][e]; - } + attendanceSearchDto.filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + Object.keys(attendanceSearchDto.filters).forEach((item) => { + Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + attendanceSearchDto.filters[item][`_${e}`] = + attendanceSearchDto.filters[item][e]; + delete attendanceSearchDto.filters[item][e]; + } + }); }); - }); - const data = { - query: `query SearchAttendance($filters:Attendance_bool_exp,$limit:Int, $offset:Int) { - Attendance_aggregate (where:$filters, limit: $limit, offset: $offset,){ - aggregate { - count + const data = { + query: `query SearchAttendance($filters:Attendance_bool_exp,$limit:Int, $offset:Int) { + Attendance_aggregate (where:$filters, limit: $limit, offset: $offset,){ + aggregate { + count + } } - } - Attendance(where:$filters, limit: $limit, offset: $offset,) { + Attendance(where:$filters, limit: $limit, offset: $offset,) { + attendance + attendanceDate + attendanceId + tenantId + userId + remark + latitude + longitude + image + metaData + remark + syncTime + session + contextId + contextType + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(attendanceSearchDto.limit) + ? parseInt(attendanceSearchDto.limit) + : 10, + offset: offset, + filters: attendanceSearchDto.filters, + }, + }; + const config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await this.axios(config); + + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: "500", + errorMessage: response.data.errors[0].message, + }); + } + + let result = response?.data?.data?.Attendance; + + let mappedResponse = await this.mappedResponse(result); + const count = response?.data?.data?.Attendance_aggregate?.aggregate?.count; + + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: mappedResponse, + }); + + }catch (e) { + console.error(e); + return e; + } + + } + + public async attendanceByDate( + tenantId: string, + request: any, + attendanceSearchDto: AttendanceDateDto + ) { + try{ + let offset = 0; + if (attendanceSearchDto.page > 1) { + offset = + parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); + } + + const filters = attendanceSearchDto.filters; + + //add tenantid + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + + Object.keys(attendanceSearchDto.filters).forEach((item) => { + Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); + }); + + const attendanceData = { + query: `query AttendanceFilter($fromDate: date, $toDate: date, $filters: [Attendance_bool_exp!], $limit: Int, $offset: Int) { + Attendance(where: {attendanceDate: {_gte: $fromDate, _lte: $toDate}, _and: $filters}, limit: $limit, offset: $offset) { attendance attendanceDate attendanceId @@ -218,7 +328,6 @@ export class AttendanceHasuraService implements IServicelocator { longitude image metaData - remark syncTime session contextId @@ -227,133 +336,50 @@ export class AttendanceHasuraService implements IServicelocator { updatedAt createdBy updatedBy - } - }`, - variables: { - limit: parseInt(attendanceSearchDto.limit) - ? parseInt(attendanceSearchDto.limit) - : 10, - offset: offset, - filters: attendanceSearchDto.filters, - }, - }; - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await this.axios(config); - - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: response.data.errors[0].message, - }); - } - - let result = response?.data?.data?.Attendance; - - let mappedResponse = await this.mappedResponse(result); - const count = response?.data?.data?.Attendance_aggregate?.aggregate?.count; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: mappedResponse, - }); - } + } + }`, + variables: { + fromDate: attendanceSearchDto.fromDate, + toDate: attendanceSearchDto.toDate, + filters: filters, + limit: parseInt(attendanceSearchDto.limit), + offset: offset, + }, + }; + const config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: attendanceData, + }; - public async attendanceByDate( - tenantId: string, - request: any, - attendanceSearchDto: AttendanceDateDto - ) { - let offset = 0; - if (attendanceSearchDto.page > 1) { - offset = - parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); - } + const response = await this.axios(config); - const filters = attendanceSearchDto.filters; + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: "400", + errorMessage: response.data.errors[0].message, + }); + } - //add tenantid - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + const result = response.data.data.Attendance; - Object.keys(attendanceSearchDto.filters).forEach((item) => { - Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); + const mappedResponse = await this.mappedResponse(result); - const attendanceData = { - query: `query AttendanceFilter($fromDate: date, $toDate: date, $filters: [Attendance_bool_exp!], $limit: Int, $offset: Int) { - Attendance(where: {attendanceDate: {_gte: $fromDate, _lte: $toDate}, _and: $filters}, limit: $limit, offset: $offset) { - attendance - attendanceDate - attendanceId - tenantId - userId - remark - latitude - longitude - image - metaData - syncTime - session - contextId - contextType - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - fromDate: attendanceSearchDto.fromDate, - toDate: attendanceSearchDto.toDate, - filters: filters, - limit: parseInt(attendanceSearchDto.limit), - offset: offset, - }, - }; - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: attendanceData, - }; - - const response = await this.axios(config); - - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: "400", - errorMessage: response.data.errors[0].message, + return new SuccessResponse({ + statusCode: 200, + message: "Ok", + totalCount: mappedResponse?.length, + data: mappedResponse, }); + }catch (e) { + console.error(e); + return e; } - - const result = response.data.data.Attendance; - - const mappedResponse = await this.mappedResponse(result); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok", - totalCount: mappedResponse?.length, - data: mappedResponse, - }); } public async checkAndAddAttendance( diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index 1854852c..caca1e4e 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -4,6 +4,7 @@ import { HttpService } from "@nestjs/axios"; import { SuccessResponse } from "src/success-response"; import { ErrorResponse } from "src/error-response"; const resolvePath = require("object-resolve-path"); +import jwt_decode from "jwt-decode"; import { CohortDto } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { IServicelocatorcohort } from "../cohortservicelocator"; @@ -23,90 +24,99 @@ export class HasuraCohortService implements IServicelocatorcohort { ) {} public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { - var axios = require("axios"); + try{ + var axios = require("axios"); - let query = ""; - Object.keys(cohortCreateDto).forEach((e) => { - if ( - cohortCreateDto[e] && - cohortCreateDto[e] != "" && - e != "fieldValues" - ) { - if (Array.isArray(cohortCreateDto[e])) { - query += `${e}: "${JSON.stringify(cohortCreateDto[e])}", `; - } else { - query += `${e}: "${cohortCreateDto[e]}", `; + let query = ""; + Object.keys(cohortCreateDto).forEach((e) => { + if ( + cohortCreateDto[e] && + cohortCreateDto[e] != "" && + e != "fieldValues" + ) { + if (Array.isArray(cohortCreateDto[e])) { + query += `${e}: "${JSON.stringify(cohortCreateDto[e])}", `; + } else { + query += `${e}: "${cohortCreateDto[e]}", `; + } } - } - }); + }); - var data = { - query: `mutation CreateCohort { - insert_Cohort_one(object: {${query}}) { - cohortId + var data = { + query: `mutation CreateCohort { + insert_Cohort_one(object: {${query}}) { + cohortId + } } - } - `, - variables: {}, - }; + `, + variables: {}, + }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - const result = response.data.data.insert_Cohort_one; - let fieldCreate = true; - let fieldError = null; - //create fields values - let cohortId = result?.cohortId; - let field_value_array = cohortCreateDto.fieldValues.split("|"); + const response = await axios(config); + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + const result = response.data.data.insert_Cohort_one; + let fieldCreate = true; + let fieldError = null; + //create fields values + let cohortId = result?.cohortId; + let field_value_array = cohortCreateDto.fieldValues.split("|"); - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - field_values.push({ - value: fieldValues[1] ? fieldValues[1] : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0] : "", - createdBy: cohortCreateDto?.createdBy, - updatedBy: cohortCreateDto?.updatedBy, - }); - } + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + let fieldValues = field_value_array[i].split(":"); + field_values.push({ + value: fieldValues[1] ? fieldValues[1] : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0] : "", + createdBy: cohortCreateDto?.createdBy, + updatedBy: cohortCreateDto?.updatedBy, + }); + } - const response_field_values = - await this.fieldsService.createFieldValuesBulk(field_values); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError = response_field_values?.data; + const response_field_values = + await this.fieldsService.createFieldValuesBulk(field_values); + if (response_field_values?.data?.errors) { + fieldCreate = false; + fieldError = response_field_values?.data; + } } - } - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } else { - return new ErrorResponse({ - errorCode: fieldError?.errors[0]?.extensions?.code, - errorMessage: fieldError?.errors[0]?.message, - }); + if (fieldCreate) { + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } else { + return new ErrorResponse({ + errorCode: fieldError?.errors[0]?.extensions?.code, + errorMessage: fieldError?.errors[0]?.message, + }); + } } + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, + }); } } @@ -255,81 +265,91 @@ export class HasuraCohortService implements IServicelocatorcohort { cohortSearchDto: CohortSearchDto, res: any ) { - let entityFilter = cohortSearchDto; - let filedsFilter = entityFilter?.filters["fields"]; - //remove fields from filter - delete entityFilter.filters["fields"]; - let newCohortSearchDto = null; - //check fields value present or not - if (filedsFilter) { - //apply filter on fields value - let response_fields_value = - await this.fieldsService.searchFieldValuesFilter(filedsFilter); - if (response_fields_value?.data?.errors) { - return res.status(200).send({ - errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, - errorMessage: response_fields_value?.data?.errors[0]?.message, - }); - } else { - //get filter result - let result_FieldValues = response_fields_value?.data?.data?.FieldValues; - //fetch cohot id list - let cohort_id_list = []; - for (let i = 0; i < result_FieldValues.length; i++) { - cohort_id_list.push(result_FieldValues[i].itemId); + try{ + let entityFilter = cohortSearchDto; + let filedsFilter = entityFilter?.filters["fields"]; + //remove fields from filter + delete entityFilter.filters["fields"]; + let newCohortSearchDto = null; + //check fields value present or not + if (filedsFilter) { + //apply filter on fields value + let response_fields_value = + await this.fieldsService.searchFieldValuesFilter(request,filedsFilter); + if (response_fields_value?.data?.errors) { + return res.status(200).send({ + errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, + errorMessage: response_fields_value?.data?.errors[0]?.message, + }); + } else { + //get filter result + let result_FieldValues = response_fields_value?.data?.data?.FieldValues; + //fetch cohot id list + let cohort_id_list = []; + for (let i = 0; i < result_FieldValues.length; i++) { + cohort_id_list.push(result_FieldValues[i].itemId); + } + //remove duplicate entries + cohort_id_list = cohort_id_list.filter( + (item, index) => cohort_id_list.indexOf(item) === index + ); + let cohort_filter = new Object(entityFilter.filters); + cohort_filter["cohortId"] = { + _in: cohort_id_list, + }; + newCohortSearchDto = new CohortSearchDto({ + limit: entityFilter.limit, + page: entityFilter.page, + filters: cohort_filter, + }); } - //remove duplicate entries - cohort_id_list = cohort_id_list.filter( - (item, index) => cohort_id_list.indexOf(item) === index - ); - let cohort_filter = new Object(entityFilter.filters); - cohort_filter["cohortId"] = { - _in: cohort_id_list, - }; + } else { newCohortSearchDto = new CohortSearchDto({ limit: entityFilter.limit, page: entityFilter.page, - filters: cohort_filter, + filters: entityFilter.filters, }); } - } else { - newCohortSearchDto = new CohortSearchDto({ - limit: entityFilter.limit, - page: entityFilter.page, - filters: entityFilter.filters, - }); - } - if (newCohortSearchDto) { - const response = await this.searchCohortQuery( - tenantId, - newCohortSearchDto - ); - if (response?.data?.errors) { - return res.status(200).send({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response?.data?.data?.Cohort; - let cohortResponse = await this.mappedResponse(result); - //const count = cohortResponse.length; - const count = result.length; - //get cohort fields value - let result_data = await this.searchCohortFields( + if (newCohortSearchDto) { + const response = await this.searchCohortQuery( + request, tenantId, - cohortResponse + newCohortSearchDto ); + if (response?.data?.errors) { + return res.status(200).send({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + let result = response?.data?.data?.Cohort; + let cohortResponse = await this.mappedResponse(result); + //const count = cohortResponse.length; + const count = result.length; + //get cohort fields value + let result_data = await this.searchCohortFields( + request, + tenantId, + cohortResponse + ); + return res.status(200).send({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: result_data, + }); + } + } else { return res.status(200).send({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result_data, + errorCode: "filter invalid", + errorMessage: "filter invalid", }); } - } else { - return res.status(200).send({ - errorCode: "filter invalid", - errorMessage: "filter invalid", + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, }); } } @@ -457,13 +477,14 @@ export class HasuraCohortService implements IServicelocatorcohort { return cohortResponse; } - public async searchCohortFields(tenantId: string, cohorts: any) { + public async searchCohortFields(request:any ,tenantId: string, cohorts: any) { let cohort_fields = []; for (let i = 0; i < cohorts.length; i++) { let new_obj = new Object(cohorts[i]); let cohortId = new_obj["cohortId"]; //get fields let response = await this.fieldsService.getFieldsContext( + request, tenantId, "Cohort", cohortId @@ -478,65 +499,76 @@ export class HasuraCohortService implements IServicelocatorcohort { return cohort_fields; } public async searchCohortQuery( + request:any, tenantId: string, cohortSearchDto: CohortSearchDto ) { - var axios = require("axios"); + try{ + var axios = require("axios"); - let offset = 0; - if (cohortSearchDto.page > 1) { - offset = parseInt(cohortSearchDto.limit) * (cohortSearchDto.page - 1); - } + let offset = 0; + if (cohortSearchDto.page > 1) { + offset = parseInt(cohortSearchDto.limit) * (cohortSearchDto.page - 1); + } - let temp_filters = cohortSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + let temp_filters = cohortSearchDto.filters; + //add tenantid + let filters = new Object(temp_filters); + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(cohortSearchDto.filters).forEach((item) => { - Object.keys(cohortSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } + Object.keys(cohortSearchDto.filters).forEach((item) => { + Object.keys(cohortSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); }); - }); - var data = { - query: `query SearchCohort($filters:Cohort_bool_exp,$limit:Int, $offset:Int) { - Cohort(where:$filters, limit: $limit, offset: $offset,) { - tenantId - programId - cohortId - parentId - referenceId - name - type - status - image - metadata - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(cohortSearchDto.limit), - offset: offset, - filters: cohortSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + var data = { + query: `query SearchCohort($filters:Cohort_bool_exp,$limit:Int, $offset:Int) { + Cohort(where:$filters, limit: $limit, offset: $offset,) { + tenantId + programId + cohortId + parentId + referenceId + name + type + status + image + metadata + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(cohortSearchDto.limit), + offset: offset, + filters: cohortSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await axios(config); - return response; + const response = await axios(config); + return response; + + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } } } diff --git a/src/adapters/hasura/cohortMembers.adapter.ts b/src/adapters/hasura/cohortMembers.adapter.ts index efd1616f..074c5865 100644 --- a/src/adapters/hasura/cohortMembers.adapter.ts +++ b/src/adapters/hasura/cohortMembers.adapter.ts @@ -17,50 +17,59 @@ export class HasuraCohortMembersService request: any, cohortMembers: CohortMembersDto ) { - var axios = require("axios"); - let query = ""; - Object.keys(cohortMembers).forEach((e) => { - if (cohortMembers[e] && cohortMembers[e] != "") { - if (Array.isArray(cohortMembers[e])) { - query += `${e}: "${JSON.stringify(cohortMembers[e])}", `; - } else { - query += `${e}: "${cohortMembers[e]}", `; + try{ + var axios = require("axios"); + let query = ""; + Object.keys(cohortMembers).forEach((e) => { + if (cohortMembers[e] && cohortMembers[e] != "") { + if (Array.isArray(cohortMembers[e])) { + query += `${e}: "${JSON.stringify(cohortMembers[e])}", `; + } else { + query += `${e}: "${cohortMembers[e]}", `; + } } - } - }); + }); - var data = { - query: `mutation CreateCohortMembers { - insert_CohortMembers_one(object: {${query}}) { - cohortMembershipId + var data = { + query: `mutation CreateCohortMembers { + insert_CohortMembers_one(object: {${query}}) { + cohortMembershipId + } } - } - `, - variables: {}, - }; + `, + variables: {}, + }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await axios(config); - if (response?.data?.errors) { + const response = await axios(config); + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + const result = response.data.data.insert_CohortMembers_one; + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } + }catch (e) { + console.error(e); return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - const result = response.data.data.insert_CohortMembers_one; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, + errorCode: "400", + errorMessage: e, }); } } @@ -134,73 +143,82 @@ export class HasuraCohortMembersService request: any, cohortMembersSearchDto: CohortMembersSearchDto ) { - var axios = require("axios"); + try{ + var axios = require("axios"); - let offset = 0; - if (cohortMembersSearchDto.page > 1) { - offset = - parseInt(cohortMembersSearchDto.limit) * - (cohortMembersSearchDto.page - 1); - } + let offset = 0; + if (cohortMembersSearchDto.page > 1) { + offset = + parseInt(cohortMembersSearchDto.limit) * + (cohortMembersSearchDto.page - 1); + } - let temp_filters = cohortMembersSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + let temp_filters = cohortMembersSearchDto.filters; + //add tenantid + let filters = new Object(temp_filters); + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(cohortMembersSearchDto.filters).forEach((item) => { - Object.keys(cohortMembersSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } + Object.keys(cohortMembersSearchDto.filters).forEach((item) => { + Object.keys(cohortMembersSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); }); - }); - var data = { - query: `query SearchCohortMembers($filters:CohortMembers_bool_exp,$limit:Int, $offset:Int) { - CohortMembers(where:$filters, limit: $limit, offset: $offset,) { - tenantId - cohortMembershipId - cohortId - userId - role - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(cohortMembersSearchDto.limit), - offset: offset, - filters: cohortMembersSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + var data = { + query: `query SearchCohortMembers($filters:CohortMembers_bool_exp,$limit:Int, $offset:Int) { + CohortMembers(where:$filters, limit: $limit, offset: $offset,) { + tenantId + cohortMembershipId + cohortId + userId + role + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(cohortMembersSearchDto.limit), + offset: offset, + filters: cohortMembersSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; - const response = await axios(config); - if (response?.data?.errors) { + const response = await axios(config); + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + let result = response.data.data.CohortMembers; + const cohortMembersResponse = await this.mappedResponse(result); + const count = cohortMembersResponse.length; + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: cohortMembersResponse, + }); + } + }catch (e) { + console.error(e); return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response.data.data.CohortMembers; - const cohortMembersResponse = await this.mappedResponse(result); - const count = cohortMembersResponse.length; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: cohortMembersResponse, + errorCode: "400", + errorMessage: e, }); } } diff --git a/src/adapters/hasura/fields.adapter.ts b/src/adapters/hasura/fields.adapter.ts index c195fcd1..fe9b4979 100644 --- a/src/adapters/hasura/fields.adapter.ts +++ b/src/adapters/hasura/fields.adapter.ts @@ -23,7 +23,7 @@ export class HasuraFieldsService implements IServicelocatorfields { //fields public async createFields(request: any, fieldsDto: FieldsDto) { - const response = await this.fieldsService.createFields(fieldsDto); + const response = await this.fieldsService.createFields(request,fieldsDto); if (response?.data?.errors) { return new ErrorResponse({ errorCode: response?.data?.errors[0]?.extensions?.code, @@ -63,6 +63,7 @@ export class HasuraFieldsService implements IServicelocatorfields { fieldsSearchDto: FieldsSearchDto ) { const response = await this.fieldsService.searchFields( + request, tenantId, fieldsSearchDto ); @@ -107,7 +108,7 @@ export class HasuraFieldsService implements IServicelocatorfields { //field values public async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { - const response = await this.fieldsService.createFieldValues(fieldValuesDto); + const response = await this.fieldsService.createFieldValues(request,fieldValuesDto); if (response?.data?.errors) { return new ErrorResponse({ errorCode: response?.data?.errors[0]?.extensions?.code, @@ -146,6 +147,7 @@ export class HasuraFieldsService implements IServicelocatorfields { fieldValuesSearchDto: FieldValuesSearchDto ) { const response = await this.fieldsService.searchFieldValues( + request, fieldValuesSearchDto ); if (response?.data?.errors) { diff --git a/src/adapters/hasura/services/fields.service.ts b/src/adapters/hasura/services/fields.service.ts index 0da56dbf..b9eaf139 100644 --- a/src/adapters/hasura/services/fields.service.ts +++ b/src/adapters/hasura/services/fields.service.ts @@ -3,53 +3,64 @@ import { FieldsDto } from "src/fields/dto/fields.dto"; import { FieldsSearchDto } from "src/fields/dto/fields-search.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; +import jwt_decode from "jwt-decode"; +import { ErrorResponse } from "src/error-response"; @Injectable() export class FieldsService { constructor() {} //fields - async createFields(fieldsDto: FieldsDto) { - var axios = require("axios"); - - //add render json object - fieldsDto = await this.addRender(fieldsDto); - - let query = ""; - Object.keys(fieldsDto).forEach((e) => { - if (fieldsDto[e] && fieldsDto[e] != "") { - if (e === "render") { - query += `${e}: ${fieldsDto[e]}, `; - } else if (Array.isArray(fieldsDto[e])) { - query += `${e}: "${JSON.stringify(fieldsDto[e])}", `; - } else { - query += `${e}: "${fieldsDto[e]}", `; + async createFields(request:any,fieldsDto: FieldsDto) { + try{ + var axios = require("axios"); + + //add render json object + fieldsDto = await this.addRender(fieldsDto); + + let query = ""; + Object.keys(fieldsDto).forEach((e) => { + if (fieldsDto[e] && fieldsDto[e] != "") { + if (e === "render") { + query += `${e}: ${fieldsDto[e]}, `; + } else if (Array.isArray(fieldsDto[e])) { + query += `${e}: "${JSON.stringify(fieldsDto[e])}", `; + } else { + query += `${e}: "${fieldsDto[e]}", `; + } } - } - }); + }); - var data = { - query: `mutation CreateFields { - insert_Fields_one(object: {${query}}) { - fieldId + var data = { + query: `mutation CreateFields { + insert_Fields_one(object: {${query}}) { + fieldId + } } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; + `, + variables: {}, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } } public async getFields(tenantId: string, fieldsId: any) { @@ -113,171 +124,190 @@ export class FieldsService { } public async getFieldsContext( + request:any, tenantId: string, context: string, contextId: string ) { - var axios = require("axios"); + try{ + var axios = require("axios"); - var data = { - query: `query GetFields($context:String!, $contextId:uuid!, $tenantId:uuid!) { - Fields( - where:{ - _or:[ - { - tenantId:{ - _eq:$tenantId - } - context:{ - _eq:$context - } - contextId:{ - _is_null:true - } - }, - { - tenantId:{ - _eq:$tenantId - } - context:{ - _eq:$context + var data = { + query: `query GetFields($context:String!, $contextId:uuid!, $tenantId:uuid!) { + Fields( + where:{ + _or:[ + { + tenantId:{ + _eq:$tenantId + } + context:{ + _eq:$context + } + contextId:{ + _is_null:true + } + }, + { + tenantId:{ + _eq:$tenantId + } + context:{ + _eq:$context + } + contextId:{ + _eq:$contextId + } } - contextId:{ + ] + } + ){ + tenantId + fieldId + assetId + context + contextId + render + groupId + name + label + defaultValue + type + note + description + state + required + ordering + metadata + access + onlyUseInSubform + createdAt + updatedAt + createdBy + updatedBy + fieldValues: FieldValues( + where:{ + itemId:{ _eq:$contextId - } + }, } - ] + ){ + value + fieldValuesId + itemId + fieldId + createdAt + updatedAt + createdBy + updatedBy } - ){ - tenantId - fieldId - assetId - context - contextId - render - groupId - name - label - defaultValue - type - note - description - state - required - ordering - metadata - access - onlyUseInSubform - createdAt - updatedAt - createdBy - updatedBy - fieldValues: FieldValues( - where:{ - itemId:{ - _eq:$contextId - }, - } - ){ - value - fieldValuesId - itemId - fieldId - createdAt - updatedAt - createdBy - updatedBy } - } - }`, - variables: { - context: context, - contextId: contextId, - tenantId: tenantId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; + }`, + variables: { + context: context, + contextId: contextId, + tenantId: tenantId, + }, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } } - async searchFields(tenantId: string, fieldsSearchDto: FieldsSearchDto) { - var axios = require("axios"); + async searchFields(request: any, tenantId: string, fieldsSearchDto: FieldsSearchDto) { + try{ + var axios = require("axios"); - let offset = 0; - if (fieldsSearchDto.page > 1) { - offset = parseInt(fieldsSearchDto.limit) * (fieldsSearchDto.page - 1); - } + let offset = 0; + if (fieldsSearchDto.page > 1) { + offset = parseInt(fieldsSearchDto.limit) * (fieldsSearchDto.page - 1); + } - let temp_filters = fieldsSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + let temp_filters = fieldsSearchDto.filters; + //add tenantid + let filters = new Object(temp_filters); + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(fieldsSearchDto.filters).forEach((item) => { - Object.keys(fieldsSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } + Object.keys(fieldsSearchDto.filters).forEach((item) => { + Object.keys(fieldsSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); }); - }); - var data = { - query: `query SearchFields($filters:Fields_bool_exp,$limit:Int, $offset:Int) { - Fields(where:$filters, limit: $limit, offset: $offset,) { - tenantId - fieldId - assetId - context - contextId - render - groupId - name - label - defaultValue - type - note - description - state - required - ordering - metadata - access - onlyUseInSubform - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(fieldsSearchDto.limit), - offset: offset, - filters: fieldsSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; + var data = { + query: `query SearchFields($filters:Fields_bool_exp,$limit:Int, $offset:Int) { + Fields(where:$filters, limit: $limit, offset: $offset,) { + tenantId + fieldId + assetId + context + contextId + render + groupId + name + label + defaultValue + type + note + description + state + required + ordering + metadata + access + onlyUseInSubform + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(fieldsSearchDto.limit), + offset: offset, + filters: fieldsSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } } async updateFields(fieldsId: string, fieldsDto: FieldsDto) { @@ -443,42 +473,51 @@ export class FieldsService { } //field values - async createFieldValues(fieldValuesDto: FieldValuesDto) { - var axios = require("axios"); - - let query = ""; - Object.keys(fieldValuesDto).forEach((e) => { - if (fieldValuesDto[e] && fieldValuesDto[e] != "") { - if (Array.isArray(fieldValuesDto[e])) { - query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; - } else { - query += `${e}: "${fieldValuesDto[e]}", `; + async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { + try{ + var axios = require("axios"); + + let query = ""; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; + } else { + query += `${e}: "${fieldValuesDto[e]}", `; + } } - } - }); + }); - var data = { - query: `mutation CreateFieldValues { - insert_FieldValues_one(object: {${query}}) { - fieldValuesId + var data = { + query: `mutation CreateFieldValues { + insert_FieldValues_one(object: {${query}}) { + fieldValuesId + } } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; + `, + variables: {}, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } } async createFieldValuesBulk(field_values: any) { @@ -598,97 +637,115 @@ export class FieldsService { return response; } - async searchFieldValues(fieldValuesSearchDto: FieldValuesSearchDto) { - var axios = require("axios"); + async searchFieldValues(request:any, fieldValuesSearchDto: FieldValuesSearchDto) { + try{ + var axios = require("axios"); - let offset = 0; - if (fieldValuesSearchDto.page > 1) { - offset = - parseInt(fieldValuesSearchDto.limit) * (fieldValuesSearchDto.page - 1); - } + let offset = 0; + if (fieldValuesSearchDto.page > 1) { + offset = + parseInt(fieldValuesSearchDto.limit) * (fieldValuesSearchDto.page - 1); + } - let filters = fieldValuesSearchDto.filters; + let filters = fieldValuesSearchDto.filters; - Object.keys(fieldValuesSearchDto.filters).forEach((item) => { - Object.keys(fieldValuesSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } + Object.keys(fieldValuesSearchDto.filters).forEach((item) => { + Object.keys(fieldValuesSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); }); - }); - var data = { - query: `query SearchFieldValues($filters:FieldValues_bool_exp,$limit:Int, $offset:Int) { - FieldValues(where:$filters, limit: $limit, offset: $offset,) { - value - fieldValuesId - itemId - fieldId - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(fieldValuesSearchDto.limit), - offset: offset, - filters: fieldValuesSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; + var data = { + query: `query SearchFieldValues($filters:FieldValues_bool_exp,$limit:Int, $offset:Int) { + FieldValues(where:$filters, limit: $limit, offset: $offset,) { + value + fieldValuesId + itemId + fieldId + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(fieldValuesSearchDto.limit), + offset: offset, + filters: fieldValuesSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } } - async searchFieldValuesFilter(filter: any) { - let obj_filter = []; - Object.keys(filter).forEach((item) => { - Object.keys(filter[item]).forEach((e) => { - let obj_val = new Object(); - obj_val[e] = filter[item][e]; - obj_filter.push({ - fieldId: { _eq: item }, - value: obj_val, + async searchFieldValuesFilter(request:any,filter: any) { + try{ + let obj_filter = []; + Object.keys(filter).forEach((item) => { + Object.keys(filter[item]).forEach((e) => { + let obj_val = new Object(); + obj_val[e] = filter[item][e]; + obj_filter.push({ + fieldId: { _eq: item }, + value: obj_val, + }); }); }); - }); - let valuefilter = new Object({ _or: obj_filter }); + let valuefilter = new Object({ _or: obj_filter }); - var axios = require("axios"); + var axios = require("axios"); - var data = { - query: `query SearchFieldValuesFilter($valuefilter:FieldValues_bool_exp) { - FieldValues( - where:$valuefilter - ){ - itemId - } - }`, - variables: { valuefilter: valuefilter }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; + var data = { + query: `query SearchFieldValuesFilter($valuefilter:FieldValues_bool_exp) { + FieldValues( + where:$valuefilter + ){ + itemId + } + }`, + variables: { valuefilter: valuefilter }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } } async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 4e876a73..ef313638 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -261,92 +261,98 @@ export class HasuraUserService implements IServicelocator { } async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { - let query = ""; - Object.keys(userCreateDto).forEach((e) => { - if ( - userCreateDto[e] && - userCreateDto[e] !== "" && - e != "password" && - e != "fieldValues" - ) { - if (e === "role") { - query += `${e}: ${userCreateDto[e]},`; - } else if (Array.isArray(userCreateDto[e])) { - query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; - } else { - query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; + try{ + let query = ""; + Object.keys(userCreateDto).forEach((e) => { + if ( + userCreateDto[e] && + userCreateDto[e] !== "" && + e != "password" && + e != "fieldValues" + ) { + if (e === "role") { + query += `${e}: ${userCreateDto[e]},`; + } else if (Array.isArray(userCreateDto[e])) { + query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; + } else { + query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; + } } - } - }); + }); - const data = { - query: `mutation CreateUser { - insert_Users_one(object: {${query}}) { - userId + const data = { + query: `mutation CreateUser { + insert_Users_one(object: {${query}}) { + userId + } } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - const response = await this.axios(config); + `, + variables: {}, + }; - if (response?.data?.errors || userCreateDto.userId == undefined) { - return new ErrorResponse({ - errorCode: response.data.errors[0].extensions, - errorMessage: response.data.errors[0].message, - }); - } else { - const result = response.data.data.insert_Users_one; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + const response = await this.axios(config); - let fieldCreate = true; - let fieldError = null; - //create fields values - let userId = result?.userId; - let field_value_array = userCreateDto.fieldValues?.split("|"); + if (response?.data?.errors || userCreateDto.userId == undefined) { + return new ErrorResponse({ + errorCode: response.data.errors[0].extensions, + errorMessage: response.data.errors[0].message, + }); + } else { + const result = response.data.data.insert_Users_one; + + let fieldCreate = true; + let fieldError = null; + //create fields values + let userId = result?.userId; + let field_value_array = userCreateDto.fieldValues?.split("|"); + + if (field_value_array?.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + let fieldValues = field_value_array[i].split(":"); + field_values.push({ + value: fieldValues[1] ? fieldValues[1] : "", + itemId: userId, + fieldId: fieldValues[0] ? fieldValues[0] : "", + createdBy: userCreateDto?.createdBy, + updatedBy: userCreateDto?.updatedBy, + }); + } - if (field_value_array?.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - field_values.push({ - value: fieldValues[1] ? fieldValues[1] : "", - itemId: userId, - fieldId: fieldValues[0] ? fieldValues[0] : "", - createdBy: userCreateDto?.createdBy, - updatedBy: userCreateDto?.updatedBy, - }); + const response_field_values = + await this.fieldsService.createFieldValuesBulk(field_values); + if (response_field_values?.data?.errors) { + fieldCreate = false; + fieldError = response_field_values?.data; + } } - const response_field_values = - await this.fieldsService.createFieldValuesBulk(field_values); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError = response_field_values?.data; + if (fieldCreate) { + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } else { + return new ErrorResponse({ + errorCode: fieldError?.errors[0]?.extensions?.code, + errorMessage: fieldError?.errors[0]?.message, + }); } } - - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } else { - return new ErrorResponse({ - errorCode: fieldError?.errors[0]?.extensions?.code, - errorMessage: fieldError?.errors[0]?.message, - }); - } + }catch (e) { + console.error(e); + return e; } } @@ -469,7 +475,7 @@ export class HasuraUserService implements IServicelocator { // searchfieldValuesFilter returns the contexts here userId that match the fieldId and value pair const responseFieldsValue = - await this.fieldsService.searchFieldValuesFilter(fieldsFilter); + await this.fieldsService.searchFieldValuesFilter(request,fieldsFilter); if (responseFieldsValue?.data?.errors) { return response.status(400).send({ @@ -523,7 +529,7 @@ export class HasuraUserService implements IServicelocator { const count = result.length; //get user fields value - let result_data = await this.searchUserFields(tenantId, userResponse); + let result_data = await this.searchUserFields(request,tenantId, userResponse); return response.status(200).send({ statusCode: 200, @@ -825,7 +831,7 @@ export class HasuraUserService implements IServicelocator { } } - public async searchUserFields(tenantId: string, users: any) { + public async searchUserFields(request:any, tenantId: string, users: any) { // function uses field service to get extra field and respective fieldValues for each user // ****Need extra field for access via role let userWithFields = []; @@ -834,6 +840,7 @@ export class HasuraUserService implements IServicelocator { let userId = new_obj["userId"]; //get fields let response = await this.fieldsService.getFieldsContext( + request, tenantId, "Users", userId @@ -914,6 +921,7 @@ export class HasuraUserService implements IServicelocator { method: "post", url: process.env.REGISTRYHASURA, headers: { + Authorization: request.headers.authorization, "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, "Content-Type": "application/json", }, From 20ec6712cb00bd7877d739f72ce795d845aacddd Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:52:26 +0530 Subject: [PATCH 005/408] Update Jenkinsfile --- Jenkinsfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 95db6d10..50e00baa 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -10,7 +10,9 @@ pipeline { steps{ - git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' + // git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' + checkout scmGit(branches: [[name: '*/oblf-21stFeb']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git']]) + echo "========================== ***Repository cloned Successfully*** ==========================" } From 07af1f40a0dc8ab05dc7c8230e3a4d5b6d02fe86 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:56:25 +0530 Subject: [PATCH 006/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 15d0bdad..1b15dac2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: main: - container_name: shiksha-backend + container_name: shiksha-backend-oblf-21stFeb build: context: . target: development From 86de746eade589f71f2ec4403eb4c71c90b46e80 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:01:22 +0530 Subject: [PATCH 007/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1b15dac2..1a3cb37c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: main: - container_name: shiksha-backend-oblf-21stFeb + container_name: shiksha-backend-oblf-21stFeb-cicd build: context: . target: development From 54bba8c120459132f7ab17125b555f55eb2ca7a1 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:07:06 +0530 Subject: [PATCH 008/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1a3cb37c..44dc13f4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ services: - /usr/src/app/node_modules ports: - ${SERVER_PORT}:${SERVER_PORT} - - 9229:9229 + - 3000:3000 command: yarn run start:dev env_file: - .env From 37c3a00d83c0e7594409ea7fd9b3132b11922ea5 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:11:59 +0530 Subject: [PATCH 009/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 44dc13f4..d16d0a71 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: main: - container_name: shiksha-backend-oblf-21stFeb-cicd + container_name: shiksha-backend-oblf-21stFeb-cicd1 build: context: . target: development From a84a6ba7b2663206925ff65b9f833d58c4dc83ae Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:16:07 +0530 Subject: [PATCH 010/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index d16d0a71..daba4c3b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ services: - /usr/src/app/node_modules ports: - ${SERVER_PORT}:${SERVER_PORT} - - 3000:3000 + - 9229:9229 command: yarn run start:dev env_file: - .env From b36eb0152d36b26c55292b8cd34bb12649bb06b5 Mon Sep 17 00:00:00 2001 From: snehal patil Date: Wed, 21 Feb 2024 17:00:06 +0530 Subject: [PATCH 011/408] Update docker-image.yml --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 9f8bb3f1..726f1f32 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -2,7 +2,7 @@ name: Docker Image CI on: push: - branches: [ main ] + branches: [ oblf-21stFeb ] jobs: build: From a5e4c83a1e1b25950113fecfbcaaa0d1ba0aec34 Mon Sep 17 00:00:00 2001 From: snehal patil Date: Wed, 21 Feb 2024 17:03:04 +0530 Subject: [PATCH 012/408] Update docker-image.yml --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 726f1f32..bef5b4a8 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,4 +1,4 @@ -name: Docker Image CI +name: Docker Image CI on: push: From 5ebac1a295d1e13a80ec932b3a6b012e966107e6 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 26 Feb 2024 14:56:13 +0530 Subject: [PATCH 013/408] Update Jenkinsfile --- Jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 50e00baa..090905ee 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,7 +11,7 @@ pipeline { steps{ // git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' - checkout scmGit(branches: [[name: '*/oblf-21stFeb']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git']]) + checkout scmGit(branches: [[name: '*/prod-oblf']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-backend', url: 'https://github.com/tekdi/shiksha-backend.git']]) echo "========================== ***Repository cloned Successfully*** ==========================" @@ -22,8 +22,8 @@ pipeline { steps { - sh 'cp -r /shiksha/.env .' - sh 'docker build -t backend .' + sh 'cp -r /home/prasad/backend-oblf/.env .' + sh 'docker build -t backend-oblf-dgocean .' sh 'docker-compose up -d --force-recreate --no-deps' } } From da1f3b3b6823bb8dd480850c27ebd5df64817574 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 26 Feb 2024 14:56:59 +0530 Subject: [PATCH 014/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index daba4c3b..08adf3a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: main: - container_name: shiksha-backend-oblf-21stFeb-cicd1 + container_name: shiksha-backend-oblf-digiocean build: context: . target: development From 77edfc7f9c81236bffab63d405ccfd84f875407c Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:44:50 +0530 Subject: [PATCH 015/408] Update Dockerfile --- Dockerfile | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7add4912..d4d75bb4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,30 +1,13 @@ -FROM node:16-alpine As development +FROM node:20-alpine As development WORKDIR /usr/src/app -#COPY package*.json ./ +COPY package*.json ./ -COPY . . - -RUN yarn install --only=development --ignore-engines - -COPY . . - -RUN yarn run build - -FROM node:16-alpine as production - -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -WORKDIR /usr/src/app - -COPY . ./ - -RUN yarn install --only=production --ignore-engines +RUN npm install COPY . . -COPY --from=development /usr/src/app/dist ./dist +RUN npm run build -CMD ["node", "dist/main"] +CMD ["npm", "start"] From 9ff90f2cb94e307b08632214c821fce072a2cd14 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:45:55 +0530 Subject: [PATCH 016/408] Update docker-compose.yml --- docker-compose.yml | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 08adf3a4..7f349861 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,29 +18,6 @@ services: networks: - webnet restart: always - # depends_on: - # - redis - # - postgres - # redis: - # container_name: redis - # image: redis:5 - # networks: - # - webnet - # postgres: - # container_name: postgres - # image: postgres:11 - # networks: - # - webnet - # environment: - # POSTGRES_PASSWORD: ${DB_PASSWORD} - # POSTGRES_USER: ${DB_USERNAME} - # POSTGRES_DB: ${DB_DATABASE_NAME} - # PG_DATA: /var/lib/postgresql/data - # ports: - # - 5432:5432 - # volumes: - # - pgdata:/var/lib/postgresql/data networks: webnet: -# volumes: -# pgdata: + From 21814cb2be08f3d2eac943ad0a425695f97daebe Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:56:19 +0530 Subject: [PATCH 017/408] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 090905ee..4d0c0fcc 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,7 +23,7 @@ pipeline { steps { sh 'cp -r /home/prasad/backend-oblf/.env .' - sh 'docker build -t backend-oblf-dgocean .' + sh 'sudo docker build -t backend-oblf-dgocean .' sh 'docker-compose up -d --force-recreate --no-deps' } } From cfc9886c194f36ebcf284119201d09755d619e76 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:04:54 +0530 Subject: [PATCH 018/408] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4d0c0fcc..090905ee 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,7 +23,7 @@ pipeline { steps { sh 'cp -r /home/prasad/backend-oblf/.env .' - sh 'sudo docker build -t backend-oblf-dgocean .' + sh 'docker build -t backend-oblf-dgocean .' sh 'docker-compose up -d --force-recreate --no-deps' } } From f491466fd4b738f1ff21c3ea6c9092a583cfce7b Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:51:46 +0530 Subject: [PATCH 019/408] Update Jenkinsfile --- Jenkinsfile | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 090905ee..3bd2cb00 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,7 @@ pipeline { - agent any + agent { + label 'oblf-139.59.50.217' + } stages { stage('clean workspace'){ steps{ @@ -9,10 +11,7 @@ pipeline { stage('Checkout'){ steps{ - - // git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' - checkout scmGit(branches: [[name: '*/prod-oblf']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-backend', url: 'https://github.com/tekdi/shiksha-backend.git']]) - + checkout scmGit(branches: [[name: '*/prod-oblf']], extensions: [], userRemoteConfigs: [[credentialsId: 'Jenkins-github', url: 'https://github.com/tekdi/shiksha-backend.git']]) echo "========================== ***Repository cloned Successfully*** ==========================" } @@ -22,8 +21,8 @@ pipeline { steps { - sh 'cp -r /home/prasad/backend-oblf/.env .' - sh 'docker build -t backend-oblf-dgocean .' + sh 'cp -r /opt/oblf-backend/.env .' + sh 'docker build -t backend-oblf-prod .' sh 'docker-compose up -d --force-recreate --no-deps' } } From 315021393a47e5833f5b8f58f69a61baf3551f09 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:23:00 +0530 Subject: [PATCH 020/408] Rename Jenkinsfile to Jenkinsfile1 --- Jenkinsfile => Jenkinsfile1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Jenkinsfile => Jenkinsfile1 (100%) diff --git a/Jenkinsfile b/Jenkinsfile1 similarity index 100% rename from Jenkinsfile rename to Jenkinsfile1 From 7454c3789a780de843a897243c4fced3495938da Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:26:49 +0530 Subject: [PATCH 021/408] Create Jenkinsfile --- Jenkinsfile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..8e125553 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,20 @@ +pipeline { + agent any + + stages { + stage('SSH to UAT Server and Deploy') { + steps { + script { + sshagent(credentials: ['ssh-agent-uat']) { + sh """ + // ssh -o StrictHostKeyChecking=no -l ubuntu ${UAT_IP} << 'ENDSSH' + cd /home/jenkins + ./backend-deploy.sh + """ + } + } + + } + } + } +} From f4751d7b415f7d2186d9bdfa2d1e7bdc14e5567f Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:33:34 +0530 Subject: [PATCH 022/408] Update Jenkinsfile --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8e125553..dd0ad2ff 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,9 +5,9 @@ pipeline { stage('SSH to UAT Server and Deploy') { steps { script { - sshagent(credentials: ['ssh-agent-uat']) { + sshagent(credentials: ['Jenkins-agent']){ sh """ - // ssh -o StrictHostKeyChecking=no -l ubuntu ${UAT_IP} << 'ENDSSH' + ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' cd /home/jenkins ./backend-deploy.sh """ From 8f955737adfda8f7a4de91ecb6b932934a7a85b8 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:38:19 +0530 Subject: [PATCH 023/408] Update Jenkinsfile --- Jenkinsfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index dd0ad2ff..0190e428 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,8 +8,9 @@ pipeline { sshagent(credentials: ['Jenkins-agent']){ sh """ ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' - cd /home/jenkins - ./backend-deploy.sh + sh 'cp -r /opt/oblf-backend/.env .' + sh 'docker build -t backend-oblf-prod .' + sh 'docker-compose up -d --force-recreate --no-deps' """ } } From 798fc808bd97103bb18874d85c94e8114f377251 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:02:30 +0530 Subject: [PATCH 024/408] Update Jenkinsfile --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 0190e428..d447c742 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,6 +8,7 @@ pipeline { sshagent(credentials: ['Jenkins-agent']){ sh """ ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' + 'echo Hello, remote world!' sh 'cp -r /opt/oblf-backend/.env .' sh 'docker build -t backend-oblf-prod .' sh 'docker-compose up -d --force-recreate --no-deps' From e2a0292cc03f5fafa2bbc155f630697cdc896ed4 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:03:43 +0530 Subject: [PATCH 025/408] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index d447c742..4de23d1b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ pipeline { script { sshagent(credentials: ['Jenkins-agent']){ sh """ - ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' + sudo ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' 'echo Hello, remote world!' sh 'cp -r /opt/oblf-backend/.env .' sh 'docker build -t backend-oblf-prod .' From d0c3e0fff64ce03f4e2b377172167504d5448f41 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:20:39 +0530 Subject: [PATCH 026/408] Update Jenkinsfile --- Jenkinsfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4de23d1b..31b8e91e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,11 +7,11 @@ pipeline { script { sshagent(credentials: ['Jenkins-agent']){ sh """ - sudo ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' - 'echo Hello, remote world!' - sh 'cp -r /opt/oblf-backend/.env .' - sh 'docker build -t backend-oblf-prod .' - sh 'docker-compose up -d --force-recreate --no-deps' + ssh -tt -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' + + cp -r /opt/oblf-backend/.env . + docker build -t backend-oblf-prod . + docker-compose up -d --force-recreate --no-deps """ } } From 70e3f676ffb700652d3fe4c68d00a383cddd1eaf Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:37:58 +0530 Subject: [PATCH 027/408] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 31b8e91e..e9cf3377 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ pipeline { script { sshagent(credentials: ['Jenkins-agent']){ sh """ - ssh -tt -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' + ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' cp -r /opt/oblf-backend/.env . docker build -t backend-oblf-prod . From ced017452c482e6f09632bcbc6088cfbbac5b695 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:58:54 +0530 Subject: [PATCH 028/408] Update Jenkinsfile --- Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e9cf3377..6dcb0b8c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,8 +8,7 @@ pipeline { sshagent(credentials: ['Jenkins-agent']){ sh """ ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' - - cp -r /opt/oblf-backend/.env . + cd /home/jenkins docker build -t backend-oblf-prod . docker-compose up -d --force-recreate --no-deps """ From 28dab8218c870a45b47f2f2e7fd684f093718a42 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 14:05:57 +0530 Subject: [PATCH 029/408] Update Jenkinsfile --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 6dcb0b8c..fc3a3b4d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,6 +9,7 @@ pipeline { sh """ ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' cd /home/jenkins + git clone -b prod-oblf https://github.com/tekdi/shiksha-backend.git docker build -t backend-oblf-prod . docker-compose up -d --force-recreate --no-deps """ From e119de95d0d1c6fe976e3251f9488f871281f322 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 14:47:23 +0530 Subject: [PATCH 030/408] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index fc3a3b4d..adddacb9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ pipeline { sh """ ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' cd /home/jenkins - git clone -b prod-oblf https://github.com/tekdi/shiksha-backend.git + ./deploy.sh docker build -t backend-oblf-prod . docker-compose up -d --force-recreate --no-deps """ From 42074236eee9e38dbd0f2d60057198092f643d0c Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 15:45:58 +0530 Subject: [PATCH 031/408] Update docker-compose.yml --- docker-compose.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7f349861..90bbde9f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,9 +3,10 @@ version: '3.7' services: main: container_name: shiksha-backend-oblf-digiocean - build: - context: . - target: development + image name: backend-oblf-prod + #build: + #context: . + # target: development volumes: - .:/usr/src/app - /usr/src/app/node_modules From 197b3759206cc1651f77b4451cdb4c313034645d Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 15:49:01 +0530 Subject: [PATCH 032/408] Rename docker-compose.yml to docker-compose.yml1 --- docker-compose.yml => docker-compose.yml1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docker-compose.yml => docker-compose.yml1 (100%) diff --git a/docker-compose.yml b/docker-compose.yml1 similarity index 100% rename from docker-compose.yml rename to docker-compose.yml1 From a5d11d0b02ee66fc446497a72627d042ba86c188 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 15:49:13 +0530 Subject: [PATCH 033/408] Rename Dockerfile to Dockerfile1 --- Dockerfile => Dockerfile1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Dockerfile => Dockerfile1 (100%) diff --git a/Dockerfile b/Dockerfile1 similarity index 100% rename from Dockerfile rename to Dockerfile1 From db4e8ff1cb8693bf528a836b0f37c9163df4fb27 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:40:33 +0530 Subject: [PATCH 034/408] Update Jenkinsfile --- Jenkinsfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index adddacb9..8808942f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -10,8 +10,6 @@ pipeline { ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' cd /home/jenkins ./deploy.sh - docker build -t backend-oblf-prod . - docker-compose up -d --force-recreate --no-deps """ } } From 831b4b1327dd81c9135b491b28d44feeca18a727 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Wed, 6 Mar 2024 16:29:43 +0530 Subject: [PATCH 035/408] Delete Dockerfile1 --- Dockerfile1 | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 Dockerfile1 diff --git a/Dockerfile1 b/Dockerfile1 deleted file mode 100644 index d4d75bb4..00000000 --- a/Dockerfile1 +++ /dev/null @@ -1,13 +0,0 @@ -FROM node:20-alpine As development - -WORKDIR /usr/src/app - -COPY package*.json ./ - -RUN npm install - -COPY . . - -RUN npm run build - -CMD ["npm", "start"] From fe4448d607e288cfbf09d3afb538632d0023ca79 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Wed, 6 Mar 2024 16:30:04 +0530 Subject: [PATCH 036/408] Delete Jenkinsfile1 --- Jenkinsfile1 | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 Jenkinsfile1 diff --git a/Jenkinsfile1 b/Jenkinsfile1 deleted file mode 100644 index 3bd2cb00..00000000 --- a/Jenkinsfile1 +++ /dev/null @@ -1,31 +0,0 @@ -pipeline { - agent { - label 'oblf-139.59.50.217' - } - stages { - stage('clean workspace'){ - steps{ - cleanWs() - } - } - stage('Checkout'){ - - steps{ - checkout scmGit(branches: [[name: '*/prod-oblf']], extensions: [], userRemoteConfigs: [[credentialsId: 'Jenkins-github', url: 'https://github.com/tekdi/shiksha-backend.git']]) - echo "========================== ***Repository cloned Successfully*** ==========================" - - } - } - - stage ('Build&Deploy') { - - steps { - - sh 'cp -r /opt/oblf-backend/.env .' - sh 'docker build -t backend-oblf-prod .' - sh 'docker-compose up -d --force-recreate --no-deps' - } - } - - } -} From 57cd7c4bd7cf923cca1cf8f3b084914fa6fc64a9 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Wed, 6 Mar 2024 16:30:16 +0530 Subject: [PATCH 037/408] Delete docker-compose.yml1 --- docker-compose.yml1 | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 docker-compose.yml1 diff --git a/docker-compose.yml1 b/docker-compose.yml1 deleted file mode 100644 index 90bbde9f..00000000 --- a/docker-compose.yml1 +++ /dev/null @@ -1,24 +0,0 @@ -version: '3.7' - -services: - main: - container_name: shiksha-backend-oblf-digiocean - image name: backend-oblf-prod - #build: - #context: . - # target: development - volumes: - - .:/usr/src/app - - /usr/src/app/node_modules - ports: - - ${SERVER_PORT}:${SERVER_PORT} - - 9229:9229 - command: yarn run start:dev - env_file: - - .env - networks: - - webnet - restart: always -networks: - webnet: - From c21661671d036baed114e14a09462699dce08e78 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:56:39 +0530 Subject: [PATCH 038/408] Create prod-oblf.yml --- .github/workflows/prod-oblf.yml | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/prod-oblf.yml diff --git a/.github/workflows/prod-oblf.yml b/.github/workflows/prod-oblf.yml new file mode 100644 index 00000000..be9e0bfd --- /dev/null +++ b/.github/workflows/prod-oblf.yml @@ -0,0 +1,42 @@ +name: Deploy to DEV +on: + push: + branches: + - main +jobs: + build: + name: Generate Build and Deploy to DEV + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node Env + uses: actions/setup-node@v3 + with: + node-version: 21.1.0 + + - name: Deploy to Server 1 + uses: easingthemes/ssh-deploy@main + env: + SSH_PRIVATE_KEY: ${{ secrets.EC2_SSH_KEY }} + REMOTE_HOST: ${{ secrets.HOST_DNS }} + REMOTE_USER: ${{ secrets.USERNAME }} + TARGET: ${{ secrets.TARGET_DIR }} + + - name: Set up SSH key + run: | + mkdir -p ~/.ssh + echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + # Add the SSH key to the known_hosts file (replace hostname with your actual hostname) + ssh-keyscan -H ${{ secrets.HOST_DNS }} >> ~/.ssh/known_hosts + sudo apt-get install sshpass + + - name: Deploy to server + run: | + sshpass -p '${{ secrets.EC2_SSH_KEY }}' ssh -v -o StrictHostKeyChecking=no ${{ secrets.USERNAME }}@${{ secrets.HOST_DNS }} <<'ENDSSH' + cd /home/ubuntu/onest/onest-vistar-backend-githubaction + ./deploy.sh + ENDSSH + From 02bde95174ca0ffd18793cc7ae316edd7dc7d790 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:06:42 +0530 Subject: [PATCH 039/408] Update prod-oblf.yml --- .github/workflows/prod-oblf.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/prod-oblf.yml b/.github/workflows/prod-oblf.yml index be9e0bfd..50b63bfc 100644 --- a/.github/workflows/prod-oblf.yml +++ b/.github/workflows/prod-oblf.yml @@ -2,7 +2,7 @@ name: Deploy to DEV on: push: branches: - - main + - prod-oblf jobs: build: name: Generate Build and Deploy to DEV @@ -21,7 +21,7 @@ jobs: env: SSH_PRIVATE_KEY: ${{ secrets.EC2_SSH_KEY }} REMOTE_HOST: ${{ secrets.HOST_DNS }} - REMOTE_USER: ${{ secrets.USERNAME }} + REMOTE_USER: ${{ secrets.USERNAME_OBLF }} TARGET: ${{ secrets.TARGET_DIR }} - name: Set up SSH key @@ -35,7 +35,7 @@ jobs: - name: Deploy to server run: | - sshpass -p '${{ secrets.EC2_SSH_KEY }}' ssh -v -o StrictHostKeyChecking=no ${{ secrets.USERNAME }}@${{ secrets.HOST_DNS }} <<'ENDSSH' + sshpass -p '${{ secrets.EC2_SSH_KEY }}' ssh -v -o StrictHostKeyChecking=no ${{ secrets.USERNAME_OBLF }}@${{ secrets.HOST_DNS }} <<'ENDSSH' cd /home/ubuntu/onest/onest-vistar-backend-githubaction ./deploy.sh ENDSSH From 1559bbab9e3734ec27abe028396fca736ae16fd1 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:34:46 +0530 Subject: [PATCH 040/408] Update prod-oblf.yml --- .github/workflows/prod-oblf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-oblf.yml b/.github/workflows/prod-oblf.yml index 50b63bfc..622e3cca 100644 --- a/.github/workflows/prod-oblf.yml +++ b/.github/workflows/prod-oblf.yml @@ -36,7 +36,7 @@ jobs: - name: Deploy to server run: | sshpass -p '${{ secrets.EC2_SSH_KEY }}' ssh -v -o StrictHostKeyChecking=no ${{ secrets.USERNAME_OBLF }}@${{ secrets.HOST_DNS }} <<'ENDSSH' - cd /home/ubuntu/onest/onest-vistar-backend-githubaction + cd /home/oblf-21Feb/oblf-githubaction-backend ./deploy.sh ENDSSH From bad1aaaaf0f03b5d0b9138d340a1d4e5a34b27f2 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 14 Mar 2024 18:59:56 +0530 Subject: [PATCH 041/408] Added Create User API for Testing --- package-lock.json | 1456 +++++++++++++++++++++-- package.json | 2 + src/adapters/auth/auth.adapter.ts | 3 +- src/adapters/hasura/user.adapter.ts | 1 - src/app.module.ts | 6 +- src/auth/auth.controller.ts | 1 + src/common/database.module.ts | 26 + src/common/keycloak.ts | 162 +++ src/main.ts | 24 +- src/user/entities/field-entities.ts | 33 + src/user/entities/user-create-entity.ts | 55 + src/user/user.controller.ts | 27 +- src/user/user.module.ts | 10 +- src/user/user.service.ts | 111 ++ 14 files changed, 1792 insertions(+), 125 deletions(-) create mode 100644 src/common/database.module.ts create mode 100644 src/common/keycloak.ts create mode 100644 src/user/entities/field-entities.ts create mode 100644 src/user/entities/user-create-entity.ts create mode 100644 src/user/user.service.ts diff --git a/package-lock.json b/package-lock.json index 2b66cd26..f438591c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@nestjs/platform-express": "^8.0.0", "@nestjs/schedule": "^1.1.0", "@nestjs/swagger": "^5.2.0", + "@nestjs/typeorm": "^10.0.2", "axios": "^0.26.1", "cache-manager": "^3.6.1", "class-transformer": "^0.5.1", @@ -31,6 +32,7 @@ "node-cron": "^3.0.1", "node-schedule": "^2.1.0", "object-resolve-path": "^1.1.1", + "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", @@ -834,7 +836,7 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 12" } @@ -843,7 +845,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-consumer": "0.8.0" }, @@ -891,6 +893,102 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "peer": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "peer": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "peer": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "peer": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1661,6 +1759,33 @@ } } }, + "node_modules/@nestjs/typeorm": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", + "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", + "dependencies": { + "uuid": "9.0.1" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.2.0", + "typeorm": "^0.3.0" + } + }, + "node_modules/@nestjs/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1713,6 +1838,16 @@ "npm": ">=5.0.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "peer": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -1731,6 +1866,12 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", + "peer": true + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1744,25 +1885,25 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "devOptional": true }, "node_modules/@types/babel__core": { "version": "7.1.18", @@ -2443,7 +2584,7 @@ "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -2504,7 +2645,7 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.0" } @@ -2592,7 +2733,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2611,6 +2751,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "peer": true + }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -2624,6 +2770,15 @@ "node": ">= 8" } }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "peer": true, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", @@ -2633,7 +2788,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "node_modules/argparse": { "version": "2.0.1", @@ -2780,7 +2935,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -2977,6 +3131,14 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, "node_modules/busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -3154,6 +3316,33 @@ "node": ">=8" } }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "peer": true, + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "peer": true + }, "node_modules/cli-spinners": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", @@ -3194,7 +3383,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -3424,7 +3612,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "node_modules/cron": { "version": "1.8.2", @@ -3450,7 +3638,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3498,11 +3685,16 @@ "node": ">=10" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "peer": true + }, "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -3622,7 +3814,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.3.1" } @@ -3697,6 +3889,12 @@ "node": ">=12" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "peer": true + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -3731,8 +3929,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -3783,7 +3980,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -4422,6 +4618,34 @@ } } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.1.tgz", @@ -4638,7 +4862,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -4828,6 +5051,15 @@ "node": ">=8" } }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "peer": true, + "engines": { + "node": "*" + } + }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -4912,7 +5144,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -5106,7 +5337,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -5209,8 +5439,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -5295,6 +5524,24 @@ "node": ">=6" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "peer": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -6396,7 +6643,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, "node_modules/makeerror": { "version": "1.0.12", @@ -6524,6 +6771,15 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "peer": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -6594,6 +6850,17 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "peer": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6921,6 +7188,11 @@ "node": ">=6" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6954,8 +7226,16 @@ "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "peer": true, + "dependencies": { + "parse5": "^6.0.1" + } }, "node_modules/parseurl": { "version": "1.3.3", @@ -6986,7 +7266,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -6997,6 +7276,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "peer": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "peer": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-to-regexp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", @@ -7011,6 +7315,89 @@ "node": ">=8" } }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -7059,6 +7446,41 @@ "node": ">=4" } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -7297,7 +7719,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7584,11 +8005,23 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -7600,7 +8033,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -7687,6 +8119,14 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -7752,7 +8192,21 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7766,7 +8220,19 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8067,6 +8533,27 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "peer": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "peer": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -8237,7 +8724,7 @@ "version": "10.7.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", @@ -8396,11 +8883,280 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typeorm": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", + "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", + "peer": true, + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "cli-highlight": "^2.1.11", + "dayjs": "^1.11.9", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "glob": "^10.3.10", + "mkdirp": "^2.1.3", + "reflect-metadata": "^0.2.1", + "sha.js": "^2.4.11", + "tslib": "^2.5.0", + "uuid": "^9.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">=16.13.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0", + "@sap/hana-client": "^2.12.25", + "better-sqlite3": "^7.1.2 || ^8.0.0 || ^9.0.0", + "hdb-pool": "^0.1.6", + "ioredis": "^5.0.4", + "mongodb": "^5.8.0", + "mssql": "^9.1.1 || ^10.0.1", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^6.3.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typeorm/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/typeorm/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/typeorm/node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/typeorm/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "peer": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "peer": true, + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/reflect-metadata": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", + "peer": true + }, + "node_modules/typeorm/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "peer": true + }, + "node_modules/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/typeorm/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/typeorm/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/typescript": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8466,7 +9222,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", - "dev": true + "devOptional": true }, "node_modules/v8-to-istanbul": { "version": "8.1.1", @@ -8666,7 +9422,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -8745,14 +9500,31 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi": { + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -8827,7 +9599,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -8850,7 +9621,6 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -8868,7 +9638,6 @@ "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, "engines": { "node": ">=10" } @@ -8877,7 +9646,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -9471,13 +10240,13 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true + "devOptional": true }, "@cspotcode/source-map-support": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "dev": true, + "devOptional": true, "requires": { "@cspotcode/source-map-consumer": "0.8.0" } @@ -9516,6 +10285,71 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "peer": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "peer": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "peer": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "peer": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "peer": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "peer": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "peer": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -10073,6 +10907,21 @@ "tslib": "2.3.1" } }, + "@nestjs/typeorm": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", + "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", + "requires": { + "uuid": "9.0.1" + }, + "dependencies": { + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -10109,6 +10958,13 @@ "node-fetch": "^2.6.1" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "peer": true + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -10127,6 +10983,12 @@ "@sinonjs/commons": "^1.7.0" } }, + "@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", + "peer": true + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -10137,25 +10999,25 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "devOptional": true }, "@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "devOptional": true }, "@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "devOptional": true }, "@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "devOptional": true }, "@types/babel__core": { "version": "7.1.18", @@ -10756,7 +11618,7 @@ "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true + "devOptional": true }, "acorn-globals": { "version": "6.0.0", @@ -10800,7 +11662,7 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true + "devOptional": true }, "agent-base": { "version": "6.0.2", @@ -10864,8 +11726,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -10875,6 +11736,12 @@ "color-convert": "^2.0.1" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "peer": true + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -10885,6 +11752,12 @@ "picomatch": "^2.0.4" } }, + "app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "peer": true + }, "append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", @@ -10894,7 +11767,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "argparse": { "version": "2.0.1", @@ -11016,8 +11889,7 @@ "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "binary-extensions": { "version": "2.2.0", @@ -11165,6 +12037,11 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -11294,6 +12171,28 @@ "restore-cursor": "^3.1.0" } }, + "cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "peer": true, + "requires": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "dependencies": { + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "peer": true + } + } + }, "cli-spinners": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", @@ -11320,7 +12219,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -11517,7 +12415,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "cron": { "version": "1.8.2", @@ -11540,7 +12438,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -11581,11 +12478,16 @@ "whatwg-url": "^8.0.0" } }, + "dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "peer": true + }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -11676,7 +12578,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "devOptional": true }, "diff-sequences": { "version": "27.5.1", @@ -11729,6 +12631,12 @@ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.2.tgz", "integrity": "sha512-vKKAk+VOzAWOV/dPIeSYqhgC/TQY+6L6Ibkzfsr8xd1stdBsTuGu9asCOXgbYbBeS+f2Y6lqqEuw7riOA+xEUQ==" }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "peer": true + }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -11757,8 +12665,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -11802,8 +12709,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-html": { "version": "1.0.3", @@ -12290,6 +13196,24 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "peer": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "peer": true + } + } + }, "fork-ts-checker-webpack-plugin": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.1.tgz", @@ -12442,8 +13366,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.1.1", @@ -12570,6 +13493,12 @@ "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", "dev": true }, + "highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "peer": true + }, "html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -12635,8 +13564,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.2.0", @@ -12774,8 +13702,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-generator-fn": { "version": "2.1.0", @@ -12845,8 +13772,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -12912,6 +13838,16 @@ "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==" }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "peer": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -13824,7 +14760,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, "makeerror": { "version": "1.0.12", @@ -13919,6 +14855,12 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "peer": true + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -13976,6 +14918,17 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "peer": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -14224,6 +15177,11 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -14248,8 +15206,16 @@ "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "peer": true, + "requires": { + "parse5": "^6.0.1" + } }, "parseurl": { "version": "1.3.3", @@ -14270,8 +15236,7 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", @@ -14279,6 +15244,24 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "peer": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "peer": true + } + } + }, "path-to-regexp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", @@ -14290,6 +15273,68 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-cloudflare": "^1.1.1", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "requires": {} + }, + "pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "requires": { + "split2": "^4.1.0" + } + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -14323,6 +15368,29 @@ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -14494,8 +15562,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-from-string": { "version": "2.0.2", @@ -14693,11 +15760,20 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "peer": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -14705,8 +15781,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shelljs": { "version": "0.8.5", @@ -14775,6 +15850,11 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -14827,7 +15907,17 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "peer": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -14838,7 +15928,15 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "peer": true, "requires": { "ansi-regex": "^5.0.1" } @@ -15047,6 +16145,24 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "peer": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "peer": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -15160,7 +16276,7 @@ "version": "10.7.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", - "dev": true, + "devOptional": true, "requires": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", @@ -15277,11 +16393,139 @@ "is-typedarray": "^1.0.0" } }, + "typeorm": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", + "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", + "peer": true, + "requires": { + "@sqltools/formatter": "^1.2.5", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "cli-highlight": "^2.1.11", + "dayjs": "^1.11.9", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "glob": "^10.3.10", + "mkdirp": "^2.1.3", + "reflect-metadata": "^0.2.1", + "sha.js": "^2.4.11", + "tslib": "^2.5.0", + "uuid": "^9.0.0", + "yargs": "^17.6.2" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "peer": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "peer": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "peer": true + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "peer": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "peer": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "peer": true + }, + "reflect-metadata": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", + "peer": true + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "peer": true + }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "peer": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "peer": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "peer": true + } + } + }, "typescript": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", - "dev": true + "devOptional": true }, "universalify": { "version": "2.0.0", @@ -15328,7 +16572,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", - "dev": true + "devOptional": true }, "v8-to-istanbul": { "version": "8.1.1", @@ -15485,7 +16729,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -15543,7 +16786,17 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "peer": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -15594,8 +16847,7 @@ "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "4.0.0", @@ -15612,7 +16864,6 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -15626,14 +16877,13 @@ "yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "devOptional": true } } } diff --git a/package.json b/package.json index dd07daad..a470ee4c 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@nestjs/platform-express": "^8.0.0", "@nestjs/schedule": "^1.1.0", "@nestjs/swagger": "^5.2.0", + "@nestjs/typeorm": "^10.0.2", "axios": "^0.26.1", "cache-manager": "^3.6.1", "class-transformer": "^0.5.1", @@ -43,6 +44,7 @@ "node-cron": "^3.0.1", "node-schedule": "^2.1.0", "object-resolve-path": "^1.1.1", + "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", diff --git a/src/adapters/auth/auth.adapter.ts b/src/adapters/auth/auth.adapter.ts index 9a5dea91..fd0b0007 100644 --- a/src/adapters/auth/auth.adapter.ts +++ b/src/adapters/auth/auth.adapter.ts @@ -10,6 +10,7 @@ export class HasuraAuthService { public async login(request: any, response: any, loginDto: AuthDto) { const qs = require("qs"); + console.log(loginDto); const data = qs.stringify({ username: loginDto.username, password: loginDto.password, @@ -17,7 +18,7 @@ export class HasuraAuthService { client_id: "hasura", client_secret: process.env.KEYCLOAK_HASURA_CLIENT_SECRET, }); - + console.log(data); const config = { method: "post", url: process.env.KEYCLOAK + process.env.KEYCLOAK_USER_TOKEN, diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index b546dd17..97c8e9e6 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -278,7 +278,6 @@ export class HasuraUserService implements IServicelocator { } } }); - const data = { query: `mutation CreateUser { insert_Users_one(object: {${query}}) { diff --git a/src/app.module.ts b/src/app.module.ts index 34f9cefd..ce3bdf25 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -30,6 +30,7 @@ import { CohortModule } from "./cohort/cohort.module"; import { CohortMembersModule } from "./cohortMembers/cohortMembers.module"; import { FieldsModule } from "./fields/fields.module"; import { AuthModule } from "./auth/auth.module"; +import { DatabaseModule } from "./common/database.module"; // Below modules no longer required in Shiksha 2.0 // import { GroupModule } from "./group/group.module"; // import { GroupMembershipModule } from "./groupMembership/groupMembership.module"; @@ -37,7 +38,7 @@ import { AuthModule } from "./auth/auth.module"; @Module({ imports: [ - ConfigModule.forRoot(), + ConfigModule.forRoot({ isGlobal: true }), MulterModule.register({ dest: "./uploads", }), @@ -67,7 +68,8 @@ import { AuthModule } from "./auth/auth.module"; CohortModule, CohortMembersModule, FieldsModule, - AuthModule + AuthModule, + DatabaseModule ], controllers: [AppController], providers: [AppService], diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index a8821917..120a9704 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -42,6 +42,7 @@ export class AuthController { @Res() response: Response, @Body() authDto: AuthDto ) { + console.log(request) return this.authService.login(request, response, authDto); } } diff --git a/src/common/database.module.ts b/src/common/database.module.ts new file mode 100644 index 00000000..90010cf2 --- /dev/null +++ b/src/common/database.module.ts @@ -0,0 +1,26 @@ +import { Module } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { User } from 'src/user/entities/user-create-entity'; + +@Module({ + imports: [ + TypeOrmModule.forRootAsync({ + useFactory: (configService: ConfigService) => ({ + type: 'postgres', + host: configService.get('POSTGRES_HOST'), + port: configService.get('POSTGRES_PORT'), + database: configService.get('POSTGRES_DATABASE'), + username: configService.get('POSTGRES_USERNAME'), + password: configService.get('POSTGRES_PASSWORD'), + // entities: [ + // User + // ], + autoLoadEntities: true, + }), + inject: [ConfigService], + }), + ], + providers: [ConfigService], +}) +export class DatabaseModule {} diff --git a/src/common/keycloak.ts b/src/common/keycloak.ts new file mode 100644 index 00000000..8904e1be --- /dev/null +++ b/src/common/keycloak.ts @@ -0,0 +1,162 @@ +function getUserRole(userRoles: string[]) { + if (userRoles.includes("systemAdmin")) { + return "systemAdmin"; + } else if (userRoles.includes("facilitator")) { + return "facilitator"; + } else if (userRoles.includes("beneficiary")) { + return "beneficiary"; + } else return "user"; + } + + function getUserGroup(role: string) { + switch (role) { + case "systemAdmin": + return "systemAdmin"; + case "facilitator": + return "facilitator"; + default: + return "beneficiary"; + } + } + + async function getKeycloakAdminToken() { + const axios = require("axios"); + const qs = require("qs"); + const data = qs.stringify({ + username: process.env.KEYCLOAK_USERNAME, + password: process.env.KEYCLOAK_PASSWORD, + grant_type: "password", + client_id: "admin-cli", + }); + + const config = { + method: "post", + url: process.env.KEYCLOAK + process.env.KEYCLOAK_ADMIN_TOKEN, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + data: data, + }; + + let res; + try { + res = await axios(config); + } catch (error) { + console.log(error, "err"); + } + + return res; + } + + async function createUserInKeyCloak(query, token) { + const axios = require("axios"); + const name = query.name; + const nameParts = name.split(" "); + let lname = ""; + + if (nameParts[2]) { + lname = nameParts[2]; + } else if (nameParts[1]) { + lname = nameParts[1]; + } + if (!query.password) { + return "User cannot be created, Password missing"; + } + + const data = JSON.stringify({ + firstName: nameParts[0], + lastName: lname, + enabled: "true", + username: query.username, + groups: [getUserGroup(query.role)], + credentials: [ + { + temporary: "false", + type: "password", + value: query.password, + }, + ], + }); + + const config = { + method: "post", + url: process.env.KEYCLOAK + process.env.KEYCLOAK_ADMIN, + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + data: data, + }; + + let userResponse; + try { + userResponse = await axios(config); + } catch (e) { + console.log(e.response, "Keycloak Creation error"); + return e; + } + + const userString = userResponse.headers.location; + const index = userString.lastIndexOf("/"); + const userId = userString.substring(index + 1); + + return userId; + } + + async function checkIfEmailExistsInKeycloak(email, token) { + const axios = require("axios"); + const config = { + method: "get", + url: process.env.KEYCLOAK + process.env.KEYCLOAK_ADMIN + `?email=${email}`, + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + }; + + let userResponse; + try { + userResponse = await axios(config); + } catch (e) { + console.log(e, "Keycloak error - email"); + return e; + } + + return userResponse; + } + + async function checkIfUsernameExistsInKeycloak(username, token) { + // console.log(username); + const axios = require("axios"); + const config = { + method: "get", + url: + process.env.KEYCLOAK + + process.env.KEYCLOAK_ADMIN + + `?username=${username}`, + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + }; + + let userResponse; + try { + userResponse = await axios(config); + } catch (e) { + console.log(e, "Keycloak error - username"); + return e; + } + + return userResponse; + } + + export { + getUserGroup, + getUserRole, + getKeycloakAdminToken, + createUserInKeyCloak, + checkIfEmailExistsInKeycloak, + checkIfUsernameExistsInKeycloak, + }; + \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 8cf49963..a3ee909b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,19 +14,17 @@ async function bootstrap() { exclude: [{ path: "health", method: RequestMethod.GET }], }); - const config = new DocumentBuilder() - .setTitle("Shiksha Platform") - .setDescription("CRUD API") - .setVersion("1.0") - .addTag("V1") - .addApiKey( - { type: "apiKey", scheme: "bearer", bearerFormat: "JWT", name: "Authorization", in: "header" }, - "access-token" - ) - - .build(); - const document = SwaggerModule.createDocument(app, config); - SwaggerModule.setup("api/swagger-docs", app, document); + // const config = new DocumentBuilder() + // .setTitle("Shiksha Platform") + // .setDescription("CRUD API") + // .setVersion("1.0") + // .addTag("V1") + // .addApiKey( + // { type: "apiKey", scheme: "bearer", bearerFormat: "JWT", name: "Authorization", in: "header" }, + // "access-token" + // ).build(); + // const document = SwaggerModule.createDocument(app, config); + // SwaggerModule.setup("api/swagger-docs", app, document); app.enableCors(); await app.listen(3000); } diff --git a/src/user/entities/field-entities.ts b/src/user/entities/field-entities.ts new file mode 100644 index 00000000..0a3d6f40 --- /dev/null +++ b/src/user/entities/field-entities.ts @@ -0,0 +1,33 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm'; +// import { Field } from './Field'; // Assuming you have a Field entity defined + +@Entity({ name: 'FieldValues' }) +export class FieldValue { + @PrimaryGeneratedColumn('uuid', { name: 'fieldValuesId' }) + fieldValuesId: string; + + @Column({ type: 'text', nullable: false }) + value: string; + + @Column({ type: 'uuid', nullable: false, default: () => 'gen_random_uuid()' }) + itemId: string; + + @Column({ type: 'uuid', nullable: false, name: 'fieldId' }) + fieldId: string; + + // @ManyToOne(() => Field, field => field.fieldValues) + // @JoinColumn({ name: 'fieldId' }) + // field: Field; + + @CreateDateColumn({ name: 'createdAt', type: 'timestamp with time zone' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updatedAt', type: 'timestamp with time zone' }) + updatedAt: Date; + + @Column({ type: 'text', nullable: true, name: 'createdBy' }) + createdBy: string; + + @Column({ type: 'text', nullable: true, name: 'updatedBy' }) + updatedBy: string; +} diff --git a/src/user/entities/user-create-entity.ts b/src/user/entities/user-create-entity.ts new file mode 100644 index 00000000..863a5a1b --- /dev/null +++ b/src/user/entities/user-create-entity.ts @@ -0,0 +1,55 @@ +import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm"; + +@Entity({ name: "Users" }) +export class User { + @PrimaryColumn({ type: "uuid" }) + userId: string; + + @Column({ unique: true }) + username: string; + + @Column() + name: string; + + @Column() + role: string; + + @Column({ type: "date", nullable: true }) + dob: Date; + + @Column({ nullable: true }) + email: string; + + @Column({ nullable: true }) + district: string; + + @Column({ nullable: true }) + state: string; + + @Column({ nullable: true }) + address: string; + + @Column({ nullable: true }) + pincode: string; + + @CreateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + createdAt: Date; + + @UpdateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + updatedAt: Date; + +// @Column({ type: "numberic", nullable: true }) +// mobile: number; + + @Column({ nullable: true }) + createdBy: string; + + @Column({ nullable: true }) + updatedBy: string; + + @Column({ type: "uuid" }) + tenantId: string; + + @Column({ default: "active" }) + status: string; +} diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index e59f6b18..21d071c7 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -36,14 +36,23 @@ import { UserDto } from "./dto/user.dto"; import { UserSearchDto } from "./dto/user-search.dto"; import { UserAdapter } from "./useradapter"; import { UserCreateDto } from "./dto/user-create.dto"; +import { UsersService1 } from "./user.service"; @ApiTags("User") @Controller("user") export class UserController { constructor( private readonly service: UserService, - private userAdapter: UserAdapter + private userAdapter: UserAdapter, + private userService1:UsersService1 ) {} + // @Get('/shubham/:userId') + // @UseInterceptors(CacheInterceptor) + // async getUser1(@Param("userid") userId: string){ + // console.log("Hi"); + // return await this.userService1.getUsers(userId); + // } + @Get("/:userid") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) @ApiBasicAuth("access-token") @@ -64,9 +73,7 @@ export class UserController { @Res() response: Response ) { const tenantId = headers["tenantid"]; - return this.userAdapter - .buildUserAdapter() - .getUser(tenantId, userId, accessRole, request, response); + return this.userAdapter.buildUserAdapter().getUser(tenantId, userId, accessRole, request, response); } @Get() @@ -99,6 +106,7 @@ export class UserController { @Req() request: Request, @Body() userCreateDto: UserCreateDto ) { + console.log(userCreateDto); userCreateDto.tenantId = headers["tenantid"]; return this.userAdapter .buildUserAdapter() @@ -167,4 +175,15 @@ export class UserController { .buildUserAdapter() .resetUserPassword(request, reqBody.username, reqBody.newPassword); } + + @Post('/createShubhamUser') + async createShubhamUser( + @Headers() headers, + @Req() request: Request, + @Body() userCreateDto: UserCreateDto + ) { + userCreateDto.tenantId = headers["tenantid"]; + return this.userService1.createShubhamUser(request, userCreateDto); + } + } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 51bb2f69..5a6c3ea1 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -4,9 +4,17 @@ import { HttpModule } from "@nestjs/axios"; import { UserAdapter } from "./useradapter"; import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { User } from "./entities/user-create-entity"; +import { UsersService1 } from "./user.service"; +import { FieldValue } from "./entities/field-entities"; const ttl = process.env.TTL as never; @Module({ imports: [ + TypeOrmModule.forFeature([ + User, + FieldValue + ]), HttpModule, SunbirdModule, HasuraModule, @@ -15,6 +23,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [UserController], - providers: [UserAdapter], + providers: [UserAdapter,UsersService1], }) export class UserModule {} diff --git a/src/user/user.service.ts b/src/user/user.service.ts new file mode 100644 index 00000000..4059d658 --- /dev/null +++ b/src/user/user.service.ts @@ -0,0 +1,111 @@ +import { Injectable } from '@nestjs/common'; +import { User } from './entities/user-create-entity' +import { FieldValue } from './entities/field-entities'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { UserCreateDto } from './dto/user-create.dto'; +import jwt_decode from "jwt-decode"; +import { + getUserRole, + getKeycloakAdminToken, + createUserInKeyCloak, + checkIfUsernameExistsInKeycloak, + } from "../common/keycloak"; +import { ErrorResponse } from 'src/error-response'; +import { SuccessResponse } from 'src/success-response'; + + +@Injectable() +@Injectable() +export class UsersService1 { + constructor( + @InjectRepository(User) + private usersRepository: Repository, + @InjectRepository(FieldValue) + private fieldsValueRepository: Repository + ) {} + + async getUsers(userID){ + let result = await this.usersRepository.findOne({ + where:{ + userId:userID + } + }); + console.log(result); + return result; + } + + public async createShubhamUser(request: any, userCreateDto: UserCreateDto) { + // It is considered that if user is not present in keycloak it is not present in database as well + try { + const decoded: any = jwt_decode(request.headers.authorization); + // const userRoles = decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; + const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + userCreateDto.createdBy = userId + userCreateDto.updatedBy = userId; + + userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); + + const userSchema = new UserCreateDto(userCreateDto); + + let errKeycloak = ""; + let resKeycloak = ""; + + // if (altUserRoles.includes("systemAdmin")) { + + const keycloakResponse = await getKeycloakAdminToken(); + const token = keycloakResponse.data.access_token; + + resKeycloak = await createUserInKeyCloak(userSchema, token).catch( + (error) => { + errKeycloak = error.response?.data.errorMessage; + + return new ErrorResponse({ + errorCode: "500", + errorMessage: "Someting went wrong", + }); + } + ); userCreateDto.userId = resKeycloak; + return await this.createUserInDatabase(request, userCreateDto); + } catch (e) { + console.error(e); + return e; + } + } + +async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { + let result = await this.usersRepository.save(userCreateDto); + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } + // if(result){ + // let fieldCreate = true; + // let fieldError = null; + // //create fields values + // let userId = result?.userId; + // let field_value_array = userCreateDto.fieldValues?.split("|"); + // if (field_value_array?.length > 0) { + // console.log("Hi"); + // let field_values = []; + // for (let i = 0; i < field_value_array.length; i++) { + // let fieldValues = field_value_array[i].split(":"); + // field_values.push({ + // value: fieldValues[1] ? fieldValues[1] : "", + // itemId: userId, + // fieldId: fieldValues[0] ? fieldValues[0] : "", + // createdBy: userCreateDto?.createdBy, + // updatedBy: userCreateDto?.updatedBy, + // }); + // } + // console.log(field_values,"Checking"); + // const response_field_values = await this.fieldsValueRepository.save(field_values); + // console.log(response_field_values); + } + + + + + From 3c4182caebefa5fff0e69c99c428d69a20c42fb3 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 14 Mar 2024 19:06:57 +0530 Subject: [PATCH 042/408] Docker File Updated --- Dockerfile | 36 +++++++++++++++++++++++++++++------- Jenkinsfile1 | 5 +++-- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 12c14c7f..f70bd5a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,30 @@ -FROM node:21.1.0 as dependencies -WORKDIR usr/src/app -COPY package*.json ./ -RUN npm install +FROM node:16-alpine As development + +WORKDIR /usr/src/app + +#COPY package*.json ./ + COPY . . -RUN npm run build -EXPOSE 3000 -CMD ["npm", "start"] + +RUN yarn install --only=development --ignore-engines + +COPY . . + +RUN yarn run build + +FROM node:16-alpine as production + +ARG NODE_ENV=production +ENV NODE_ENV=${NODE_ENV} + +WORKDIR /usr/src/app + +COPY . ./ + +RUN yarn install --only=production --ignore-engines + +COPY . . + +COPY --from=development /usr/src/app/dist ./dist + +CMD ["node", "dist/main"] \ No newline at end of file diff --git a/Jenkinsfile1 b/Jenkinsfile1 index 95db6d10..1290ce58 100644 --- a/Jenkinsfile1 +++ b/Jenkinsfile1 @@ -10,7 +10,9 @@ pipeline { steps{ - git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' + // git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' + checkout scmGit(branches: [[name: '*/oblf-21stFeb']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git']]) + echo "========================== ***Repository cloned Successfully*** ==========================" } @@ -27,4 +29,3 @@ pipeline { } } -} From 879f233443939a6c7acd3260855ddfbdfbd5ab36 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 14 Mar 2024 19:08:56 +0530 Subject: [PATCH 043/408] Docker Updated --- Dockerfile1 | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 Dockerfile1 diff --git a/Dockerfile1 b/Dockerfile1 deleted file mode 100644 index 7add4912..00000000 --- a/Dockerfile1 +++ /dev/null @@ -1,30 +0,0 @@ -FROM node:16-alpine As development - -WORKDIR /usr/src/app - -#COPY package*.json ./ - -COPY . . - -RUN yarn install --only=development --ignore-engines - -COPY . . - -RUN yarn run build - -FROM node:16-alpine as production - -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -WORKDIR /usr/src/app - -COPY . ./ - -RUN yarn install --only=production --ignore-engines - -COPY . . - -COPY --from=development /usr/src/app/dist ./dist - -CMD ["node", "dist/main"] From e02d6370544395fb8245af3de25a7b723098938e Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 14 Mar 2024 19:16:43 +0530 Subject: [PATCH 044/408] Solved Merge Conflicts --- Jenkinsfile1 | 1 + src/adapters/hasura/user.adapter.ts | 170 +++++++++++++++------------- src/main.ts | 37 +++++- 3 files changed, 125 insertions(+), 83 deletions(-) diff --git a/Jenkinsfile1 b/Jenkinsfile1 index 1290ce58..1fb8fa20 100644 --- a/Jenkinsfile1 +++ b/Jenkinsfile1 @@ -29,3 +29,4 @@ pipeline { } } +} \ No newline at end of file diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 97c8e9e6..840a3632 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -261,91 +261,98 @@ export class HasuraUserService implements IServicelocator { } async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { - let query = ""; - Object.keys(userCreateDto).forEach((e) => { - if ( - userCreateDto[e] && - userCreateDto[e] !== "" && - e != "password" && - e != "fieldValues" - ) { - if (e === "role") { - query += `${e}: ${userCreateDto[e]},`; - } else if (Array.isArray(userCreateDto[e])) { - query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; - } else { - query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; + try{ + let query = ""; + Object.keys(userCreateDto).forEach((e) => { + if ( + userCreateDto[e] && + userCreateDto[e] !== "" && + e != "password" && + e != "fieldValues" + ) { + if (e === "role") { + query += `${e}: ${userCreateDto[e]},`; + } else if (Array.isArray(userCreateDto[e])) { + query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; + } else { + query += `${e}: ${JSON.stringify(userCreateDto[e])}, `; + } } - } - }); - const data = { - query: `mutation CreateUser { - insert_Users_one(object: {${query}}) { - userId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - const response = await this.axios(config); - - if (response?.data?.errors || userCreateDto.userId == undefined) { - return new ErrorResponse({ - errorCode: response.data.errors[0].extensions, - errorMessage: response.data.errors[0].message, }); - } else { - const result = response.data.data.insert_Users_one; - - let fieldCreate = true; - let fieldError = null; - //create fields values - let userId = result?.userId; - let field_value_array = userCreateDto.fieldValues?.split("|"); - if (field_value_array?.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - field_values.push({ - value: fieldValues[1] ? fieldValues[1] : "", - itemId: userId, - fieldId: fieldValues[0] ? fieldValues[0] : "", - createdBy: userCreateDto?.createdBy, - updatedBy: userCreateDto?.updatedBy, - }); - } - - const response_field_values = - await this.fieldsService.createFieldValuesBulk(field_values); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError = response_field_values?.data; + const data = { + query: `mutation CreateUser { + insert_Users_one(object: {${query}}) { + userId } } + `, + variables: {}, + }; - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } else { + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + const response = await this.axios(config); + + if (response?.data?.errors || userCreateDto.userId == undefined) { return new ErrorResponse({ - errorCode: fieldError?.errors[0]?.extensions?.code, - errorMessage: fieldError?.errors[0]?.message, + errorCode: response.data.errors[0].extensions, + errorMessage: response.data.errors[0].message, }); + } else { + const result = response.data.data.insert_Users_one; + + let fieldCreate = true; + let fieldError = null; + //create fields values + let userId = result?.userId; + let field_value_array = userCreateDto.fieldValues?.split("|"); + + if (field_value_array?.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + let fieldValues = field_value_array[i].split(":"); + field_values.push({ + value: fieldValues[1] ? fieldValues[1] : "", + itemId: userId, + fieldId: fieldValues[0] ? fieldValues[0] : "", + createdBy: userCreateDto?.createdBy, + updatedBy: userCreateDto?.updatedBy, + }); + } + + const response_field_values = + await this.fieldsService.createFieldValuesBulk(field_values); + if (response_field_values?.data?.errors) { + fieldCreate = false; + fieldError = response_field_values?.data; + } + } + + if (fieldCreate) { + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } else { + return new ErrorResponse({ + errorCode: fieldError?.errors[0]?.extensions?.code, + errorMessage: fieldError?.errors[0]?.message, + }); + } } + }catch (e) { + console.error(e); + return e; } } @@ -465,6 +472,7 @@ export class HasuraUserService implements IServicelocator { if (fieldsFilter) { //apply filter on fields value + // searchfieldValuesFilter returns the contexts here userId that match the fieldId and value pair const responseFieldsValue = await this.fieldsService.searchFieldValuesFilter(request,fieldsFilter); @@ -521,7 +529,7 @@ export class HasuraUserService implements IServicelocator { const count = result.length; //get user fields value - let result_data = await this.searchUserFields(tenantId, userResponse); + let result_data = await this.searchUserFields(request,tenantId, userResponse); return response.status(200).send({ statusCode: 200, @@ -823,7 +831,7 @@ export class HasuraUserService implements IServicelocator { } } - public async searchUserFields(tenantId: string, users: any) { + public async searchUserFields(request:any, tenantId: string, users: any) { // function uses field service to get extra field and respective fieldValues for each user // ****Need extra field for access via role let userWithFields = []; @@ -832,9 +840,10 @@ export class HasuraUserService implements IServicelocator { let userId = new_obj["userId"]; //get fields let response = await this.fieldsService.getFieldsContext( + request, tenantId, "Users", - userId + // userId ); if (response?.data?.errors) { } else { @@ -856,7 +865,6 @@ export class HasuraUserService implements IServicelocator { ) { // function to search users within the user tables try { - const decoded: any = jwt_decode(request.headers.authorization); let offset = 0; if (userSearchDto.page > 1) { offset = parseInt(userSearchDto.limit) * (userSearchDto.page - 1); @@ -928,4 +936,4 @@ export class HasuraUserService implements IServicelocator { return e; } } -} +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index a3ee909b..661c7e0f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,3 +1,34 @@ +// import { NestFactory } from "@nestjs/core"; +// import { AppModule } from "./app.module"; +// import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger"; +// import { RequestMethod } from "@nestjs/common"; +// import { join } from "path"; +// import express = require("express"); +// async function bootstrap() { +// const app = await NestFactory.create(AppModule); +// app.use( +// process.env.IMAGEPATH, +// express.static(join(__dirname, "..", "uploads")) +// ); +// app.setGlobalPrefix("api/v1", { +// exclude: [{ path: "health", method: RequestMethod.GET }], +// }); + +// // const config = new DocumentBuilder() +// // .setTitle("Shiksha Platform") +// // .setDescription("CRUD API") +// // .setVersion("1.0") +// // .addTag("V1") +// // .addApiKey( +// // { type: "apiKey", scheme: "bearer", bearerFormat: "JWT", name: "Authorization", in: "header" }, +// // "access-token" +// // ).build(); +// // const document = SwaggerModule.createDocument(app, config); +// // SwaggerModule.setup("api/swagger-docs", app, document); +// app.enableCors(); +// await app.listen(3000); +// } +// bootstrap(); import { NestFactory } from "@nestjs/core"; import { AppModule } from "./app.module"; import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger"; @@ -20,9 +51,11 @@ async function bootstrap() { // .setVersion("1.0") // .addTag("V1") // .addApiKey( - // { type: "apiKey", scheme: "bearer", bearerFormat: "JWT", name: "Authorization", in: "header" }, + // { type: "apiKey", name: "Authorization", in: "header" }, // "access-token" - // ).build(); + // ) + + // .build(); // const document = SwaggerModule.createDocument(app, config); // SwaggerModule.setup("api/swagger-docs", app, document); app.enableCors(); From 8ac5848dbeb4ae8b86a3062c292ea261a9188fc3 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 14 Mar 2024 19:21:52 +0530 Subject: [PATCH 045/408] Updated Docker File --- Jenkinsfile1 | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 Jenkinsfile1 diff --git a/Jenkinsfile1 b/Jenkinsfile1 deleted file mode 100644 index 1fb8fa20..00000000 --- a/Jenkinsfile1 +++ /dev/null @@ -1,32 +0,0 @@ -pipeline { - agent any - stages { - stage('clean workspace'){ - steps{ - cleanWs() - } - } - stage('Checkout'){ - - steps{ - - // git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' - checkout scmGit(branches: [[name: '*/oblf-21stFeb']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git']]) - - echo "========================== ***Repository cloned Successfully*** ==========================" - - } - } - - stage ('Build&Deploy') { - - steps { - - sh 'cp -r /shiksha/.env .' - sh 'docker build -t backend .' - sh 'docker-compose up -d --force-recreate --no-deps' - } - } - - } -} \ No newline at end of file From ed1c6dd11a2299383ebf7fe6eb1837996fe86447 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 15 Mar 2024 14:08:02 +0530 Subject: [PATCH 046/408] Updated and Fixed User Asdapter File --- src/adapters/hasura/user.adapter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 840a3632..873ecfcf 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -843,7 +843,7 @@ export class HasuraUserService implements IServicelocator { request, tenantId, "Users", - // userId + userId ); if (response?.data?.errors) { } else { From fd352e4364cbce405876c8087753ff8b71a9730a Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 15 Mar 2024 14:12:36 +0530 Subject: [PATCH 047/408] Solved Merge Conflict --- Dockerfile | 30 ------------------------------ Jenkinsfile | 40 ++++++++++++++-------------------------- 2 files changed, 14 insertions(+), 56 deletions(-) delete mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index f70bd5a8..00000000 --- a/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -FROM node:16-alpine As development - -WORKDIR /usr/src/app - -#COPY package*.json ./ - -COPY . . - -RUN yarn install --only=development --ignore-engines - -COPY . . - -RUN yarn run build - -FROM node:16-alpine as production - -ARG NODE_ENV=production -ENV NODE_ENV=${NODE_ENV} - -WORKDIR /usr/src/app - -COPY . ./ - -RUN yarn install --only=production --ignore-engines - -COPY . . - -COPY --from=development /usr/src/app/dist ./dist - -CMD ["node", "dist/main"] \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 1fb8fa20..778bb998 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,32 +1,20 @@ pipeline { agent any - stages { - stage('clean workspace'){ - steps{ - cleanWs() - } - } - stage('Checkout'){ - - steps{ - - // git branch: 'main', credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git' - checkout scmGit(branches: [[name: '*/oblf-21stFeb']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git']]) - - echo "========================== ***Repository cloned Successfully*** ==========================" - - } - } - - stage ('Build&Deploy') { - + + stages { + stage('SSH to UAT Server and Deploy') { steps { - - sh 'cp -r /shiksha/.env .' - sh 'docker build -t backend .' - sh 'docker-compose up -d --force-recreate --no-deps' + script { + sshagent(credentials: ['Jenkins-agent']){ + sh """ + ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' + cd /home/jenkins + ./deploy.sh + """ + } } + } - - } + } + } } \ No newline at end of file From 93562f3a4d521bb0a96393ba8e492edcd2d30002 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:40:51 +0530 Subject: [PATCH 048/408] Update Jenkinsfile --- Jenkinsfile | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8808942f..6427f41a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,20 +1,27 @@ pipeline { - agent any - - stages { - stage('SSH to UAT Server and Deploy') { + agent any + stages { + stage('Checkout'){ + steps{ + cleanWs() + sh 'rm -rf *' + //checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'githubtoken', url: 'https://github.com/tekdi/onest.network.backend.git']]) + checkout scmGit(branches: [[name: '*/dev']], extensions: [], userRemoteConfigs: [[credentialsId: 'ONEST-ID', url: 'https://github.com/tekdi/onest.network.backend.git']]) + } + } + + stage ('Build-image') { + steps { + sh 'docker build -t onest-network-backend-p-11 .' + } + } + + stage ('Deploy') { steps { - script { - sshagent(credentials: ['Jenkins-agent']){ - sh """ - ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' - cd /home/jenkins - ./deploy.sh - """ - } - } - + + + sh 'docker-compose up -d --force-recreate --no-deps backend' + } } - } - } + } } From 9057e0c59ba6849195c66fe6ce38bf027c74d4ab Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:26:26 +0530 Subject: [PATCH 049/408] Create Dockerfile --- Dockerfile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..b7649c97 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM node:20 as dependencies +WORKDIR usr/src/app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build +EXPOSE 3000 +CMD ["npm", "start"] From 6f23e2d1942b5d6e1003faa242c9cb0f0ac6a350 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:26:59 +0530 Subject: [PATCH 050/408] Create docker-compose.yml --- docker-compose.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..41bd9ecb --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3.6" + +services: + backend: + image: onest-network-backend-p-11 + container_name: "onest-network-backend-p-29-2" + restart: always + ports: + - 4000:3000 + env_file: + - /home/ubuntu/onest/onest-backend-network-p/.env From c004dc9f99450f61f83df9cff11938b53e242a3c Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:32:09 +0530 Subject: [PATCH 051/408] Update Jenkinsfile --- Jenkinsfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6427f41a..c8cde920 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,13 +6,14 @@ pipeline { cleanWs() sh 'rm -rf *' //checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'githubtoken', url: 'https://github.com/tekdi/onest.network.backend.git']]) - checkout scmGit(branches: [[name: '*/dev']], extensions: [], userRemoteConfigs: [[credentialsId: 'ONEST-ID', url: 'https://github.com/tekdi/onest.network.backend.git']]) - } + // checkout scmGit(branches: [[name: '*/dev']], extensions: [], userRemoteConfigs: [[credentialsId: 'ONEST-ID', url: 'https://github.com/tekdi/onest.network.backend.git']]) + checkout scmGit(branches: [[name: '*/Shiksha-2.0']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git']]) + } } stage ('Build-image') { steps { - sh 'docker build -t onest-network-backend-p-11 .' + sh 'docker build -t shiksha-backend-2.0 .' } } From 7abe735b5776e7c92bd99d1aeee220359264fba2 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:35:04 +0530 Subject: [PATCH 052/408] Update docker-compose.yml --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 41bd9ecb..b4237cb3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,10 +2,10 @@ version: "3.6" services: backend: - image: onest-network-backend-p-11 - container_name: "onest-network-backend-p-29-2" + image: shiksha-backend-2.0 + container_name: "shiksha-backend-2.0" restart: always ports: - - 4000:3000 + - 3000:3000 env_file: - /home/ubuntu/onest/onest-backend-network-p/.env From 2e3f514acdd2a9f9739d0a3b650688ad08a554d9 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:43:42 +0530 Subject: [PATCH 053/408] Update docker-compose.yml From 39bc0ef4151cfdd3701dbce9dbd33158322f63f4 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:46:53 +0530 Subject: [PATCH 054/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index b4237cb3..b5fdaf96 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,4 +8,4 @@ services: ports: - 3000:3000 env_file: - - /home/ubuntu/onest/onest-backend-network-p/.env + - /home/ubuntu-backend-shiksha2.0/.env From 97b90220c9ffa6f283d22d79229c5d96967e2702 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 15 Mar 2024 18:31:13 +0530 Subject: [PATCH 055/408] Updated Docker File and Jenkins File --- Dockerfile | 8 ++++++++ Jenkinsfile | 40 ++++++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..ac5f1593 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM node:20 as dependencies +WORKDIR usr/src/app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build +EXPOSE 3000 +CMD ["npm", "start"] \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 778bb998..0cc24c52 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,20 +1,28 @@ pipeline { - agent any - - stages { - stage('SSH to UAT Server and Deploy') { - steps { - script { - sshagent(credentials: ['Jenkins-agent']){ - sh """ - ssh -o StrictHostKeyChecking=no -l root 143.110.179.209 << 'ENDSSH' - cd /home/jenkins - ./deploy.sh - """ - } - } - + agent any + stages { + stage('Checkout'){ + steps{ + cleanWs() + sh 'rm -rf *' + //checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'githubtoken', url: 'https://github.com/tekdi/onest.network.backend.git']]) + // checkout scmGit(branches: [[name: '*/dev']], extensions: [], userRemoteConfigs: [[credentialsId: 'ONEST-ID', url: 'https://github.com/tekdi/onest.network.backend.git']]) + checkout scmGit(branches: [[name: '*/Shiksha-2.0']], extensions: [], userRemoteConfigs: [[credentialsId: 'github-1', url: 'https://github.com/tekdi/shiksha-backend.git']]) } } - } + + stage ('Build-image') { + steps { + sh 'docker build -t shiksha-backend-2.0 .' + } + } + + stage ('Deploy') { + steps { + + + sh 'docker-compose up -d --force-recreate --no-deps backend' + } + } + } } \ No newline at end of file From 28018bd36b868d33c18c4d3dc0625110a85a7697 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 15 Mar 2024 18:33:20 +0530 Subject: [PATCH 056/408] Updated Docker Compose Fle --- docker-compose.yml | 49 +++++++--------------------------------------- 1 file changed, 7 insertions(+), 42 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index daba4c3b..44e61c28 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,46 +1,11 @@ -version: '3.7' +version: "3.6" services: - main: - container_name: shiksha-backend-oblf-21stFeb-cicd1 - build: - context: . - target: development - volumes: - - .:/usr/src/app - - /usr/src/app/node_modules + backend: + image: shiksha-backend-2.0 + container_name: "shiksha-backend-2.0" + restart: always ports: - - ${SERVER_PORT}:${SERVER_PORT} - - 9229:9229 - command: yarn run start:dev + - 3000:3000 env_file: - - .env - networks: - - webnet - restart: always - # depends_on: - # - redis - # - postgres - # redis: - # container_name: redis - # image: redis:5 - # networks: - # - webnet - # postgres: - # container_name: postgres - # image: postgres:11 - # networks: - # - webnet - # environment: - # POSTGRES_PASSWORD: ${DB_PASSWORD} - # POSTGRES_USER: ${DB_USERNAME} - # POSTGRES_DB: ${DB_DATABASE_NAME} - # PG_DATA: /var/lib/postgresql/data - # ports: - # - 5432:5432 - # volumes: - # - pgdata:/var/lib/postgresql/data -networks: - webnet: -# volumes: -# pgdata: + - /home/ubuntu-backend-shiksha2.0/.env \ No newline at end of file From 88c81be72911c1eb143231dbc3b02822519cce46 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Mon, 18 Mar 2024 10:59:59 +0530 Subject: [PATCH 057/408] Cohort:get cohot data API --- src/cohort/cohort.controller.ts | 35 ++++++++++++-- src/cohort/cohort.module.ts | 6 ++- src/cohort/entities/cohort.entity.ts | 67 +++++++++++++++++++++++++++ src/cohort/entities/cohort.service.ts | 64 +++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 src/cohort/entities/cohort.entity.ts create mode 100644 src/cohort/entities/cohort.service.ts diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 71b2afcb..020f7695 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -35,11 +35,15 @@ import { Response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; +import { CohortService } from "./entities/cohort.service"; @ApiTags("Cohort") @Controller("cohort") export class CohortController { - constructor(private cohortAdapter: CohortAdapter) {} + constructor( + private cohortAdapter: CohortAdapter, + private readonly cohortService: CohortService + ) {} //create cohort @Post() @@ -79,6 +83,30 @@ export class CohortController { .createCohort(request, cohortCreateDto); } + // //get cohort + // @Get("/:id") + // @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Cohort detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async getCohort( + // @Headers() headers, + // @Param("id") cohortId: string, + // @Req() request: Request, + // @Res() res: Response + // ) { + // let tenantid = headers["tenantid"]; + // return this.cohortAdapter + // .buildCohortAdapter() + // .getCohort(tenantid, cohortId, request, res); + // } + //get cohort @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) @@ -98,11 +126,8 @@ export class CohortController { @Res() res: Response ) { let tenantid = headers["tenantid"]; - return this.cohortAdapter - .buildCohortAdapter() - .getCohort(tenantid, cohortId, request, res); + return this.cohortService.getCohort(tenantid, cohortId, request, res); } - //search @Post("/search") @ApiBasicAuth("access-token") diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 26c696e4..4ccafe83 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -3,9 +3,13 @@ import { CohortController } from "./cohort.controller"; import { HttpModule } from "@nestjs/axios"; import { CohortAdapter } from "./cohortadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { CohortService } from "./entities/cohort.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { Cohort } from "./entities/cohort.entity"; const ttl = process.env.TTL as never; @Module({ imports: [ + TypeOrmModule.forFeature([Cohort]), HttpModule, HasuraModule, CacheModule.register({ @@ -13,6 +17,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [CohortController], - providers: [CohortAdapter], + providers: [CohortAdapter, CohortService], }) export class CohortModule {} diff --git a/src/cohort/entities/cohort.entity.ts b/src/cohort/entities/cohort.entity.ts new file mode 100644 index 00000000..c190de8d --- /dev/null +++ b/src/cohort/entities/cohort.entity.ts @@ -0,0 +1,67 @@ +import { + Entity, + PrimaryColumn, + Column, + CreateDateColumn, + UpdateDateColumn, +} from "typeorm"; + +@Entity({ name: "Cohort" }) +export class Cohort { + @PrimaryColumn({ type: "uuid" }) + cohortId: string; + + @Column({ nullable: true }) + parentId: string; + + @Column({ nullable: true }) + name: string; + + @Column({ nullable: true }) + type: string; + + @Column({ nullable: true }) + status: string; + + @Column({ nullable: true }) + image: string; + + @Column({ nullable: true }) + referenceId: string; + + @Column({ nullable: true }) + metadata: string; + + @Column({ nullable: true }) + tenantId: string; + + @Column({ nullable: true }) + programId: string; + + @Column() + attendanceCaptureImage: boolean; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdBy: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedBy: Date; +} diff --git a/src/cohort/entities/cohort.service.ts b/src/cohort/entities/cohort.service.ts new file mode 100644 index 00000000..5b1ecf83 --- /dev/null +++ b/src/cohort/entities/cohort.service.ts @@ -0,0 +1,64 @@ +import { Injectable } from "@nestjs/common"; +import { CohortInterface } from "../../cohort/interfaces/cohort.interface"; +import { HttpService } from "@nestjs/axios"; +import { SuccessResponse } from "src/success-response"; +import { ErrorResponse } from "src/error-response"; +const resolvePath = require("object-resolve-path"); +import jwt_decode from "jwt-decode"; +import { CohortDto } from "src/cohort/dto/cohort.dto"; +import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; +// import { IServicelocatorcohort } from "../cohortservicelocator"; +import { UserDto } from "src/user/dto/user.dto"; +import { StudentDto } from "src/student/dto/student.dto"; +// import { FieldsService } from "./services/fields.service"; +import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; +import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; +import { Cohort } from "src/cohort/entities/cohort.entity"; +import { InjectRepository } from "@nestjs/typeorm"; + +@Injectable() +export class CohortService { + private cohort: CohortInterface; + + constructor( + @InjectRepository(Cohort) + private cohortRepository: Repository + ) {} + + public async getCohort( + tenantId: string, + cohortId: string, + request: any, + res: any + ) { + try { + console.log("Tenant id", tenantId); + console.log("cohortId", cohortId); + const cohort = await this.cohortRepository.findOne({ + where: { tenantId: tenantId, cohortId: cohortId }, + }); + if (!cohort) { + console.log("if ! cohort"); + + return res.status(404).send({ + statusCode: 404, + message: "Cohort not found.", + }); + } + console.log("cohort", cohort); + return res.status(200).send({ + statusCode: 200, + message: "Ok.", + data: cohort, + }); + } catch (error) { + console.log("heyyy"); + console.error("Error fetching cohort:", error); + return res.status(500).send({ + statusCode: 500, + message: "Internal server error.", + }); + } + } +} From 962c03730d164935286cf2541fe647fe65a0d59c Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:01:09 +0530 Subject: [PATCH 058/408] Rename docker-compose.yml to docker-compose.yml1 --- docker-compose.yml => docker-compose.yml1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docker-compose.yml => docker-compose.yml1 (100%) diff --git a/docker-compose.yml b/docker-compose.yml1 similarity index 100% rename from docker-compose.yml rename to docker-compose.yml1 From b8a619a1f16625ac4ba982284dfd58a61e4fd451 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:05:54 +0530 Subject: [PATCH 059/408] Create docker-compose.yml --- docker-compose.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..91f08ac3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.7' + +services: + main: + container_name: shiksha-backend-2.0 + build: + context: . + target: development + volumes: + - .:/usr/src/app + - /usr/src/app/node_modules + ports: + - ${SERVER_PORT}:${SERVER_PORT} + - 9229:9229 + command: yarn run start:dev + env_file: + - /home/ubuntu-backend-shiksha2.0/.env + networks: + - webnet + restart: always From 4cdc14d8870f774177440c1dccee43a2edc41dc9 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:12:37 +0530 Subject: [PATCH 060/408] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 91f08ac3..9655b8f1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: - .:/usr/src/app - /usr/src/app/node_modules ports: - - ${SERVER_PORT}:${SERVER_PORT} + # - ${SERVER_PORT}:${SERVER_PORT} - 9229:9229 command: yarn run start:dev env_file: From cad137ffcd08971c720e7490bcc0e767a685f84d Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:14:21 +0530 Subject: [PATCH 061/408] Update docker-compose.yml --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9655b8f1..8c3b7cb0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,6 @@ services: command: yarn run start:dev env_file: - /home/ubuntu-backend-shiksha2.0/.env - networks: - - webnet + # networks: + # - webnet restart: always From 583e60cd6f7a1843fc31b9740d25af01e7d74fc9 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:19:57 +0530 Subject: [PATCH 062/408] Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b7649c97..bd0935cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM node:20 as dependencies WORKDIR usr/src/app COPY package*.json ./ -RUN npm install +RUN npm run install COPY . . RUN npm run build EXPOSE 3000 From bba50161611fdec2d8b0641fc06a89f6be3c1c6e Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 18 Mar 2024 11:22:52 +0530 Subject: [PATCH 063/408] Fix[SearchAttendance API using typeorm in Attendance module] --- src/attendance/attendance.controller.ts | 28 +++++- src/attendance/attendance.module.ts | 9 +- src/attendance/attendance.service.ts | 100 +++++++++++++++++++ src/attendance/entities/attendance.entity.ts | 62 ++++++++++++ 4 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 src/attendance/attendance.service.ts create mode 100644 src/attendance/entities/attendance.entity.ts diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 9bef3129..6c5ec1d4 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -1,3 +1,4 @@ +// import { AttendanceService } from 'src/adapters/sunbirdrc/attendance.adapter'; import { ApiTags, ApiBody, @@ -34,13 +35,15 @@ import { AttendanceSearchDto } from "./dto/attendance-search.dto"; import { AttendanceHasuraService } from "src/adapters/hasura/attendance.adapter"; import { AttendaceAdapter } from "./attendanceadapter"; import { AttendanceDateDto } from "./dto/attendance-date.dto"; +import { AttendanceService } from './attendance.service'; @ApiTags("Attendance") @Controller("attendance") export class AttendanceController { constructor( private service: AttendanceHasuraService, - private attendaceAdapter: AttendaceAdapter + private attendaceAdapter: AttendaceAdapter, + private attendaceService: AttendanceService ) {} @Get("/:id") @@ -155,6 +158,29 @@ export class AttendanceController { .searchAttendance(tenantid, request, studentSearchDto); } + + @Post("/searchNew") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Attendance list." }) + @ApiBody({ type: AttendanceSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async searchAttendanceNew( + @Headers() headers, + @Req() request: Request, + @Body() studentSearchDto: AttendanceSearchDto + ) { + let tenantid = headers["tenantid"]; + return this.attendaceService + .searchAttendance(tenantid, request, studentSearchDto); + } + @Post("/bydate") @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") diff --git a/src/attendance/attendance.module.ts b/src/attendance/attendance.module.ts index 75ef9385..ee7ef942 100644 --- a/src/attendance/attendance.module.ts +++ b/src/attendance/attendance.module.ts @@ -4,10 +4,17 @@ import { ScheduleModule } from "@nestjs/schedule"; import { AttendaceAdapter } from "./attendanceadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; +import { AttendanceService } from "./attendance.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { AttendanceEntity } from "./entities/attendance.entity"; +import { Repository } from "typeorm"; const ttl = process.env.TTL as never; @Module({ imports: [ + TypeOrmModule.forFeature([ + AttendanceEntity + ]), SunbirdModule, HasuraModule, CacheModule.register({ @@ -16,6 +23,6 @@ const ttl = process.env.TTL as never; ScheduleModule.forRoot(), ], controllers: [AttendanceController], - providers: [AttendaceAdapter], + providers: [AttendaceAdapter,AttendanceService,Repository], }) export class AttendanceModule {} diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts new file mode 100644 index 00000000..f4120ce4 --- /dev/null +++ b/src/attendance/attendance.service.ts @@ -0,0 +1,100 @@ +import { ConfigService } from '@nestjs/config'; +import { Client } from 'pg'; +import jwt_decode from "jwt-decode"; +import { InjectRepository } from "@nestjs/typeorm"; +import { AttendanceEntity } from "./entities/attendance.entity"; +import { Repository } from "typeorm"; +import { Injectable } from "@nestjs/common"; +import { ErrorResponse } from "src/error-response"; +import { AttendanceSearchDto } from "./dto/attendance-search.dto"; +import { SuccessResponse } from 'src/success-response'; +import { AttendanceDto } from './dto/attendance.dto'; + + + +@Injectable() +export class AttendanceService { + constructor(private configService: ConfigService, + @InjectRepository(AttendanceEntity) + private readonly attendanceRepository: Repository,) { } + + async searchAttendance(tenantId: string, request: any, attendanceSearchDto: AttendanceSearchDto) { + + try { + let { limit, page, filters } = attendanceSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + else { + whereClause['tenantId'] = tenantId; + } + + + const [results, totalCount] = await this.attendanceRepository.findAndCount({ + where: whereClause, + take: parseInt(limit), + skip: offset, + }); + const mappedResponse = await this.mappedResponse(results); + + return new SuccessResponse({ + statusCode: 200, + message: 'Ok.', + totalCount, + data: mappedResponse, + }); + } catch (error) { + return new ErrorResponse({ + errorCode: '500', + errorMessage: error, + }); + } + } + + public async mappedResponse(result: any) { + const attendanceResponse = result.map((item: any) => { + const attendanceMapping = { + tenantId: item?.tenantId ? `${item.tenantId}` : "", + attendanceId: item?.attendanceId ? `${item.attendanceId}` : "", + userId: item?.userId ? `${item.userId}` : "", + attendanceDate: item?.attendanceDate ? `${item.attendanceDate}` : "", + attendance: item?.attendance ? `${item.attendance}` : "", + remark: item?.remark ? `${item.remark}` : "", + latitude: item?.latitude ? item.latitude : 0, + longitude: item?.longitude ? item.longitude : 0, + image: item?.image ? `${item.image}` : "", + metaData: item?.metaData ? item.metaData : [], + syncTime: item?.syncTime ? `${item.syncTime}` : "", + session: item?.session ? `${item.session}` : "", + contextId: item?.contextId ? `${item.contextId}` : "", + contextType: item?.contextType ? `${item.contextType}` : "", + createdAt: item?.createdAt ? `${item.createdAt}` : "", + updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", + createdBy: item?.createdBy ? `${item.createdBy}` : "", + updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + }; + + return new AttendanceDto(attendanceMapping); + }); + + return attendanceResponse; + } +} + + + + diff --git a/src/attendance/entities/attendance.entity.ts b/src/attendance/entities/attendance.entity.ts new file mode 100644 index 00000000..faa60c3c --- /dev/null +++ b/src/attendance/entities/attendance.entity.ts @@ -0,0 +1,62 @@ +import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity({name:"Attendance"}) +export class AttendanceEntity { + @PrimaryGeneratedColumn('uuid') + attendanceId: string; + + @Column() + tenantId: string; + + @Column() + userId: string; + + @Column({ type: 'date' }) + attendanceDate: Date; + + @Column() + attendance: string; + + @Column({ nullable: true }) + remark: string; + + @Column({ type: 'numeric', nullable: true }) + latitude: number; + + @Column({ type: 'numeric', nullable: true }) + longitude: number; + + @Column({ nullable: true }) + image: string; + + @Column({ nullable: true }) + metaData: string; + + @Column({ nullable: true }) + syncTime: string; + + @Column({ nullable: true }) + session: string; + + @Column({ nullable: true }) + contextType: string; + + @Column({ nullable: true }) + contextId: string; + + @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) + createdAt: Date; + + @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP' }) + updatedAt: Date; + + @Column() + createdBy: string; + + @Column() + updatedBy: string; + + constructor(obj: Partial) { + Object.assign(this, obj); + } +} From 28a5be090046a919b78137d614c54fa89175ecf9 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:23:32 +0530 Subject: [PATCH 064/408] Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bd0935cd..b7649c97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM node:20 as dependencies WORKDIR usr/src/app COPY package*.json ./ -RUN npm run install +RUN npm install COPY . . RUN npm run build EXPOSE 3000 From 10292e7a81af0b594954b80388177fed44b08a1a Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:52:16 +0530 Subject: [PATCH 065/408] Update Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index b7649c97..3414815a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM node:20 as dependencies WORKDIR usr/src/app COPY package*.json ./ -RUN npm install +RUN yarn install COPY . . -RUN npm run build +RUN yarn run build EXPOSE 3000 CMD ["npm", "start"] From a400bfe47c14768d53a7eda3be7d891198d5e078 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:02:51 +0530 Subject: [PATCH 066/408] Update Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3414815a..b7649c97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM node:20 as dependencies WORKDIR usr/src/app COPY package*.json ./ -RUN yarn install +RUN npm install COPY . . -RUN yarn run build +RUN npm run build EXPOSE 3000 CMD ["npm", "start"] From 047ff530799e9366e6b4865de4e1f9d52b63fce9 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:11:42 +0530 Subject: [PATCH 067/408] Update Dockerfile From 3d7291685eeb8a1eb5291665b1b0b3d32e117722 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:56:40 +0530 Subject: [PATCH 068/408] Update Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index b7649c97..d2bc7818 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM node:20 as dependencies WORKDIR usr/src/app COPY package*.json ./ -RUN npm install +CMD npm install COPY . . -RUN npm run build +CMD npm run build EXPOSE 3000 CMD ["npm", "start"] From 0a8347ac460b45ab19ff808c55754c70fe9a9f3b Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:06:20 +0530 Subject: [PATCH 069/408] Update Dockerfile --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index d2bc7818..87727bdd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ -FROM node:20 as dependencies +FROM node:16 as dependencies WORKDIR usr/src/app COPY package*.json ./ -CMD npm install +RUN npm install COPY . . -CMD npm run build +RUN npm run build EXPOSE 3000 CMD ["npm", "start"] From f6756e31881bae5eb12c1b4b51de0296ad8b4bd1 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:15:03 +0530 Subject: [PATCH 070/408] Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 87727bdd..b7649c97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16 as dependencies +FROM node:20 as dependencies WORKDIR usr/src/app COPY package*.json ./ RUN npm install From 05591693297a10e55459ea40a0a5aae0b0fceaa0 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:15:53 +0530 Subject: [PATCH 071/408] Delete docker-compose.yml --- docker-compose.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 8c3b7cb0..00000000 --- a/docker-compose.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: '3.7' - -services: - main: - container_name: shiksha-backend-2.0 - build: - context: . - target: development - volumes: - - .:/usr/src/app - - /usr/src/app/node_modules - ports: - # - ${SERVER_PORT}:${SERVER_PORT} - - 9229:9229 - command: yarn run start:dev - env_file: - - /home/ubuntu-backend-shiksha2.0/.env - # networks: - # - webnet - restart: always From 1360fddce35d8904ee0aca0027fafa91d8c585c6 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:16:09 +0530 Subject: [PATCH 072/408] Rename docker-compose.yml1 to docker-compose.yml --- docker-compose.yml1 => docker-compose.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docker-compose.yml1 => docker-compose.yml (100%) diff --git a/docker-compose.yml1 b/docker-compose.yml similarity index 100% rename from docker-compose.yml1 rename to docker-compose.yml From 0963e931d1ab2c587ea6bee40ede2cc1ba0ad90a Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Mon, 18 Mar 2024 14:51:48 +0530 Subject: [PATCH 073/408] Resolve comments --- src/cohort/cohort.controller.ts | 7 ++- src/cohort/cohort.module.ts | 2 +- src/cohort/cohort.service.ts | 76 +++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 src/cohort/cohort.service.ts diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 020f7695..e23b07e9 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -35,7 +35,7 @@ import { Response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; -import { CohortService } from "./entities/cohort.service"; +import { CohortService } from "./cohort.service"; @ApiTags("Cohort") @Controller("cohort") @@ -122,11 +122,10 @@ export class CohortController { public async getCohort( @Headers() headers, @Param("id") cohortId: string, - @Req() request: Request, - @Res() res: Response + @Req() request: Request ) { let tenantid = headers["tenantid"]; - return this.cohortService.getCohort(tenantid, cohortId, request, res); + return this.cohortService.getCohort(tenantid, cohortId, request); } //search @Post("/search") diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 4ccafe83..6a17c041 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -3,7 +3,7 @@ import { CohortController } from "./cohort.controller"; import { HttpModule } from "@nestjs/axios"; import { CohortAdapter } from "./cohortadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { CohortService } from "./entities/cohort.service"; +import { CohortService } from "./cohort.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { Cohort } from "./entities/cohort.entity"; const ttl = process.env.TTL as never; diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts new file mode 100644 index 00000000..1a6ba366 --- /dev/null +++ b/src/cohort/cohort.service.ts @@ -0,0 +1,76 @@ +import { Injectable } from "@nestjs/common"; +import { CohortInterface } from "./interfaces/cohort.interface"; +import { HttpService } from "@nestjs/axios"; +import { SuccessResponse } from "src/success-response"; +import { ErrorResponse } from "src/error-response"; +const resolvePath = require("object-resolve-path"); +import jwt_decode from "jwt-decode"; +import { CohortDto } from "src/cohort/dto/cohort.dto"; +import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; +// import { IServicelocatorcohort } from "../cohortservicelocator"; +import { UserDto } from "src/user/dto/user.dto"; +import { StudentDto } from "src/student/dto/student.dto"; +// import { FieldsService } from "./services/fields.service"; +import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; +import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; +import { Cohort } from "src/cohort/entities/cohort.entity"; +import { InjectRepository } from "@nestjs/typeorm"; + +@Injectable() +export class CohortService { + private cohort: CohortInterface; + + constructor( + @InjectRepository(Cohort) + private cohortRepository: Repository + ) {} + + public async getCohort(tenantId: string, cohortId: string, request: any) { + try { + const cohort = await this.cohortRepository.findOne({ + where: { tenantId: tenantId, cohortId: cohortId }, + }); + + if (!cohort) { + return new ErrorResponse({ + errorCode: "404", + errorMessage: "Cohort not found.", + }); + } + + let cohortResponse = await this.mappedResponse(cohort); + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: cohortResponse, + }); + } catch (error) { + return new ErrorResponse({ + errorCode: "500", + errorMessage: "Something went wrong", + }); + } + } + + public async mappedResponse(result: any) { + const cohortMapping = { + tenantId: result?.tenantId ? `${result.tenantId}` : "", + programId: result?.programId ? `${result.programId}` : "", + cohortId: result?.cohortId ? `${result.cohortId}` : "", + parentId: result?.parentId ? `${result.parentId}` : "", + name: result?.name ? `${result.name}` : "", + type: result?.type ? `${result.type}` : "", + status: result?.status ? `${result.status}` : "", + image: result?.image ? `${result.image}` : "", + createdAt: result?.createdAt ? `${result.createdAt}` : "", + updatedAt: result?.updatedAt ? `${result.updatedAt}` : "", + createdBy: result?.createdBy ? `${result.createdBy}` : "", + updatedBy: result?.updatedBy ? `${result.updatedBy}` : "", + referenceId: result?.referenceId ? `${result.referenceId}` : "", + metadata: result?.metadata ? `${result.metadata}` : "", + }; + + return new CohortDto(cohortMapping); + } +} From 828058f9f03cb464021f7b9d8b0a713c357f3320 Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 18 Mar 2024 15:10:06 +0530 Subject: [PATCH 074/408] Task #215678 : Added Global Error Handling Filess --- src/user/user.controller.ts | 7 ++-- src/user/user.module.ts | 4 +- src/user/user.service.ts | 3 +- src/utils/response-interface.ts | 30 ++++++++++++++ src/utils/response.ts | 70 +++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 src/utils/response-interface.ts create mode 100644 src/utils/response.ts diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 21d071c7..3b16bbbf 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -17,7 +17,6 @@ import { } from "@nestjs/common"; import { SunbirdUserToken, - UserService, } from "../adapters/sunbirdrc/user.adapter"; import { Request, Response } from "@nestjs/common"; import { @@ -36,14 +35,14 @@ import { UserDto } from "./dto/user.dto"; import { UserSearchDto } from "./dto/user-search.dto"; import { UserAdapter } from "./useradapter"; import { UserCreateDto } from "./dto/user-create.dto"; -import { UsersService1 } from "./user.service"; +import { UserService } from "./user.service"; @ApiTags("User") @Controller("user") export class UserController { constructor( private readonly service: UserService, private userAdapter: UserAdapter, - private userService1:UsersService1 + private userService:UserService ) {} // @Get('/shubham/:userId') @@ -183,7 +182,7 @@ export class UserController { @Body() userCreateDto: UserCreateDto ) { userCreateDto.tenantId = headers["tenantid"]; - return this.userService1.createShubhamUser(request, userCreateDto); + return this.userService.createShubhamUser(request, userCreateDto); } } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 5a6c3ea1..a114b913 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -6,7 +6,7 @@ import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { TypeOrmModule } from "@nestjs/typeorm"; import { User } from "./entities/user-create-entity"; -import { UsersService1 } from "./user.service"; +import { UserService } from "./user.service"; import { FieldValue } from "./entities/field-entities"; const ttl = process.env.TTL as never; @Module({ @@ -23,6 +23,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [UserController], - providers: [UserAdapter,UsersService1], + providers: [UserAdapter,UserService], }) export class UserModule {} diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 4059d658..33b6388d 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -17,7 +17,7 @@ import { SuccessResponse } from 'src/success-response'; @Injectable() @Injectable() -export class UsersService1 { +export class UserService { constructor( @InjectRepository(User) private usersRepository: Repository, @@ -38,6 +38,7 @@ export class UsersService1 { public async createShubhamUser(request: any, userCreateDto: UserCreateDto) { // It is considered that if user is not present in keycloak it is not present in database as well try { + console.log("Hi"); const decoded: any = jwt_decode(request.headers.authorization); // const userRoles = decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; diff --git a/src/utils/response-interface.ts b/src/utils/response-interface.ts new file mode 100644 index 00000000..bfbb9269 --- /dev/null +++ b/src/utils/response-interface.ts @@ -0,0 +1,30 @@ +// structure for server responses +export interface ServerResponse { + // api id + id: string; + + // response param + params: Params; + + // response code + responseCode: string; + + //server result + result: any; + + // time stamp + ts: string; + + // api version + ver: string; + + headers?: any; + } + + export interface Params { + resmsgid: string; + err?: any; + status: string; + errmsg?: any; + } + \ No newline at end of file diff --git a/src/utils/response.ts b/src/utils/response.ts new file mode 100644 index 00000000..1f9f406d --- /dev/null +++ b/src/utils/response.ts @@ -0,0 +1,70 @@ +import { v4 } from 'uuid'; +import { ServerResponse, Params } from './response-interface'; + +export default class APIResponse { + public static success( + id: string, + result: Type, + statusCode: string, + ): ServerResponse { + try { + const params: Params = { + resmsgid: v4(), + status: 'successful', + err: null, + errmsg: null, + }; + + const resObj: ServerResponse = { + id, + ver: '1.0', + ts: new Date().toISOString(), + params, + responseCode: statusCode, + result, + }; + return resObj; + } catch (e) { + return e; + } + } + + public static error( + id: string, + errmsg: string, + error: string, + statusCode: string, + ): ServerResponse { + try { + const params: Params = { + resmsgid: v4(), + status: 'failed', + err: error, + errmsg: errmsg, + }; + + const resObj: ServerResponse = { + id, + ver: '1.0', + ts: new Date().toISOString(), + params, + responseCode: statusCode, + result: { success: false }, + }; + return resObj; + } catch (e) { + return e; + } + } + +// public static handleBadRequests( +// response: Response, +// apiId: string, +// errmsg: string, +// error: string, +// ) { +// return response +// .status(HttpStatus.BAD_REQUEST) +// .json(APIResponse.error(apiId, errmsg, error, 'BAD_REQUEST')); +// } +} From b4ea69dc859cfcf8e3e9fdf90e03fed99eea0248 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 18 Mar 2024 20:32:42 +0530 Subject: [PATCH 075/408] Fix[Attendance create and update API] --- src/attendance/attendance.controller.ts | 46 +++++++- src/attendance/attendance.service.ts | 136 ++++++++++++++++++++++-- src/attendance/dto/attendance.dto.ts | 26 ++++- 3 files changed, 193 insertions(+), 15 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 6c5ec1d4..be3ab3fc 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -26,6 +26,8 @@ import { CacheInterceptor, Query, Headers, + UsePipes, + ValidationPipe, } from "@nestjs/common"; import { AttendanceDto } from "./dto/attendance.dto"; import { FileInterceptor } from "@nestjs/platform-express"; @@ -68,7 +70,10 @@ export class AttendanceController { .getAttendance(tenantid, attendanceId, request); } + @Post() + + @UsePipes(new ValidationPipe()) @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ @@ -97,11 +102,44 @@ export class AttendanceController { ) { attendanceDto.tenantId = headers["tenantid"]; attendanceDto.image = image?.filename; - return this.attendaceAdapter - .buildAttenceAdapter() + return this.attendaceService .checkAndAddAttendance(request, attendanceDto); } + // @Post() + // @ApiConsumes("multipart/form-data") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Attendance has been created successfully.", + // }) + // @UseInterceptors( + // FileInterceptor("image", { + // storage: diskStorage({ + // destination: process.env.IMAGEPATH, + // filename: editFileName, + // }), + // fileFilter: imageFileFilter, + // }) + // ) + // @ApiBody({ type: AttendanceDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async createAttendace( + // @Headers() headers, + // @Req() request: Request, + // @Body() attendanceDto: AttendanceDto, + // @UploadedFile() image + // ) { + // attendanceDto.tenantId = headers["tenantid"]; + // attendanceDto.image = image?.filename; + // return this.attendaceAdapter + // .buildAttenceAdapter() + // .checkAndAddAttendance(request, attendanceDto); + // } + @Put("/:id") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @@ -130,8 +168,7 @@ export class AttendanceController { image: image?.filename, }; Object.assign(attendanceDto, response); - return this.attendaceAdapter - .buildAttenceAdapter() + return this.attendaceService .updateAttendance(attendanceId, request, attendanceDto); } @@ -165,6 +202,7 @@ export class AttendanceController { @ApiBody({ type: AttendanceSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) + @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", }) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index f4120ce4..41a499f7 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -4,7 +4,7 @@ import jwt_decode from "jwt-decode"; import { InjectRepository } from "@nestjs/typeorm"; import { AttendanceEntity } from "./entities/attendance.entity"; import { Repository } from "typeorm"; -import { Injectable } from "@nestjs/common"; +import { BadRequestException, Injectable } from "@nestjs/common"; import { ErrorResponse } from "src/error-response"; import { AttendanceSearchDto } from "./dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; @@ -22,17 +22,14 @@ export class AttendanceService { try { let { limit, page, filters } = attendanceSearchDto; + if (!limit) { + limit = '0'; + } let offset = 0; if (page > 1) { offset = parseInt(limit) * (page - 1); } - - if (limit.trim() === '') { - limit = '0'; - } - - const whereClause = {}; if (filters && Object.keys(filters).length > 0) { Object.entries(filters).forEach(([key, value]) => { @@ -93,6 +90,131 @@ export class AttendanceService { return attendanceResponse; } + + public async checkAndAddAttendance( + request: any, + attendanceDto: AttendanceDto + ) { + try { + const decoded: any = jwt_decode(request.headers.authorization); + + const userId = + decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + attendanceDto.createdBy = userId; + attendanceDto.updatedBy = userId; + const attendanceToSearch = new AttendanceSearchDto({}); + + attendanceToSearch.filters = { + attendanceDate: attendanceDto.attendanceDate, + userId: attendanceDto.userId, + }; + + + const attendanceFound: any = await this.searchAttendance( + attendanceDto.tenantId, + request, + attendanceToSearch + ); + + + if (attendanceFound?.errorCode) { + return new ErrorResponse({ + errorCode: "500", + errorMessage: attendanceFound?.errorMessage, + }); + } + + if ( + attendanceFound.data.length > 0 && + attendanceFound.statusCode === 200 + ) { + + return await this.updateAttendance( + attendanceFound.data[0].attendanceId, + request, + attendanceDto + ); + } else { + + return await this.createAttendance(request, attendanceDto); + } + } catch (e) { + return e; + } + } + + + public async updateAttendance( + attendanceId: string, + request: any, + attendanceDto: AttendanceDto + ) { + try { + + const attendanceRecord = await this.attendanceRepository.findOne({ + where: { attendanceId }, + }); + + if (!attendanceRecord) { + return new ErrorResponse({ + errorCode: "404", + errorMessage: "Attendance record not found", + }); + } + + + this.attendanceRepository.merge(attendanceRecord, attendanceDto); + + // Save the updated attendance record + const updatedAttendanceRecord = await this.attendanceRepository.save( + attendanceRecord + ); + + return new SuccessResponse({ + statusCode: 200, + message: "Attendance record updated successfully", + data: updatedAttendanceRecord, + }); + } catch (error) { + if (error instanceof BadRequestException) { + console.error("Error updating attendance:", error); + return new ErrorResponse({ + errorCode: "500", + errorMessage: "Internal Server Error", + + }); + } + } + } + + + public async createAttendance(request: any, attendanceDto: AttendanceDto) { + try { + + const attendance = this.attendanceRepository.create(attendanceDto); + const result = await this.attendanceRepository.save(attendance); + + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } catch (error) { + if (error.code === '23503' && error.constraint === 'Attendance_userId_fkey') { + // Handle foreign key constraint violation + return new ErrorResponse({ + errorCode: "23503", + errorMessage: "Please provide valid userID", + }); + } else { + console.error('Error creating attendance:', error); + return new ErrorResponse({ + errorCode: "500", + errorMessage: 'Internal Server Error', + }); + } + } + } } diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 85655e9e..02889f0d 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -1,6 +1,14 @@ +import { ManyToOne, JoinColumn } from 'typeorm'; +import { IsDate, IsDateString, IsEnum, IsUUID, Matches } from 'class-validator'; import { Exclude, Expose } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { IsNotEmpty, IsString, IsObject } from 'class-validator'; +import { User } from 'src/user/entities/user-create-entity'; +enum Attendance{ + present="present", + absent="absent" +} export class AttendanceDto { @Expose() attendanceId: string; @@ -13,16 +21,24 @@ export class AttendanceDto { description: "The userid of the attendance", default: "", }) + @IsNotEmpty() + @IsUUID() @Expose() userId: string; + @ManyToOne(() => User, {nullable:true}) + @JoinColumn({ name: 'userId' }) + user: User; + @ApiProperty({ type: String, description: "The date of the attendance in format yyyy-mm-dd", - default: new Date(), + default: new Date() }) + @IsNotEmpty() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @Expose() - attendanceDate: string; + attendanceDate: Date; @ApiProperty({ type: String, @@ -30,6 +46,8 @@ export class AttendanceDto { default: "", }) @Expose() + @IsNotEmpty() + @IsEnum(Attendance,{message:"Please enter valid enum [present or absent]"}) attendance: string; @ApiProperty({ @@ -48,7 +66,7 @@ export class AttendanceDto { }) @Expose() @ApiPropertyOptional() - latitude: Number; + latitude: number; @ApiProperty({ type: String, @@ -57,7 +75,7 @@ export class AttendanceDto { }) @Expose() @ApiPropertyOptional() - longitude: Number; + longitude: number; @ApiProperty({ type: "string", From 8c1865c5e9d7ab5b1f26d4f44f41b4e7f20790dd Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Tue, 19 Mar 2024 12:15:23 +0530 Subject: [PATCH 076/408] Added success & error response --- src/cohort/cohort.controller.ts | 53 +++++++++++++-------------- src/cohort/cohort.service.ts | 64 +++++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 44 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index e23b07e9..c3147678 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -31,7 +31,7 @@ import { CohortDto } from "./dto/cohort.dto"; import { FileInterceptor } from "@nestjs/platform-express"; import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; import { diskStorage } from "multer"; -import { Response } from "express"; +import { Response, response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; @@ -122,35 +122,36 @@ export class CohortController { public async getCohort( @Headers() headers, @Param("id") cohortId: string, - @Req() request: Request - ) { - let tenantid = headers["tenantid"]; - return this.cohortService.getCohort(tenantid, cohortId, request); - } - //search - @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort list." }) - @ApiBody({ type: CohortSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async searchCohort( - @Headers() headers, @Req() request: Request, - @Body() cohortSearchDto: CohortSearchDto, - @Res() res: Response + @Res() response: Response ) { let tenantid = headers["tenantid"]; - return this.cohortAdapter - .buildCohortAdapter() - .searchCohort(tenantid, request, cohortSearchDto, res); + return this.cohortService.getCohort(tenantid, cohortId, request, response); } + //search + // @Post("/search") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Cohort list." }) + // @ApiBody({ type: CohortSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async searchCohort( + // @Headers() headers, + // @Req() request: Request, + // @Body() cohortSearchDto: CohortSearchDto, + // @Res() res: Response + // ) { + // let tenantid = headers["tenantid"]; + // return this.cohortAdapter + // .buildCohortAdapter() + // .searchCohort(tenantid, request, cohortSearchDto, res); + // } //update @Put("/:id") diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 1a6ba366..972c539d 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from "@nestjs/common"; +import { HttpStatus, Injectable } from "@nestjs/common"; import { CohortInterface } from "./interfaces/cohort.interface"; import { HttpService } from "@nestjs/axios"; import { SuccessResponse } from "src/success-response"; @@ -16,6 +16,10 @@ import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { InjectRepository } from "@nestjs/typeorm"; +import { FieldsService } from "src/adapters/hasura/services/fields.service"; +import { FieldValues } from "src/fields/entities/field-values.entity"; +import { response } from "express"; +import APIResponse from "src/utils/response"; @Injectable() export class CohortService { @@ -23,33 +27,57 @@ export class CohortService { constructor( @InjectRepository(Cohort) - private cohortRepository: Repository + @InjectRepository(FieldValues) + private cohortRepository: Repository, + private readonly fieldsService: FieldsService ) {} - public async getCohort(tenantId: string, cohortId: string, request: any) { + public async getCohort( + tenantId: string, + cohortId: string, + request: any, + response: any + ) { + const apiId = "api.concept.editminiScreeningAnswer"; + console.log("tenantId", tenantId); + console.log("cohortId", cohortId); + try { const cohort = await this.cohortRepository.findOne({ where: { tenantId: tenantId, cohortId: cohortId }, }); - + console.log("cohort", cohort); if (!cohort) { - return new ErrorResponse({ - errorCode: "404", - errorMessage: "Cohort not found.", - }); + return response + .status(HttpStatus.NOT_FOUND) // Change status to 404 Not Found + .send( + APIResponse.error( + apiId, + `Cohort Id is wrong`, + `Cohort not found`, + "COHORT_NOT_FOUND" + ) + ); } - let cohortResponse = await this.mappedResponse(cohort); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: cohortResponse, - }); + return response.status(HttpStatus.OK).send( + APIResponse.success( + apiId, + cohort, // Send cohort data + "Cohort Retrieved Successfully" + ) + ); } catch (error) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: "Something went wrong", - }); + return response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong", + `Failure Retrieving Cohort. Error is: ${error}`, + "INTERNAL_SERVER_ERROR" + ) + ); } } From 2e4e8e6f0131133d3dc8d8de3e4b0070e956edcc Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Tue, 19 Mar 2024 12:32:47 +0530 Subject: [PATCH 077/408] Remove commented code and console --- src/cohort/cohort.controller.ts | 72 +++++++++++---------------------- src/cohort/cohort.service.ts | 5 --- 2 files changed, 24 insertions(+), 53 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index c3147678..ca666cef 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -83,30 +83,6 @@ export class CohortController { .createCohort(request, cohortCreateDto); } - // //get cohort - // @Get("/:id") - // @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Cohort detail" }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @SerializeOptions({ - // strategy: "excludeAll", - // }) - // @ApiHeader({ - // name: "tenantid", - // }) - // public async getCohort( - // @Headers() headers, - // @Param("id") cohortId: string, - // @Req() request: Request, - // @Res() res: Response - // ) { - // let tenantid = headers["tenantid"]; - // return this.cohortAdapter - // .buildCohortAdapter() - // .getCohort(tenantid, cohortId, request, res); - // } - //get cohort @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) @@ -128,30 +104,30 @@ export class CohortController { let tenantid = headers["tenantid"]; return this.cohortService.getCohort(tenantid, cohortId, request, response); } - //search - // @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Cohort list." }) - // @ApiBody({ type: CohortSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - // @SerializeOptions({ - // strategy: "excludeAll", - // }) - // @ApiHeader({ - // name: "tenantid", - // }) - // public async searchCohort( - // @Headers() headers, - // @Req() request: Request, - // @Body() cohortSearchDto: CohortSearchDto, - // @Res() res: Response - // ) { - // let tenantid = headers["tenantid"]; - // return this.cohortAdapter - // .buildCohortAdapter() - // .searchCohort(tenantid, request, cohortSearchDto, res); - // } + search; + @Post("/search") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Cohort list." }) + @ApiBody({ type: CohortSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async searchCohort( + @Headers() headers, + @Req() request: Request, + @Body() cohortSearchDto: CohortSearchDto, + @Res() res: Response + ) { + let tenantid = headers["tenantid"]; + return this.cohortAdapter + .buildCohortAdapter() + .searchCohort(tenantid, request, cohortSearchDto, res); + } //update @Put("/:id") diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 972c539d..036b407e 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -7,10 +7,8 @@ const resolvePath = require("object-resolve-path"); import jwt_decode from "jwt-decode"; import { CohortDto } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; -// import { IServicelocatorcohort } from "../cohortservicelocator"; import { UserDto } from "src/user/dto/user.dto"; import { StudentDto } from "src/student/dto/student.dto"; -// import { FieldsService } from "./services/fields.service"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; @@ -39,14 +37,11 @@ export class CohortService { response: any ) { const apiId = "api.concept.editminiScreeningAnswer"; - console.log("tenantId", tenantId); - console.log("cohortId", cohortId); try { const cohort = await this.cohortRepository.findOne({ where: { tenantId: tenantId, cohortId: cohortId }, }); - console.log("cohort", cohort); if (!cohort) { return response .status(HttpStatus.NOT_FOUND) // Change status to 404 Not Found From 01969439509145785915825ca8196a00737a10a7 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 21 Mar 2024 11:44:44 +0530 Subject: [PATCH 078/408] Fix[Attendance by-date and bulk attendance API] --- package-lock.json | 9811 +-------------------- package.json | 4 +- src/attendance/attendance.controller.ts | 33 +- src/attendance/attendance.service.ts | 119 +- src/attendance/dto/attendance-date.dto.ts | 4 +- src/attendance/dto/attendance.dto.ts | 19 +- 6 files changed, 195 insertions(+), 9795 deletions(-) diff --git a/package-lock.json b/package-lock.json index f438591c..842f7f9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9657 +1,8 @@ { "name": "shiksha-backend-v2", "version": "0.0.1", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "shiksha-backend-v2", - "version": "0.0.1", - "license": "UNLICENSED", - "dependencies": { - "@nestjs/axios": "^0.0.7", - "@nestjs/common": "^8.4.2", - "@nestjs/config": "^2.0.0", - "@nestjs/core": "^8.0.0", - "@nestjs/jwt": "^8.0.0", - "@nestjs/platform-express": "^8.0.0", - "@nestjs/schedule": "^1.1.0", - "@nestjs/swagger": "^5.2.0", - "@nestjs/typeorm": "^10.0.2", - "axios": "^0.26.1", - "cache-manager": "^3.6.1", - "class-transformer": "^0.5.1", - "class-validator": "^0.13.2", - "dotenv": "^16.0.0", - "express": "^4.17.3", - "form-data": "^4.0.0", - "graphql-tag": "^2.12.6", - "jwt-decode": "^3.1.2", - "moment": "^2.29.3", - "multer": "^1.4.4", - "node-cron": "^3.0.1", - "node-schedule": "^2.1.0", - "object-resolve-path": "^1.1.1", - "pg": "^8.11.3", - "reflect-metadata": "^0.1.13", - "rimraf": "^3.0.2", - "rxjs": "^7.2.0", - "swagger-ui-express": "^4.3.0", - "templates.js": "^0.3.11" - }, - "devDependencies": { - "@nestjs/cli": "^8.0.0", - "@nestjs/schematics": "^8.0.0", - "@nestjs/testing": "^8.0.0", - "@types/cache-manager": "^3.4.3", - "@types/cron": "^1.7.3", - "@types/express": "^4.17.13", - "@types/jest": "27.4.1", - "@types/node": "^16.0.0", - "@types/supertest": "^2.0.11", - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^8.0.1", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0", - "jest": "^27.2.5", - "prettier": "^2.3.2", - "source-map-support": "^0.5.20", - "supertest": "^6.1.3", - "ts-jest": "^27.0.3", - "ts-loader": "^9.2.3", - "ts-node": "^10.0.0", - "tsconfig-paths": "^3.10.1", - "typescript": "^4.3.5" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@angular-devkit/core": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.6.tgz", - "integrity": "sha512-8h2mWdBTN/dYwZuzKMg2IODlOWMdbJcpQG4XVrkk9ejCPP+3aX5Aa3glCe/voN6eBNiRfs8YDM0jxmpN2aWVtg==", - "dev": true, - "dependencies": { - "ajv": "8.9.0", - "ajv-formats": "2.1.1", - "fast-json-stable-stringify": "2.1.0", - "magic-string": "0.25.7", - "rxjs": "6.6.7", - "source-map": "0.7.3" - }, - "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/core/node_modules/ajv": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", - "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular-devkit/core/node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/core/node_modules/ajv-formats/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular-devkit/core/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/core/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@angular-devkit/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@angular-devkit/schematics": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.6.tgz", - "integrity": "sha512-mPgSqdnZRuPSMeUA+T+mwVCrq2yhXpcYm1/Rjbhy09CyHs4wSrFv21WHCrE6shlvXpcmwr0n+I0DIeagAPmjUA==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "13.2.6", - "jsonc-parser": "3.0.0", - "magic-string": "0.25.7", - "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-devkit/schematics-cli": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-13.2.6.tgz", - "integrity": "sha512-VdMLn4DoTswjk+1RL+pod8EwLkzh8pMT2OBJ9dhsITru1sr0/2nhsqRwZzZylAXjrFwdfPj1E/vfcAfSkmMGvw==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "13.2.6", - "@angular-devkit/schematics": "13.2.6", - "ansi-colors": "4.1.1", - "inquirer": "8.2.0", - "minimist": "1.2.5", - "symbol-observable": "4.0.0" - }, - "bin": { - "schematics": "bin/schematics.js" - }, - "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.7.tgz", - "integrity": "sha512-djHlEfFHnSnTAcPb7dATbiM5HxGOP98+3JLBZtjRb5I7RXrw7kFRoG2dXM8cm3H+o11A8IFH/uprmJpwFynRNQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.7", - "@babel/parser": "^7.17.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.7.tgz", - "integrity": "sha512-TKsj9NkjJfTBxM7Phfy7kv6yYc4ZcOo+AaWGqQOKTPDOmcGkIFb5xNA746eKisQkm4yavUYh4InYM9S+VnO01w==", - "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.7.tgz", - "integrity": "sha512-bm3AQf45vR4gKggRfvJdYJ0gFLoCbsPxiFLSH6hTVYABptNHY6l9NrhnucVjQ/X+SPtLANT9lc0fFhikj+VBRA==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", - "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "devOptional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "devOptional": true, - "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "peer": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "peer": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "peer": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "peer": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "peer": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/console/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", - "dev": true, - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/environment/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/fake-timers/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", - "dev": true, - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", - "dev": true, - "dependencies": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/types/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@nestjs/axios": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.0.7.tgz", - "integrity": "sha512-at8nj+1Nb8UleHcIN5QqZYeWX54m4m9s9gxzVE1qWy00neX2rg0+h2TfbWsnDi2tc23zIxqexanxMOJZbzO0CA==", - "dependencies": { - "axios": "0.26.0" - }, - "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0", - "reflect-metadata": "^0.1.12", - "rxjs": "^6.0.0 || ^7.0.0" - } - }, - "node_modules/@nestjs/axios/node_modules/axios": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", - "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/@nestjs/cli": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-8.2.3.tgz", - "integrity": "sha512-p//DACefn40VClXroxzS+2pkSdaXYvKKcr4bFOUBMTdJqT9he+U9ifcJUkg/h1bFU/Y8SS2cUsTyl0ZBHHHRcw==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "13.2.6", - "@angular-devkit/schematics": "13.2.6", - "@angular-devkit/schematics-cli": "13.2.6", - "@nestjs/schematics": "^8.0.3", - "chalk": "3.0.0", - "chokidar": "3.5.3", - "cli-table3": "0.6.1", - "commander": "4.1.1", - "fork-ts-checker-webpack-plugin": "7.2.1", - "inquirer": "7.3.3", - "node-emoji": "1.11.0", - "ora": "5.4.1", - "os-name": "4.0.1", - "rimraf": "3.0.2", - "shelljs": "0.8.5", - "source-map-support": "0.5.21", - "tree-kill": "1.2.2", - "tsconfig-paths": "3.14.0", - "tsconfig-paths-webpack-plugin": "3.5.2", - "typescript": "4.6.2", - "webpack": "5.70.0", - "webpack-node-externals": "3.0.0" - }, - "bin": { - "nest": "bin/nest.js" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 6.11.0" - } - }, - "node_modules/@nestjs/cli/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nestjs/common": { - "version": "8.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-8.4.3.tgz", - "integrity": "sha512-QIhWykB7IPOwHQB/K9wMwmQKibQ5dhg9dt8ySOoD36uFFwN3RJQelzMFF9Rtu7hrMPk6pSyismEUKQ8BZMUD9w==", - "dependencies": { - "axios": "0.26.1", - "iterare": "1.2.1", - "tslib": "2.3.1", - "uuid": "8.3.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "cache-manager": "*", - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "cache-manager": { - "optional": true - }, - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.0.0.tgz", - "integrity": "sha512-Hi1k/1S5ogsS5c0OtNm72thiLSngijOaLDFaGI5ZPxNGpF23lctPg6ox3pYIOhXVRX/u+eiUIp71gswH2k8YNw==", - "dependencies": { - "dotenv": "16.0.0", - "dotenv-expand": "8.0.2", - "lodash": "4.17.21", - "uuid": "8.3.2" - }, - "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0", - "reflect-metadata": "^0.1.13", - "rxjs": "^6.0.0 || ^7.2.0" - } - }, - "node_modules/@nestjs/core": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-8.4.1.tgz", - "integrity": "sha512-JUV2cy/5z8MS2SRwszLmyOCclMMlyumxIbC1YFFlnSInhu7ODhrHLIMztyGmyAIuaehbOnyXPtHkjl01rHxc5w==", - "hasInstallScript": true, - "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "object-hash": "3.0.0", - "path-to-regexp": "3.2.0", - "tslib": "2.3.1", - "uuid": "8.3.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0", - "@nestjs/microservices": "^8.0.0", - "@nestjs/platform-express": "^8.0.0", - "@nestjs/websockets": "^8.0.0", - "reflect-metadata": "^0.1.12", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } - } - }, - "node_modules/@nestjs/jwt": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-8.0.0.tgz", - "integrity": "sha512-fz2LQgYY2zmuD8S+8UE215anwKyXlnB/1FwJQLVR47clNfMeFMK8WCxmn6xdPhF5JKuV1crO6FVabb1qWzDxqQ==", - "dependencies": { - "@types/jsonwebtoken": "8.5.4", - "jsonwebtoken": "8.5.1" - }, - "peerDependencies": { - "@nestjs/common": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@nestjs/mapped-types": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz", - "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==", - "peerDependencies": { - "@nestjs/common": "^7.0.8 || ^8.0.0", - "class-transformer": "^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0", - "class-validator": "^0.11.1 || ^0.12.0 || ^0.13.0", - "reflect-metadata": "^0.1.12" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/platform-express": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-8.4.1.tgz", - "integrity": "sha512-c18zuhoegJsS1vZueGaNyvU8mLyFtS+6FJ2WAzDOXNpchpq0okrEPdKBifIisWuxgffQYKIufoK73vEfXSfDLg==", - "dependencies": { - "body-parser": "1.19.2", - "cors": "2.8.5", - "express": "4.17.3", - "multer": "1.4.4", - "tslib": "2.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0", - "@nestjs/core": "^8.0.0" - } - }, - "node_modules/@nestjs/schedule": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-1.1.0.tgz", - "integrity": "sha512-0QpbwClUildXqlyoaygG+aIQZNNMv31XDyQxX+Ob1zw/3I8+AVrDlBwZHQ+tlhIcJFR8aG+VTH8xwIjXwtS1UA==", - "dependencies": { - "cron": "1.8.2", - "uuid": "8.3.2" - }, - "peerDependencies": { - "@nestjs/common": "^6.10.11 || ^7.0.0 || ^8.0.0", - "@nestjs/core": "^7.0.0 || ^8.0.0", - "reflect-metadata": "^0.1.12" - } - }, - "node_modules/@nestjs/schematics": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-8.0.8.tgz", - "integrity": "sha512-xIIb5YnMQN/OJQ68+MCapy2bXvTxSWgINoqQbyZWkLL/yTIuROvZCdtV850NPGyr7f7l93VBP0ZPitbFIexy3Q==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "13.2.5", - "@angular-devkit/schematics": "13.2.5", - "fs-extra": "10.0.1", - "jsonc-parser": "3.0.0", - "pluralize": "8.0.0" - }, - "peerDependencies": { - "typescript": "^3.4.5 || ^4.3.5" - } - }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { - "version": "13.2.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.5.tgz", - "integrity": "sha512-WuWp/1R0FtCHPBcJLF13lTLHETtDGFUX0ULfGPRaYB5OVCSQcovVp5UbZTTy/Ss3ub3EOEmJlU8kMJfBrWuq+A==", - "dev": true, - "dependencies": { - "ajv": "8.9.0", - "ajv-formats": "2.1.1", - "fast-json-stable-stringify": "2.1.0", - "magic-string": "0.25.7", - "rxjs": "6.6.7", - "source-map": "0.7.3" - }, - "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { - "version": "13.2.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.5.tgz", - "integrity": "sha512-kAye6VYiF9JQAoeO+BYhy8eT2QOmhB+WLziRjXoFCBxh5+yXTygTVfs9fD5jmIpHmeu4hd2ErSh69yT5xWcD9g==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "13.2.5", - "jsonc-parser": "3.0.0", - "magic-string": "0.25.7", - "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@nestjs/schematics/node_modules/ajv": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", - "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@nestjs/schematics/node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/@nestjs/schematics/node_modules/ajv-formats/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@nestjs/schematics/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@nestjs/schematics/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nestjs/schematics/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@nestjs/swagger": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-5.2.1.tgz", - "integrity": "sha512-7dNa08WCnTsW/oAk3Ujde+z64JMfNm19DhpXasFR8oJp/9pggYAbYU927HpA+GJsSFJX6adjIRZsCKUqaGWznw==", - "dependencies": { - "@nestjs/mapped-types": "1.0.1", - "lodash": "4.17.21", - "path-to-regexp": "3.2.0" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0", - "@nestjs/core": "^8.0.0", - "fastify-swagger": "*", - "reflect-metadata": "^0.1.12", - "swagger-ui-express": "*" - }, - "peerDependenciesMeta": { - "fastify-swagger": { - "optional": true - }, - "swagger-ui-express": { - "optional": true - } - } - }, - "node_modules/@nestjs/testing": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-8.4.1.tgz", - "integrity": "sha512-LOvsLuNh2eRwAtyeoIZWmUZ08wt7QrPrKQujWuRyv+vBYtC+FLHjqreWLpwG2yulNEoQs9Qlr2ubPvFGT1953g==", - "dev": true, - "dependencies": { - "optional": "0.1.4", - "tslib": "2.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0", - "@nestjs/core": "^8.0.0", - "@nestjs/microservices": "^8.0.0", - "@nestjs/platform-express": "^8.0.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - } - } - }, - "node_modules/@nestjs/typeorm": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", - "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", - "dependencies": { - "uuid": "9.0.1" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13 || ^0.2.0", - "rxjs": "^7.2.0", - "typeorm": "^0.3.0" - } - }, - "node_modules/@nestjs/typeorm/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sqltools/formatter": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", - "peer": true - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "devOptional": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "devOptional": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "devOptional": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "devOptional": true - }, - "node_modules/@types/babel__core": { - "version": "7.1.18", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.18.tgz", - "integrity": "sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.3.0" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/body-parser/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@types/cache-manager": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-3.4.3.tgz", - "integrity": "sha512-71aBXoFYXZW4TnDHHH8gExw2lS28BZaWeKefgsiJI7QYZeJfUEbMKw6CQtzGjlYQcGIWwB76hcCrkVA3YHSvsw==", - "dev": true - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", - "dev": true - }, - "node_modules/@types/cron": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@types/cron/-/cron-1.7.3.tgz", - "integrity": "sha512-iPmUXyIJG1Js+ldPYhOQcYU3kCAQ2FWrSkm1FJPoii2eYSn6wEW6onPukNTT0bfiflexNSRPl6KWmAIqS+36YA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "moment": ">=2.14.0" - } - }, - "node_modules/@types/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/express-serve-static-core/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/graceful-fs/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", - "dev": true, - "dependencies": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "node_modules/@types/jsonwebtoken": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", - "integrity": "sha512-4L8msWK31oXwdtC81RmRBAULd0ShnAHjBuKT9MRQpjP0piNrZdXyTRcKY9/UIfhGeKIT4PvF5amOOUbbT/9Wpg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "node_modules/@types/node": { - "version": "16.11.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", - "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==" - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/prettier": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", - "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", - "dev": true, - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "node_modules/@types/superagent/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/@types/supertest": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.11.tgz", - "integrity": "sha512-uci4Esokrw9qGb9bvhhSVEjd6rkny/dk5PK/Qz4yxKiyppEI+dOPlNrZBahE3i+PoKFYyDxChVXZ/ysS/nrm1Q==", - "dev": true, - "dependencies": { - "@types/superagent": "*" - } - }, - "node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", - "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/type-utils": "5.15.0", - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", - "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", - "debug": "^4.3.2" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", - "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", - "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", - "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", - "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", - "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", - "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.15.0", - "eslint-visitor-keys": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "devOptional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals/node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "devOptional": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ajv/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "peer": true - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/app-root-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", - "peer": true, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dev": true, - "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz", - "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001313", - "electron-to-chromium": "^1.4.76", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "dependencies": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cache-manager": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-3.6.1.tgz", - "integrity": "sha512-jxJvGYhN5dUgpriAdsDnnYbKse4dEXI5i3XpwTfPq5utPtXH1uYXWyGLHGlbSlh9Vq4ytrgAUVwY+IodNeKigA==", - "dependencies": { - "async": "3.2.3", - "lodash": "^4.17.21", - "lru-cache": "6.0.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001317", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz", - "integrity": "sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", - "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", - "dev": true - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "node_modules/class-transformer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" - }, - "node_modules/class-validator": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz", - "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==", - "dependencies": { - "libphonenumber-js": "^1.9.43", - "validator": "^13.7.0" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "peer": true, - "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "bin": { - "highlight": "bin/highlight" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/cli-highlight/node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "peer": true - }, - "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", - "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "colors": "1.4.0" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true - }, - "node_modules/cron": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz", - "integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==", - "dependencies": { - "moment-timezone": "^0.5.x" - } - }, - "node_modules/cron-parser": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", - "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", - "dependencies": { - "is-nan": "^1.3.2", - "luxon": "^1.26.0" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", - "peer": true - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", - "dev": true, - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "dependencies": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", - "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", - "engines": { - "node": ">=12" - } - }, - "node_modules/dotenv-expand": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.2.tgz", - "integrity": "sha512-vKKAk+VOzAWOV/dPIeSYqhgC/TQY+6L6Ibkzfsr8xd1stdBsTuGu9asCOXgbYbBeS+f2Y6lqqEuw7riOA+xEUQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "peer": true - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.84", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.84.tgz", - "integrity": "sha512-b+DdcyOiZtLXHdgEG8lncYJdxbdJWJvclPNMg0eLUDcSOSO876WA/pYjdSblUTd7eJdIs4YdIxHWGazx7UPSJw==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "dependencies": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "peer": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "peer": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.1.tgz", - "integrity": "sha512-uOfQdg/iQ8iokQ64qcbu8iZb114rOmaKLQFu7hU14/eJaKgsP91cQ7ts7v2iiDld6TzDe84Meksha8/MkWiCyw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "schema-utils": "4.0.0", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "vue-template-compiler": "*", - "webpack": "^5.11.0" - }, - "peerDependenciesMeta": { - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formidable": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz", - "integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==", - "dev": true, - "dependencies": { - "dezalgo": "1.0.3", - "hexoid": "1.0.0", - "once": "1.4.0", - "qs": "6.9.3" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/formidable/node_modules/qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==", - "dev": true, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "node_modules/graphql": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz", - "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } - }, - "node_modules/graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "peer": true, - "engines": { - "node": "*" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/inquirer/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/inquirer/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterare": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "peer": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", - "dev": true, - "dependencies": { - "@jest/core": "^27.5.1", - "import-local": "^3.0.2", - "jest-cli": "^27.5.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-circus/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dev": true, - "dependencies": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-node/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-haste-map/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-jasmine2/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", - "dev": true, - "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dev": true, - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runner/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runtime/node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dev": true, - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-serializer/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-util/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-watcher/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=4", - "npm": ">=1.4.28" - } - }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/levn/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/levn/node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libphonenumber-js": { - "version": "1.9.50", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.50.tgz", - "integrity": "sha512-cCzQPChw2XbordcO2LKiw5Htx5leHVfFk/EXkxNHqJfFo7Fndcb1kF5wPJpc316vCJhhikedYnVysMh3Sc7Ocw==" - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/long-timeout": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", - "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/luxon": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", - "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==", - "engines": { - "node": "*" - } - }, - "node_modules/macos-release": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", - "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", - "dev": true, - "dependencies": { - "fs-monkey": "1.0.3" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "peer": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", - "dependencies": { - "moment": ">= 2.9.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/multer": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", - "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/multer/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "peer": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/node-cron": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.1.tgz", - "integrity": "sha512-RAWZTNn2M5KDIUV/389UX0EXsqvdFAwc9QwHQceh0Ga56dygqSRthqIjwpgZsoDspHGt2rkHdk9Z4RgfPMdALw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true - }, - "node_modules/node-schedule": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.0.tgz", - "integrity": "sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==", - "dependencies": { - "cron-parser": "^3.5.0", - "long-timeout": "0.1.1", - "sorted-array-functions": "^1.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-resolve-path": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-resolve-path/-/object-resolve-path-1.1.1.tgz", - "integrity": "sha1-p/j5Poogr4DkQhe6fbVDFtnRIjI=" - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optional": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/optional/-/optional-0.1.4.tgz", - "integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==", - "dev": true - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/optionator/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/optionator/node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/os-name": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", - "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", - "dev": true, - "dependencies": { - "macos-release": "^2.5.0", - "windows-release": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "peer": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "peer": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "peer": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": { - "split2": "^4.1.0" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", - "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "peer": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz", - "integrity": "sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ==", - "dev": true, - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.3", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "^2.5.0", - "qs": "^6.10.1", - "readable-stream": "^3.6.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, - "node_modules/superagent/node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/superagent/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/superagent/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/supertest": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz", - "integrity": "sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^7.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/swagger-ui-dist": { - "version": "4.10.3", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.10.3.tgz", - "integrity": "sha512-eR4vsd7sYo0Sx7ZKRP5Z04yij7JkNmIlUQfrDQgC+xO5ABYx+waabzN+nDsQTLAJ4Z04bjkRd8xqkJtbxr3G7w==" - }, - "node_modules/swagger-ui-express": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.3.0.tgz", - "integrity": "sha512-jN46SEEe9EoXa3ZgZoKgnSF6z0w3tnM1yqhO4Y+Q4iZVc8JOQB960EZpIAz6rNROrDApVDwcMHR0mhlnc/5Omw==", - "dependencies": { - "swagger-ui-dist": ">=4.1.3" - }, - "engines": { - "node": ">= v0.10.32" - }, - "peerDependencies": { - "express": ">=4.0.0" - } - }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/templates.js": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/templates.js/-/templates.js-0.3.11.tgz", - "integrity": "sha1-qAtXgaoySmHpK+GmlHDVATQd6QQ=", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", - "dev": true, - "dependencies": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", - "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", - "dev": true, - "dependencies": { - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "peer": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "peer": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-jest": { - "version": "27.1.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.3.tgz", - "integrity": "sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@types/jest": "^27.0.0", - "babel-jest": ">=27.0.0 <28", - "esbuild": "~0.14.0", - "jest": "^27.0.0", - "typescript": ">=3.8 <5.0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/ts-loader": { - "version": "9.2.8", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", - "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", - "devOptional": true, - "dependencies": { - "@cspotcode/source-map-support": "0.7.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.0.tgz", - "integrity": "sha512-cg/1jAZoL57R39+wiw4u/SCC6Ic9Q5NqjBOb+9xISedOYurfog9ZNmKJSxAnb2m/5Bq4lE9lhUcau33Ml8DM0g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths-webpack-plugin": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz", - "integrity": "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tsconfig-paths": "^3.9.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typeorm": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", - "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", - "peer": true, - "dependencies": { - "@sqltools/formatter": "^1.2.5", - "app-root-path": "^3.1.0", - "buffer": "^6.0.3", - "chalk": "^4.1.2", - "cli-highlight": "^2.1.11", - "dayjs": "^1.11.9", - "debug": "^4.3.4", - "dotenv": "^16.0.3", - "glob": "^10.3.10", - "mkdirp": "^2.1.3", - "reflect-metadata": "^0.2.1", - "sha.js": "^2.4.11", - "tslib": "^2.5.0", - "uuid": "^9.0.0", - "yargs": "^17.6.2" - }, - "bin": { - "typeorm": "cli.js", - "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", - "typeorm-ts-node-esm": "cli-ts-node-esm.js" - }, - "engines": { - "node": ">=16.13.0" - }, - "funding": { - "url": "https://opencollective.com/typeorm" - }, - "peerDependencies": { - "@google-cloud/spanner": "^5.18.0", - "@sap/hana-client": "^2.12.25", - "better-sqlite3": "^7.1.2 || ^8.0.0 || ^9.0.0", - "hdb-pool": "^0.1.6", - "ioredis": "^5.0.4", - "mongodb": "^5.8.0", - "mssql": "^9.1.1 || ^10.0.1", - "mysql2": "^2.2.5 || ^3.0.1", - "oracledb": "^6.3.0", - "pg": "^8.5.1", - "pg-native": "^3.0.0", - "pg-query-stream": "^4.0.0", - "redis": "^3.1.1 || ^4.0.0", - "sql.js": "^1.4.0", - "sqlite3": "^5.0.3", - "ts-node": "^10.7.0", - "typeorm-aurora-data-api-driver": "^2.0.0" - }, - "peerDependenciesMeta": { - "@google-cloud/spanner": { - "optional": true - }, - "@sap/hana-client": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "hdb-pool": { - "optional": true - }, - "ioredis": { - "optional": true - }, - "mongodb": { - "optional": true - }, - "mssql": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "oracledb": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-native": { - "optional": true - }, - "pg-query-stream": { - "optional": true - }, - "redis": { - "optional": true - }, - "sql.js": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "ts-node": { - "optional": true - }, - "typeorm-aurora-data-api-driver": { - "optional": true - } - } - }, - "node_modules/typeorm/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typeorm/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peer": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/typeorm/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/typeorm/node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/typeorm/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "peer": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typeorm/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "peer": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typeorm/node_modules/mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", - "peer": true, - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typeorm/node_modules/reflect-metadata": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", - "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", - "peer": true - }, - "node_modules/typeorm/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "peer": true - }, - "node_modules/typeorm/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/typeorm/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/typeorm/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", - "devOptional": true - }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" - } - }, - "node_modules/webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-node-externals": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", - "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/windows-release": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", - "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", - "dev": true, - "dependencies": { - "execa": "^4.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/windows-release/node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/windows-release/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/windows-release/node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "peer": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, - "engines": { - "node": ">=6" - } - } - }, "dependencies": { "@ampproject/remapping": { "version": "2.1.2", @@ -10240,13 +591,13 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "devOptional": true + "dev": true }, "@cspotcode/source-map-support": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "devOptional": true, + "dev": true, "requires": { "@cspotcode/source-map-consumer": "0.8.0" } @@ -10289,7 +640,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "peer": true, "requires": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -10302,26 +652,22 @@ "ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "peer": true + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, "ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "peer": true + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "peer": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "peer": true, "requires": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -10332,7 +678,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "peer": true, "requires": { "ansi-regex": "^6.0.1" } @@ -10341,7 +686,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "peer": true, "requires": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -10765,8 +1109,7 @@ "@nestjs/mapped-types": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz", - "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==", - "requires": {} + "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==" }, "@nestjs/platform-express": { "version": "8.4.1", @@ -10962,8 +1305,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "peer": true + "optional": true }, "@sinonjs/commons": { "version": "1.8.3", @@ -10986,8 +1328,7 @@ "@sqltools/formatter": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", - "peer": true + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" }, "@tootallnate/once": { "version": "1.1.2", @@ -10999,25 +1340,25 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "devOptional": true + "dev": true }, "@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "devOptional": true + "dev": true }, "@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "devOptional": true + "dev": true }, "@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "devOptional": true + "dev": true }, "@types/babel__core": { "version": "7.1.18", @@ -11618,7 +1959,7 @@ "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "devOptional": true + "dev": true }, "acorn-globals": { "version": "6.0.0", @@ -11648,21 +1989,19 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} + "dev": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "devOptional": true + "dev": true }, "agent-base": { "version": "6.0.2", @@ -11697,8 +2036,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "ansi-colors": { "version": "4.1.1", @@ -11739,8 +2077,7 @@ "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "peer": true + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "anymatch": { "version": "3.1.2", @@ -11755,8 +2092,7 @@ "app-root-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", - "peer": true + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==" }, "append-field": { "version": "1.0.0", @@ -11767,7 +2103,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true + "dev": true }, "argparse": { "version": "2.0.1", @@ -12175,7 +2511,6 @@ "version": "2.1.11", "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "peer": true, "requires": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", @@ -12188,8 +2523,7 @@ "parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "peer": true + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" } } }, @@ -12415,7 +2749,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true + "dev": true }, "cron": { "version": "1.8.2", @@ -12478,11 +2812,15 @@ "whatwg-url": "^8.0.0" } }, + "date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" + }, "dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", - "peer": true + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" }, "debug": { "version": "4.3.4", @@ -12578,7 +2916,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true + "dev": true }, "diff-sequences": { "version": "27.5.1", @@ -12634,8 +2972,7 @@ "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "peer": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "ecdsa-sig-formatter": { "version": "1.0.11", @@ -12835,8 +3172,7 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-prettier": { "version": "4.0.0", @@ -13200,7 +3536,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "peer": true, "requires": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -13209,8 +3544,7 @@ "signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "peer": true + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" } } }, @@ -13447,12 +3781,6 @@ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, - "graphql": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz", - "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==", - "peer": true - }, "graphql-tag": { "version": "2.12.6", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", @@ -13496,8 +3824,7 @@ "highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "peer": true + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" }, "html-encoding-sniffer": { "version": "2.0.1", @@ -13842,7 +4169,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "peer": true, "requires": { "@isaacs/cliui": "^8.0.2", "@pkgjs/parseargs": "^0.11.0" @@ -14165,8 +4491,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "27.5.1", @@ -14760,7 +5085,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true + "dev": true }, "makeerror": { "version": "1.0.12", @@ -14858,8 +5183,7 @@ "minipass": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "peer": true + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" }, "mkdirp": { "version": "0.5.5", @@ -14922,7 +5246,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "peer": true, "requires": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -15212,7 +5535,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "peer": true, "requires": { "parse5": "^6.0.1" } @@ -15248,7 +5570,6 @@ "version": "1.10.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "peer": true, "requires": { "lru-cache": "^9.1.1 || ^10.0.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -15257,8 +5578,7 @@ "lru-cache": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "peer": true + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" } } }, @@ -15307,8 +5627,7 @@ "pg-pool": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==" }, "pg-protocol": { "version": "1.6.0", @@ -15764,7 +6083,6 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "peer": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -15888,11 +6206,6 @@ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -15917,13 +6230,17 @@ "version": "npm:string-width@4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "peer": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -15936,7 +6253,6 @@ "version": "npm:strip-ansi@6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "peer": true, "requires": { "ansi-regex": "^5.0.1" } @@ -16149,7 +6465,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "peer": true, "requires": { "any-promise": "^1.0.0" } @@ -16158,7 +6473,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "peer": true, "requires": { "thenify": ">= 3.1.0 < 4" } @@ -16276,7 +6590,7 @@ "version": "10.7.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", - "devOptional": true, + "dev": true, "requires": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", @@ -16397,7 +6711,6 @@ "version": "0.3.20", "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", - "peer": true, "requires": { "@sqltools/formatter": "^1.2.5", "app-root-path": "^3.1.0", @@ -16420,7 +6733,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, "requires": { "balanced-match": "^1.0.0" } @@ -16429,7 +6741,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "peer": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -16439,7 +6750,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "peer": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -16449,14 +6759,12 @@ "dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "peer": true + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" }, "glob": { "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "peer": true, "requires": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.5", @@ -16469,7 +6777,6 @@ "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "peer": true, "requires": { "brace-expansion": "^2.0.1" } @@ -16477,32 +6784,27 @@ "mkdirp": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", - "peer": true + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==" }, "reflect-metadata": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", - "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", - "peer": true + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" }, "tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "peer": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "peer": true + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "peer": true, "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -16516,8 +6818,7 @@ "yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "peer": true + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" } } }, @@ -16525,7 +6826,7 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", - "devOptional": true + "dev": true }, "universalify": { "version": "2.0.0", @@ -16572,7 +6873,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", - "devOptional": true + "dev": true }, "v8-to-istanbul": { "version": "8.1.1", @@ -16796,7 +7097,6 @@ "version": "npm:wrap-ansi@7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "peer": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -16824,8 +7124,7 @@ "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "requires": {} + "dev": true }, "xml-name-validator": { "version": "3.0.0", @@ -16883,7 +7182,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true + "dev": true } } } diff --git a/package.json b/package.json index a470ee4c..4026374b 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "cache-manager": "^3.6.1", "class-transformer": "^0.5.1", "class-validator": "^0.13.2", + "date-fns": "^3.6.0", "dotenv": "^16.0.0", "express": "^4.17.3", "form-data": "^4.0.0", @@ -49,7 +50,8 @@ "rimraf": "^3.0.2", "rxjs": "^7.2.0", "swagger-ui-express": "^4.3.0", - "templates.js": "^0.3.11" + "templates.js": "^0.3.11", + "typeorm": "^0.3.20" }, "devDependencies": { "@nestjs/cli": "^8.0.0", diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index be3ab3fc..b2903e42 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -171,37 +171,12 @@ export class AttendanceController { return this.attendaceService .updateAttendance(attendanceId, request, attendanceDto); } - @Post("/search") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Attendance list." }) @ApiBody({ type: AttendanceSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async searchAttendance( - @Headers() headers, - @Req() request: Request, - @Body() studentSearchDto: AttendanceSearchDto - ) { - let tenantid = headers["tenantid"]; - return this.attendaceAdapter - .buildAttenceAdapter() - .searchAttendance(tenantid, request, studentSearchDto); - } - - - @Post("/searchNew") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Attendance list." }) - @ApiBody({ type: AttendanceSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", @@ -233,9 +208,7 @@ export class AttendanceController { @Body() attendanceDateDto: AttendanceDateDto ) { const tenantId = headers["tenantid"]; - return this.attendaceAdapter - .buildAttenceAdapter() - .attendanceByDate(tenantId, request, attendanceDateDto); + return this.attendaceService.attendanceByDate(tenantId, request, attendanceDateDto); } @Post("bulkAttendance") @@ -249,14 +222,14 @@ export class AttendanceController { @ApiHeader({ name: "tenantid", }) + @UsePipes(ValidationPipe) public async multipleAttendance( @Headers() headers, @Req() request: Request, @Body() attendanceDtos: [AttendanceDto] ) { let tenantid = headers["tenantid"]; - return this.attendaceAdapter - .buildAttenceAdapter() + return this.attendaceService .multipleAttendance(tenantid, request, attendanceDtos); } diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 41a499f7..1f8776d8 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -1,14 +1,17 @@ +import { isAfter } from 'date-fns'; import { ConfigService } from '@nestjs/config'; import { Client } from 'pg'; import jwt_decode from "jwt-decode"; import { InjectRepository } from "@nestjs/typeorm"; import { AttendanceEntity } from "./entities/attendance.entity"; import { Repository } from "typeorm"; -import { BadRequestException, Injectable } from "@nestjs/common"; +import { BadRequestException, HttpException, HttpStatus, Injectable } from "@nestjs/common"; import { ErrorResponse } from "src/error-response"; import { AttendanceSearchDto } from "./dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; import { AttendanceDto } from './dto/attendance.dto'; +import { AttendanceDateDto } from './dto/attendance-date.dto'; +import { Between } from 'typeorm'; @@ -95,6 +98,8 @@ export class AttendanceService { request: any, attendanceDto: AttendanceDto ) { + + try { const decoded: any = jwt_decode(request.headers.authorization); @@ -104,10 +109,13 @@ export class AttendanceService { attendanceDto.updatedBy = userId; const attendanceToSearch = new AttendanceSearchDto({}); + + attendanceToSearch.filters = { attendanceDate: attendanceDto.attendanceDate, userId: attendanceDto.userId, }; + console.log("attendanceToSearch.filters",attendanceToSearch.filters) const attendanceFound: any = await this.searchAttendance( @@ -150,11 +158,10 @@ export class AttendanceService { attendanceDto: AttendanceDto ) { try { - const attendanceRecord = await this.attendanceRepository.findOne({ where: { attendanceId }, }); - + if (!attendanceRecord) { return new ErrorResponse({ errorCode: "404", @@ -189,6 +196,8 @@ export class AttendanceService { public async createAttendance(request: any, attendanceDto: AttendanceDto) { + + console.log("created") try { const attendance = this.attendanceRepository.create(attendanceDto); @@ -215,6 +224,110 @@ export class AttendanceService { } } } + + public async attendanceByDate( + tenantId: string, + request: any, + attendanceSearchDto: AttendanceDateDto + ) { + try { + let offset = 0; + if (attendanceSearchDto.page > 1) { + offset = parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); + } + + const fromDate = new Date(attendanceSearchDto.fromDate); + const toDate = new Date(attendanceSearchDto.toDate); + + const whereClause: any = { + tenantId: tenantId ? tenantId : '', + attendanceDate: Between(fromDate, toDate), + }; + + // Add additional filters if present + if (attendanceSearchDto.filters) { + Object.keys(attendanceSearchDto.filters).forEach((key) => { + whereClause[key] = attendanceSearchDto.filters[key]; + }); + } + + const [results, totalCount] = await this.attendanceRepository.findAndCount({ + where: whereClause, + take: parseInt(attendanceSearchDto.limit), + skip: offset, + }); + + const mappedResponse = await this.mappedResponse(results); + + return new SuccessResponse({ + statusCode: 200, + message: "Ok", + totalCount: totalCount, + data: mappedResponse, + }); + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "500", + errorMessage: "Internal Server Error", + }); + } + } + + public async multipleAttendance( + tenantId: string, + request: any, + attendanceData: [AttendanceDto] + ) { + const responses = []; + const errors = []; + try { + let count = 1; + + for (const attendance of attendanceData) { + console.log("new Date(attendance.attendanceDate)",attendance.attendanceDate) + if(attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance){ + + attendance.tenantId = tenantId; + const attendanceRes: any = await this.checkAndAddAttendance( + request, + attendance + ); + if (attendanceRes?.statusCode === 200) { + responses.push(attendanceRes.data); + } else { + errors.push({ + userId: attendance.userId, + attendanceRes, + }); + } + count++; + } + else{ + errors.push({ + message:`userId should not be empty null or undefined for record or attendance date should not be of future for${count}` + + }); + count++; + } + + } + } catch (e) { + console.error(e); + return e; + } + + + return { + statusCode: 200, + totalCount: attendanceData.length, + successCount: responses.length, + errorCount:errors.length, + responses, + errors, + }; + } + } diff --git a/src/attendance/dto/attendance-date.dto.ts b/src/attendance/dto/attendance-date.dto.ts index 07edc8af..8f2ebdb1 100644 --- a/src/attendance/dto/attendance-date.dto.ts +++ b/src/attendance/dto/attendance-date.dto.ts @@ -2,13 +2,13 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class AttendanceDateDto { @ApiProperty({ - type: String, + type: Date, description: "From Date", }) fromDate: string; @ApiProperty({ - type: String, + type: Date, description: "To Date", }) toDate: string; diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 02889f0d..6e4b174e 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -1,14 +1,19 @@ import { ManyToOne, JoinColumn } from 'typeorm'; -import { IsDate, IsDateString, IsEnum, IsUUID, Matches } from 'class-validator'; -import { Exclude, Expose } from "class-transformer"; +import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; +import { Exclude, Expose, Transform } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsObject } from 'class-validator'; import { User } from 'src/user/entities/user-create-entity'; +import { format, isAfter } from 'date-fns'; // Import isAfter function from date-fns +import { HttpException, HttpStatus } from '@nestjs/common'; + enum Attendance{ present="present", - absent="absent" + absent="absent", + halfDay="halfday" } + export class AttendanceDto { @Expose() attendanceId: string; @@ -21,6 +26,7 @@ export class AttendanceDto { description: "The userid of the attendance", default: "", }) + @IsDefined() @IsNotEmpty() @IsUUID() @Expose() @@ -38,6 +44,13 @@ export class AttendanceDto { @IsNotEmpty() @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @Expose() + @Transform(({ value }) => new Date(value)) // Transform the incoming value to a Date object + @Transform(({ value }) => { // Custom transform function to validate date + if (isAfter(value, new Date())) { + throw new HttpException('Attendance date cannot be of future', HttpStatus.BAD_REQUEST); + } + return value; + }) attendanceDate: Date; @ApiProperty({ From 4f252b7852169d37cebf6a5fe308e46aea0cc19a Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 21 Mar 2024 14:36:23 +0530 Subject: [PATCH 079/408] Fix[error handling for API] --- src/attendance/attendance.service.ts | 11 ++++++++++- src/attendance/dto/attendance.dto.ts | 7 ------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 1f8776d8..90895f8f 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -101,6 +101,7 @@ export class AttendanceService { try { + if( !isAfter(new Date(attendanceDto.attendanceDate), new Date()) && attendanceDto.attendanceDate){ const decoded: any = jwt_decode(request.headers.authorization); const userId = @@ -146,6 +147,13 @@ export class AttendanceService { return await this.createAttendance(request, attendanceDto); } + } + else{ + return new ErrorResponse({ + errorCode: '500', + errorMessage: "Date cannot be from future", + }); + } } catch (e) { return e; } @@ -303,9 +311,10 @@ export class AttendanceService { } count++; } + else{ errors.push({ - message:`userId should not be empty null or undefined for record or attendance date should not be of future for${count}` + message:`userId should not be empty null or undefined for record or attendance date should not be of future for ${count} or attendance should be valid enum value[present,absent,halfday]` }); count++; diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 6e4b174e..65f8377e 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -44,13 +44,6 @@ export class AttendanceDto { @IsNotEmpty() @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @Expose() - @Transform(({ value }) => new Date(value)) // Transform the incoming value to a Date object - @Transform(({ value }) => { // Custom transform function to validate date - if (isAfter(value, new Date())) { - throw new HttpException('Attendance date cannot be of future', HttpStatus.BAD_REQUEST); - } - return value; - }) attendanceDate: Date; @ApiProperty({ From 1158078339b3a1e6655a48f18ccbdf7b8fdaa101 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 21 Mar 2024 14:52:20 +0530 Subject: [PATCH 080/408] Fix[removed commented code] --- src/attendance/attendance.controller.ts | 34 ------------------------- 1 file changed, 34 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index b2903e42..a0f674dc 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -106,40 +106,6 @@ export class AttendanceController { .checkAndAddAttendance(request, attendanceDto); } - // @Post() - // @ApiConsumes("multipart/form-data") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Attendance has been created successfully.", - // }) - // @UseInterceptors( - // FileInterceptor("image", { - // storage: diskStorage({ - // destination: process.env.IMAGEPATH, - // filename: editFileName, - // }), - // fileFilter: imageFileFilter, - // }) - // ) - // @ApiBody({ type: AttendanceDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - // @ApiHeader({ - // name: "tenantid", - // }) - // public async createAttendace( - // @Headers() headers, - // @Req() request: Request, - // @Body() attendanceDto: AttendanceDto, - // @UploadedFile() image - // ) { - // attendanceDto.tenantId = headers["tenantid"]; - // attendanceDto.image = image?.filename; - // return this.attendaceAdapter - // .buildAttenceAdapter() - // .checkAndAddAttendance(request, attendanceDto); - // } - @Put("/:id") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") From 23cddb74ca11981092787228e00cd869eaa25381 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 21 Mar 2024 14:59:26 +0530 Subject: [PATCH 081/408] Fix[changed name of the method] --- src/attendance/attendance.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 90895f8f..5e46835b 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -94,7 +94,7 @@ export class AttendanceService { return attendanceResponse; } - public async checkAndAddAttendance( + public async updateAttendanceRecord( request: any, attendanceDto: AttendanceDto ) { @@ -297,7 +297,7 @@ export class AttendanceService { if(attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance){ attendance.tenantId = tenantId; - const attendanceRes: any = await this.checkAndAddAttendance( + const attendanceRes: any = await this.updateAttendanceRecord( request, attendance ); From d7582a9a376e9a0426d77a719dffe1d9e9962e54 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 21 Mar 2024 16:44:33 +0530 Subject: [PATCH 082/408] Fix[resolved comments] --- src/attendance/attendance.controller.ts | 9 +- src/attendance/attendance.service.ts | 322 +++++++++++++----------- 2 files changed, 177 insertions(+), 154 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index a0f674dc..0c6672b5 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -46,7 +46,7 @@ export class AttendanceController { private service: AttendanceHasuraService, private attendaceAdapter: AttendaceAdapter, private attendaceService: AttendanceService - ) {} + ) { } @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) @@ -72,7 +72,7 @@ export class AttendanceController { @Post() - + @UsePipes(new ValidationPipe()) @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @@ -102,8 +102,7 @@ export class AttendanceController { ) { attendanceDto.tenantId = headers["tenantid"]; attendanceDto.image = image?.filename; - return this.attendaceService - .checkAndAddAttendance(request, attendanceDto); + return this.attendaceService.updateAttendanceRecord(request, attendanceDto); } @Put("/:id") @@ -217,5 +216,5 @@ export class AttendanceController { return await this.service.userSegment(groupId, attendance, date, request); } */ - + } diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 5e46835b..eec3e88b 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -21,6 +21,14 @@ export class AttendanceService { @InjectRepository(AttendanceEntity) private readonly attendanceRepository: Repository,) { } + + + /* + Method to search attendance for all or for the key value pair provided in filter object + @body an object of details consisting of attendance details of user (attendance dto) + @return Attendance records from attendance table for provided filters + */ + async searchAttendance(tenantId: string, request: any, attendanceSearchDto: AttendanceSearchDto) { try { @@ -42,8 +50,6 @@ export class AttendanceService { else { whereClause['tenantId'] = tenantId; } - - const [results, totalCount] = await this.attendanceRepository.findAndCount({ where: whereClause, take: parseInt(limit), @@ -94,72 +100,80 @@ export class AttendanceService { return attendanceResponse; } + /* + Method to create,update or add attendance for valid user in attendance table + @body an object of details consisting of attendance details of user (attendance dto) + @return updated details of attendance record + */ + public async updateAttendanceRecord( request: any, attendanceDto: AttendanceDto ) { - + try { - if( !isAfter(new Date(attendanceDto.attendanceDate), new Date()) && attendanceDto.attendanceDate){ - const decoded: any = jwt_decode(request.headers.authorization); + if (!isAfter(new Date(attendanceDto.attendanceDate), new Date()) && attendanceDto.attendanceDate) { + const decoded: any = jwt_decode(request?.headers?.authorization); - const userId = - decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - attendanceDto.createdBy = userId; - attendanceDto.updatedBy = userId; - const attendanceToSearch = new AttendanceSearchDto({}); + const userId = + decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + attendanceDto.createdBy = userId; + attendanceDto.updatedBy = userId; + const attendanceToSearch = new AttendanceSearchDto({}); - attendanceToSearch.filters = { - attendanceDate: attendanceDto.attendanceDate, - userId: attendanceDto.userId, - }; - console.log("attendanceToSearch.filters",attendanceToSearch.filters) + attendanceToSearch.filters = { + attendanceDate: attendanceDto.attendanceDate, + userId: attendanceDto.userId, + }; - const attendanceFound: any = await this.searchAttendance( - attendanceDto.tenantId, - request, - attendanceToSearch - ); + const attendanceFound: any = await this.searchAttendance( + attendanceDto.tenantId, + request, + attendanceToSearch + ); - if (attendanceFound?.errorCode) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: attendanceFound?.errorMessage, - }); - } + if (attendanceFound?.errorCode) { + return new ErrorResponse({ + errorCode: "500", + errorMessage: attendanceFound?.errorMessage, + }); + } - if ( - attendanceFound.data.length > 0 && - attendanceFound.statusCode === 200 - ) { + if ( + attendanceFound.data.length > 0 && + attendanceFound.statusCode === 200 + ) { - return await this.updateAttendance( - attendanceFound.data[0].attendanceId, - request, - attendanceDto - ); - } else { + return await this.updateAttendance( + attendanceFound.data[0].attendanceId, + request, + attendanceDto + ); + } else { - return await this.createAttendance(request, attendanceDto); + return await this.createAttendance(request, attendanceDto); + } + } + else { + return new ErrorResponse({ + errorCode: '500', + errorMessage: "Date cannot be from future", + }); } - } - else{ - return new ErrorResponse({ - errorCode: '500', - errorMessage: "Date cannot be from future", - }); - } } catch (e) { return e; } } - + /*Method to update attendance for userId + @body an object of details consisting of attendance details of user (attendance dto),attendanceId + @return updated attendance record based on attendanceId + */ public async updateAttendance( attendanceId: string, request: any, @@ -169,7 +183,7 @@ export class AttendanceService { const attendanceRecord = await this.attendanceRepository.findOne({ where: { attendanceId }, }); - + if (!attendanceRecord) { return new ErrorResponse({ errorCode: "404", @@ -202,10 +216,13 @@ export class AttendanceService { } } - + /*method to add attendance of new user in attendance + @body object containing details related to attendance details (AttendanceDto) + @return attendance record for newly added user in Attendance table + */ public async createAttendance(request: any, attendanceDto: AttendanceDto) { - console.log("created") + console.log("created") try { const attendance = this.attendanceRepository.create(attendanceDto); @@ -233,110 +250,117 @@ export class AttendanceService { } } - public async attendanceByDate( - tenantId: string, - request: any, - attendanceSearchDto: AttendanceDateDto - ) { - try { - let offset = 0; - if (attendanceSearchDto.page > 1) { - offset = parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); - } - - const fromDate = new Date(attendanceSearchDto.fromDate); - const toDate = new Date(attendanceSearchDto.toDate); - - const whereClause: any = { - tenantId: tenantId ? tenantId : '', - attendanceDate: Between(fromDate, toDate), - }; - - // Add additional filters if present - if (attendanceSearchDto.filters) { - Object.keys(attendanceSearchDto.filters).forEach((key) => { - whereClause[key] = attendanceSearchDto.filters[key]; - }); - } - - const [results, totalCount] = await this.attendanceRepository.findAndCount({ - where: whereClause, - take: parseInt(attendanceSearchDto.limit), - skip: offset, - }); - - const mappedResponse = await this.mappedResponse(results); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok", - totalCount: totalCount, - data: mappedResponse, - }); - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "500", - errorMessage: "Internal Server Error", - }); - } - } - - public async multipleAttendance( - tenantId: string, - request: any, - attendanceData: [AttendanceDto] - ) { - const responses = []; - const errors = []; - try { - let count = 1; - - for (const attendance of attendanceData) { - console.log("new Date(attendance.attendanceDate)",attendance.attendanceDate) - if(attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance){ - - attendance.tenantId = tenantId; - const attendanceRes: any = await this.updateAttendanceRecord( - request, - attendance - ); - if (attendanceRes?.statusCode === 200) { - responses.push(attendanceRes.data); - } else { - errors.push({ - userId: attendance.userId, - attendanceRes, - }); - } - count++; + /*Method to search attendance fromDate to toDate + @body object containing attendance date details for user (AttendanceDateDto) + @return attendance records from fromDate to toDate */ + + public async attendanceByDate( + tenantId: string, + request: any, + attendanceSearchDto: AttendanceDateDto + ) { + try { + let offset = 0; + if (attendanceSearchDto.page > 1) { + offset = parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); + } + + const fromDate = new Date(attendanceSearchDto.fromDate); + const toDate = new Date(attendanceSearchDto.toDate); + + const whereClause: any = { + tenantId: tenantId ? tenantId : '', + attendanceDate: Between(fromDate, toDate), + }; + + // Add additional filters if present + if (attendanceSearchDto.filters) { + Object.keys(attendanceSearchDto.filters).forEach((key) => { + whereClause[key] = attendanceSearchDto.filters[key]; + }); + } + + const [results, totalCount] = await this.attendanceRepository.findAndCount({ + where: whereClause, + take: parseInt(attendanceSearchDto.limit), + skip: offset, + }); + + const mappedResponse = await this.mappedResponse(results); + + return new SuccessResponse({ + statusCode: 200, + message: "Ok", + totalCount: totalCount, + data: mappedResponse, + }); + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "500", + errorMessage: "Internal Server Error", + }); } - - else{ - errors.push({ - message:`userId should not be empty null or undefined for record or attendance date should not be of future for ${count} or attendance should be valid enum value[present,absent,halfday]` - - }); - count++; + } + + /*Method to add multiple attendance records in Attendance table + @body Array of objects containing attendance details of user (AttendanceDto) + */ + + public async multipleAttendance( + tenantId: string, + request: any, + attendanceData: [AttendanceDto] + ) { + const responses = []; + const errors = []; + try { + let count = 1; + + for (const attendance of attendanceData) { + if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance) { + + attendance.tenantId = tenantId; + const attendanceRes: any = await this.updateAttendanceRecord( + request, + attendance + ); + if (attendanceRes?.statusCode === 200) { + responses.push(attendanceRes.data); + } else { + errors.push({ + userId: attendance.userId, + attendanceRes, + }); + } + count++; + } + + else { + errors.push({ + message: `userId should not be empty null or undefined for record or attendance date should not be of future for ${count} or attendance should be valid enum value[present,absent,halfday]` + + }); + count++; + } + + } + } catch (e) { + console.error(e); + return e; } - - } - } catch (e) { - console.error(e); - return e; + + + return { + statusCode: 200, + totalCount: attendanceData.length, + successCount: responses.length, + errorCount: errors.length, + responses, + errors, + }; } - - - return { - statusCode: 200, - totalCount: attendanceData.length, - successCount: responses.length, - errorCount:errors.length, - responses, - errors, - }; - } - + } From 6341ef2ffafb632e0dfb30ae9dc368581bf96818 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 21 Mar 2024 17:03:49 +0530 Subject: [PATCH 083/408] Fix[related to search attendance by toDate and fromDate] --- src/attendance/attendance.service.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index eec3e88b..08d6d194 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -260,15 +260,22 @@ export class AttendanceService { attendanceSearchDto: AttendanceDateDto ) { try { + + + let { limit, page } = attendanceSearchDto; + if (!limit) { + limit = '0'; + } + let offset = 0; - if (attendanceSearchDto.page > 1) { - offset = parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); + if (page > 1) { + offset = parseInt(limit) * (page - 1); } const fromDate = new Date(attendanceSearchDto.fromDate); const toDate = new Date(attendanceSearchDto.toDate); - const whereClause: any = { + let whereClause: any = { tenantId: tenantId ? tenantId : '', attendanceDate: Between(fromDate, toDate), }; @@ -282,7 +289,7 @@ export class AttendanceService { const [results, totalCount] = await this.attendanceRepository.findAndCount({ where: whereClause, - take: parseInt(attendanceSearchDto.limit), + take: parseInt(limit), skip: offset, }); @@ -298,7 +305,7 @@ export class AttendanceService { console.error(e); return new ErrorResponse({ errorCode: "500", - errorMessage: "Internal Server Error", + errorMessage: e, }); } } From 933b168cf013de7381b839485b74827895c46de9 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 22 Mar 2024 15:59:54 +0530 Subject: [PATCH 084/408] Create new field --- src/cohort/cohort.controller.ts | 3 +- src/cohort/cohort.service.ts | 6 +- src/cohort/entities/cohort.service.ts | 64 --- src/fields/dto/fields.dto.ts | 76 +-- src/fields/entities/fields.entity.ts | 98 ++++ src/fields/fields.controller.ts | 130 +---- src/fields/fields.module.ts | 6 +- src/fields/fields.service.ts | 788 ++++++++++++++++++++++++++ 8 files changed, 948 insertions(+), 223 deletions(-) delete mode 100644 src/cohort/entities/cohort.service.ts create mode 100644 src/fields/entities/fields.entity.ts create mode 100644 src/fields/fields.service.ts diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index ca666cef..94bcea26 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -104,7 +104,8 @@ export class CohortController { let tenantid = headers["tenantid"]; return this.cohortService.getCohort(tenantid, cohortId, request, response); } - search; + + // search @Post("/search") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort list." }) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 036b407e..56e92a1f 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -15,7 +15,7 @@ import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { FieldsService } from "src/adapters/hasura/services/fields.service"; -import { FieldValues } from "src/fields/entities/field-values.entity"; +// import { FieldValues } from "src/fields/entities/field-values.entity"; import { response } from "express"; import APIResponse from "src/utils/response"; @@ -25,9 +25,9 @@ export class CohortService { constructor( @InjectRepository(Cohort) - @InjectRepository(FieldValues) + // @InjectRepository(FieldValues) private cohortRepository: Repository, - private readonly fieldsService: FieldsService + // private readonly fieldsService: FieldsService ) {} public async getCohort( diff --git a/src/cohort/entities/cohort.service.ts b/src/cohort/entities/cohort.service.ts deleted file mode 100644 index 5b1ecf83..00000000 --- a/src/cohort/entities/cohort.service.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { CohortInterface } from "../../cohort/interfaces/cohort.interface"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { ErrorResponse } from "src/error-response"; -const resolvePath = require("object-resolve-path"); -import jwt_decode from "jwt-decode"; -import { CohortDto } from "src/cohort/dto/cohort.dto"; -import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; -// import { IServicelocatorcohort } from "../cohortservicelocator"; -import { UserDto } from "src/user/dto/user.dto"; -import { StudentDto } from "src/student/dto/student.dto"; -// import { FieldsService } from "./services/fields.service"; -import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; -import { FieldValuesDto } from "src/fields/dto/field-values.dto"; -import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; -import { Cohort } from "src/cohort/entities/cohort.entity"; -import { InjectRepository } from "@nestjs/typeorm"; - -@Injectable() -export class CohortService { - private cohort: CohortInterface; - - constructor( - @InjectRepository(Cohort) - private cohortRepository: Repository - ) {} - - public async getCohort( - tenantId: string, - cohortId: string, - request: any, - res: any - ) { - try { - console.log("Tenant id", tenantId); - console.log("cohortId", cohortId); - const cohort = await this.cohortRepository.findOne({ - where: { tenantId: tenantId, cohortId: cohortId }, - }); - if (!cohort) { - console.log("if ! cohort"); - - return res.status(404).send({ - statusCode: 404, - message: "Cohort not found.", - }); - } - console.log("cohort", cohort); - return res.status(200).send({ - statusCode: 200, - message: "Ok.", - data: cohort, - }); - } catch (error) { - console.log("heyyy"); - console.error("Error fetching cohort:", error); - return res.status(500).send({ - statusCode: 500, - message: "Internal server error.", - }); - } - } -} diff --git a/src/fields/dto/fields.dto.ts b/src/fields/dto/fields.dto.ts index 083690f1..d36c0fc6 100644 --- a/src/fields/dto/fields.dto.ts +++ b/src/fields/dto/fields.dto.ts @@ -11,13 +11,7 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class FieldsDto { //generated fields @Expose() - tenantId: string; - @Expose() fieldId: string; - @Expose() - createdAt: string; - @Expose() - updatedAt: string; //assetId @ApiProperty({ @@ -37,32 +31,6 @@ export class FieldsDto { @Expose() context: string; - //contextId - @ApiProperty({ - type: String, - description: "The contextId of the fields", - default: "", - }) - @Expose() - contextId: string; - - //contexType - @ApiProperty({ - type: String, - description: "The contexType of the fields", - default: "", - }) - @Expose() - contexType: string; - - //render - @ApiProperty({ - type: Object, - description: "The form render json of the fields", - }) - @Expose() - render: any; - //groupId @ApiProperty({ type: String, @@ -180,6 +148,15 @@ export class FieldsDto { @Expose() onlyUseInSubform: Boolean; + @Expose() + tenantId: string; + + @Expose() + createdAt: string; + + @Expose() + updatedAt: string; + //createdBy @ApiProperty({ type: String, @@ -198,6 +175,41 @@ export class FieldsDto { @Expose() updatedBy: string; + //contextId + @ApiProperty({ + type: String, + description: "The contextId of the fields", + default: "", + }) + @Expose() + contextId: string; + + //render + @ApiProperty({ + type: Object, + description: "The form render json of the fields", + }) + @Expose() + render: any; + + //contexType + @ApiProperty({ + type: String, + description: "The contexType of the fields", + default: "", + }) + @Expose() + contexType: string; + + //contexType + @ApiProperty({ + type: Object, + description: "The fieldParams of the fields", + default: "", + }) + @Expose() + fieldParams: object; + constructor(obj: any) { Object.assign(this, obj); } diff --git a/src/fields/entities/fields.entity.ts b/src/fields/entities/fields.entity.ts new file mode 100644 index 00000000..13a2799f --- /dev/null +++ b/src/fields/entities/fields.entity.ts @@ -0,0 +1,98 @@ +import { + Entity, + Column, + PrimaryColumn, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm'; + +@Entity({ name: 'Fields' }) +export class Fields { + + @PrimaryColumn({ type: "uuid" }) + fieldId: string; + + @Column({ type: 'varchar' }) + assetId: string; + + @Column({ type: 'varchar' }) + context: string; + + @Column({ type: 'varchar' }) + groupId: string; + + @Column({ type: 'varchar' }) + name: string; + + @Column({ type: 'varchar' }) + label: string; + + @Column({ type: 'varchar' }) + defaultValue: string; + + @Column({ type: 'varchar' }) + type: string; + + @Column({ type: 'text' }) + note: string; + + @Column({ type: 'text' }) + description: string; + + @Column({ type: 'text' }) + state: string; + + @Column({ type: 'boolean' }) + required: boolean; + + @Column({ type: 'int' }) + ordering: number; + + @Column({ type: 'text' }) + metadata: string; + + @Column({ type: 'varchar' }) + access: string; + + @Column({ type: 'boolean' }) + onlyUseInSubform: boolean; + + @Column({ type: 'uuid' }) + tenantId: string; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdBy: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedBy: Date; + + @Column({ type: 'uuid' }) + contextId: string; + + @Column({ type: 'varchar' }) + render: string; + + @Column({ type: 'varchar' }) + contextType: string; + + @Column({ type: 'jsonb' }) + fieldParams: object; +} diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 9e57c896..596360e6 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -33,11 +33,14 @@ import { diskStorage } from "multer"; import { FieldsAdapter } from "./fieldsadapter"; import { FieldValuesDto } from "./dto/field-values.dto"; import { FieldValuesSearchDto } from "./dto/field-values-search.dto"; +import { FieldsService } from "./fields.service"; @ApiTags("Fields") @Controller("fields") export class FieldsController { - constructor(private fieldsAdapter: FieldsAdapter) {} + constructor(private fieldsAdapter: FieldsAdapter, + private readonly fieldsService: FieldsService + ) {} //fields //create fields @@ -61,34 +64,11 @@ export class FieldsController { }; Object.assign(fieldsDto, payload); - return this.fieldsAdapter - .buildFieldsAdapter() - .createFields(request, fieldsDto); - } - - //get fields - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Fields detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async getFields( - @Headers() headers, - @Param("id") fieldsId: string, - @Req() request: Request - ) { - let tenantid = headers["tenantid"]; - return this.fieldsAdapter - .buildFieldsAdapter() - .getFields(tenantid, fieldsId, request); + return this.fieldsService.createFields(request, fieldsDto); + } + //search @Post("/search") @ApiBasicAuth("access-token") @@ -113,99 +93,5 @@ export class FieldsController { .searchFields(tenantid, request, fieldsSearchDto); } - //update - @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Fields has been updated successfully." }) - @ApiBody({ type: FieldsDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async updateFields( - @Param("id") fieldsId: string, - @Req() request: Request, - @Body() fieldsDto: FieldsDto - ) { - return this.fieldsAdapter - .buildFieldsAdapter() - .updateFields(fieldsId, request, fieldsDto); - } - - //field values - //create fields values - @Post("/values") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Fields Values has been created successfully.", - }) - @ApiBody({ type: FieldValuesDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createFieldValues( - @Req() request: Request, - @Body() fieldValuesDto: FieldValuesDto - ) { - return this.fieldsAdapter - .buildFieldsAdapter() - .createFieldValues(request, fieldValuesDto); - } - - //get fields values - @Get("/values/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Fields Values detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getFieldValues( - @Param("id") id: string, - @Req() request: Request - ) { - return this.fieldsAdapter.buildFieldsAdapter().getFieldValues(id, request); - } - - //search fields values - @Post("/values/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Fields Values list." }) - @ApiBody({ type: FieldValuesSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchFieldValues( - @Req() request: Request, - @Body() fieldValuesSearchDto: FieldValuesSearchDto - ) { - return this.fieldsAdapter - .buildFieldsAdapter() - .searchFieldValues(request, fieldValuesSearchDto); - } - - //update - @Put("/values/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Fields Values has been updated successfully.", - }) - @ApiBody({ type: FieldValuesDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async updateFieldValues( - @Param("id") id: string, - @Req() request: Request, - @Body() fieldValuesDto: FieldValuesDto - ) { - return this.fieldsAdapter - .buildFieldsAdapter() - .updateFieldValues(id, request, fieldValuesDto); - } + } diff --git a/src/fields/fields.module.ts b/src/fields/fields.module.ts index a46da0e6..533b7069 100644 --- a/src/fields/fields.module.ts +++ b/src/fields/fields.module.ts @@ -3,9 +3,13 @@ import { FieldsController } from "./fields.controller"; import { HttpModule } from "@nestjs/axios"; import { FieldsAdapter } from "./fieldsadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { Fields } from "./entities/fields.entity"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { FieldsService } from "./fields.service"; const ttl = process.env.TTL as never; @Module({ imports: [ + TypeOrmModule.forFeature([Fields]), HttpModule, HasuraModule, CacheModule.register({ @@ -13,6 +17,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [FieldsController], - providers: [FieldsAdapter], + providers: [FieldsAdapter, FieldsService], }) export class FieldsModule {} diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts new file mode 100644 index 00000000..48588004 --- /dev/null +++ b/src/fields/fields.service.ts @@ -0,0 +1,788 @@ +import { Injectable } from "@nestjs/common"; +import { FieldsDto } from "src/fields/dto/fields.dto"; +import { FieldsSearchDto } from "src/fields/dto/fields-search.dto"; +import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; +import jwt_decode from "jwt-decode"; +import { ErrorResponse } from "src/error-response"; +import { Fields } from "./entities/fields.entity"; +import { InjectRepository } from "@nestjs/typeorm"; +import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; +import { SuccessResponse } from "src/success-response"; + +@Injectable() +export class FieldsService { + constructor( + @InjectRepository(Fields) + // @InjectRepository(FieldValues) + private fieldsRepository: Repository, + ) { } + + //fields + async createFields(request: any, fieldsDto: FieldsDto) { + try { + + const fieldsData: any = {}; // Define an empty object to store field data + + Object.keys(fieldsDto).forEach((e) => { + if (fieldsDto[e] && fieldsDto[e] !== "") { + if (e === "render") { + fieldsData[e] = fieldsDto[e]; + } else if (Array.isArray(fieldsDto[e])) { + fieldsData[e] = JSON.stringify(fieldsDto[e]); + } else { + fieldsData[e] = fieldsDto[e]; + } + } + }); + + let result = await this.fieldsRepository.save(fieldsData); + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + public async getFields(tenantId: string, fieldsId: any) { + var axios = require("axios"); + + var data = { + query: `query GetFields($fieldsId:uuid!, $tenantId:uuid!) { + Fields( + where:{ + tenantId:{ + _eq:$tenantId + } + fieldId:{ + _eq:$fieldsId + }, + } + ){ + tenantId + fieldId + assetId + context + contextId + render + groupId + name + label + defaultValue + type + note + description + state + required + ordering + metadata + access + onlyUseInSubform + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + fieldsId: fieldsId, + tenantId: tenantId, + }, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } + + public async getFieldsContext( + request: any, + tenantId: string, + context: string, + contextId: string + ) { + try { + var axios = require("axios"); + + var data = { + query: `query GetFields($context:String!, $contextId:uuid!, $tenantId:uuid!) { + Fields( + where:{ + _or:[ + { + tenantId:{ + _eq:$tenantId + } + context:{ + _eq:$context + } + contextId:{ + _is_null:true + } + }, + { + tenantId:{ + _eq:$tenantId + } + context:{ + _eq:$context + } + contextId:{ + _eq:$contextId + } + } + ] + } + ){ + tenantId + fieldId + assetId + context + contextId + render + groupId + name + label + defaultValue + type + note + description + state + required + ordering + metadata + access + onlyUseInSubform + createdAt + updatedAt + createdBy + updatedBy + fieldValues: FieldValues( + where:{ + itemId:{ + _eq:$contextId + }, + } + ){ + value + fieldValuesId + itemId + fieldId + createdAt + updatedAt + createdBy + updatedBy + } + } + }`, + variables: { + context: context, + contextId: contextId, + tenantId: tenantId, + }, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + async searchFields(request: any, tenantId: string, fieldsSearchDto: FieldsSearchDto) { + try { + var axios = require("axios"); + + let offset = 0; + if (fieldsSearchDto.page > 1) { + offset = parseInt(fieldsSearchDto.limit) * (fieldsSearchDto.page - 1); + } + + let temp_filters = fieldsSearchDto.filters; + //add tenantid + let filters = new Object(temp_filters); + filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + + Object.keys(fieldsSearchDto.filters).forEach((item) => { + Object.keys(fieldsSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); + }); + var data = { + query: `query SearchFields($filters:Fields_bool_exp,$limit:Int, $offset:Int) { + Fields(where:$filters, limit: $limit, offset: $offset,) { + tenantId + fieldId + assetId + context + contextId + render + groupId + name + label + defaultValue + type + note + description + state + required + ordering + metadata + access + onlyUseInSubform + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(fieldsSearchDto.limit), + offset: offset, + filters: fieldsSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + async updateFields(fieldsId: string, fieldsDto: FieldsDto) { + var axios = require("axios"); + + //add render json object + fieldsDto = await this.addRender(fieldsDto); + + let query = ""; + Object.keys(fieldsDto).forEach((e) => { + if (fieldsDto[e] && fieldsDto[e] != "") { + if (e === "render") { + query += `${e}: ${fieldsDto[e]}, `; + } else if (Array.isArray(fieldsDto[e])) { + query += `${e}: "${JSON.stringify(fieldsDto[e])}", `; + } else { + query += `${e}: "${fieldsDto[e]}", `; + } + } + }); + + var data = { + query: ` + mutation UpdateFields($fieldsId:uuid!) { + update_Fields_by_pk( + pk_columns: { + fieldId: $fieldsId + }, + _set: { + ${query} + } + ) { + fieldId + } + } + `, + variables: { + fieldsId: fieldsId, + }, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + + return response; + } + + //required functions + public async addRender(fieldsDto: FieldsDto) { + let fieldsDtoTemp = fieldsDto; + if (fieldsDtoTemp?.render) { + let renderObj = await this.createFieldSchema(fieldsDtoTemp?.render); + fieldsDtoTemp.render = JSON.stringify(JSON.stringify(renderObj)); + } + fieldsDto = fieldsDtoTemp; + return fieldsDto; + } + + public async setTypeProperties(schema, payload) { + switch (payload.type) { + case "string": + case "text": + schema.coreSchema.type = "string"; + break; + case "integer": + case "number": + schema.coreSchema.type = "integer"; + break; + case "password": + schema.coreSchema.type = "string"; + schema.uiSchema["ui:widget"] = "password"; + break; + case "email": + schema.coreSchema.type = "string"; + schema.uiSchema["ui:widget"] = "email"; + break; + case "textarea": + schema.coreSchema.type = "string"; + schema.uiSchema["ui:widget"] = "textarea"; + break; + case "radio": + schema.coreSchema.type = "boolean"; + schema.uiSchema["ui:widget"] = "radio"; + break; + case "checkbox": + schema.coreSchema.type = "array"; + if (payload.hasOwnProperty("items")) { + schema.coreSchema.items = payload.items; + schema.coreSchema.uniqueItems = payload.uniqueItems; + schema.uiSchema["ui:widget"] = "checkboxes"; + } + break; + case "select": + schema.coreSchema.type = payload.fieldType; + if ( + payload.hasOwnProperty("enum") && + Array.isArray(payload.enum) && + payload.hasOwnProperty("labels") && + Array.isArray(payload.labels) && + payload.enum.length === payload.labels.length + ) { + schema.coreSchema.enum = payload.enum; + schema.coreSchema.enumNames = payload.labels; + } + if (payload.hasOwnProperty("label")) { + schema.coreSchema.title = payload.label; + } + break; + } + + return schema; + } + + public async createFieldSchema(payload) { + let fieldSchema = { + required: false, + coreSchema: {}, + uiSchema: {}, + }; + fieldSchema = await this.setTypeProperties(fieldSchema, payload); + if (payload.label) { + fieldSchema.coreSchema["title"] = payload.label; + } + + if (payload.pattern) { + fieldSchema.coreSchema["pattern"] = payload.pattern; + } + + if (payload.hasOwnProperty("minLength")) { + fieldSchema.coreSchema["minLength"] = payload.minLength; + } + + if (payload.hasOwnProperty("maxLength")) { + fieldSchema.coreSchema["maxLength"] = payload.maxLength; + } + + if (payload.defaultValue) { + fieldSchema.coreSchema["default"] = payload.defaultValue; + } + if (payload.placeholder) { + fieldSchema.uiSchema["ui:placeholder"] = payload.placeholder; + } + if (payload.hasOwnProperty("required")) { + fieldSchema.required = true; + } + + if (payload.hasOwnProperty("oneOf")) { + fieldSchema.coreSchema["oneOf"] = payload.oneOf; + } + + return { + [payload.name]: fieldSchema, + }; + } + + //field values + async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { + try { + var axios = require("axios"); + + let query = ""; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; + } else { + query += `${e}: "${fieldValuesDto[e]}", `; + } + } + }); + + var data = { + query: `mutation CreateFieldValues { + insert_FieldValues_one(object: {${query}}) { + fieldValuesId + } + } + `, + variables: {}, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + async createFieldValuesBulk(field_values: any) { + var axios = require("axios"); + + var data_field_values = { + query: `mutation insert_multiple_fieldValues($objects: [FieldValues_insert_input!]!) { + insert_FieldValues(objects: $objects) { + returning { + fieldValuesId + } + } + } + `, + variables: { + objects: field_values, + }, + }; + + var config_field_value = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data_field_values, + }; + + const response = await axios(config_field_value); + return response; + } + + public async getFieldValues(id: any) { + var axios = require("axios"); + + var data = { + query: `query GetFieldValues($id:uuid!) { + FieldValues( + where:{ + fieldValuesId:{ + _eq:$id + }, + } + ){ + value + fieldValuesId + itemId + fieldId + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + id: id, + }, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } + + public async getFieldValuesFieldsItemId(field_id: string, item_id: string) { + var axios = require("axios"); + + var data = { + query: `query GetFieldValuesItemId($field_id:uuid!,$item_id:uuid!) { + FieldValues( + where:{ + itemId:{ + _eq:$item_id + }, + fieldId:{ + _eq:$field_id + }, + } + ){ + value + fieldValuesId + itemId + fieldId + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + field_id: field_id, + item_id: item_id, + }, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } + + async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { + try { + var axios = require("axios"); + + let offset = 0; + if (fieldValuesSearchDto.page > 1) { + offset = + parseInt(fieldValuesSearchDto.limit) * (fieldValuesSearchDto.page - 1); + } + + let filters = fieldValuesSearchDto.filters; + + Object.keys(fieldValuesSearchDto.filters).forEach((item) => { + Object.keys(fieldValuesSearchDto.filters[item]).forEach((e) => { + if (!e.startsWith("_")) { + filters[item][`_${e}`] = filters[item][e]; + delete filters[item][e]; + } + }); + }); + var data = { + query: `query SearchFieldValues($filters:FieldValues_bool_exp,$limit:Int, $offset:Int) { + FieldValues(where:$filters, limit: $limit, offset: $offset,) { + value + fieldValuesId + itemId + fieldId + createdAt + updatedAt + createdBy + updatedBy + } + }`, + variables: { + limit: parseInt(fieldValuesSearchDto.limit), + offset: offset, + filters: fieldValuesSearchDto.filters, + }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + async searchFieldValuesFilter(request: any, filter: any) { + try { + let obj_filter = []; + Object.keys(filter).forEach((item) => { + Object.keys(filter[item]).forEach((e) => { + let obj_val = new Object(); + obj_val[e] = filter[item][e]; + obj_filter.push({ + fieldId: { _eq: item }, + value: obj_val, + }); + }); + }); + + let valuefilter = new Object({ _or: obj_filter }); + + var axios = require("axios"); + + var data = { + query: `query SearchFieldValuesFilter($valuefilter:FieldValues_bool_exp) { + FieldValues( + where:$valuefilter + ){ + itemId + } + }`, + variables: { valuefilter: valuefilter }, + }; + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + return response; + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { + var axios = require("axios"); + + let query = ""; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; + } else { + query += `${e}: "${fieldValuesDto[e]}", `; + } + } + }); + + var data = { + query: ` + mutation UpdateFieldValues($id:uuid!) { + update_FieldValues_by_pk( + pk_columns: { + fieldValuesId: $id + }, + _set: { + ${query} + } + ) { + fieldValuesId + } + } + `, + variables: { + id: id, + }, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + + return response; + } +} From ad2b86260fb3eb2584738629c2e3e5b879644ce9 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 22 Mar 2024 17:59:07 +0530 Subject: [PATCH 085/408] add --- src/fields/fields.controller.ts | 13 +- src/fields/fields.service.ts | 738 ++------------------------------ 2 files changed, 25 insertions(+), 726 deletions(-) diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 596360e6..a73618a3 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -45,10 +45,6 @@ export class FieldsController { //fields //create fields @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Fields has been created successfully." }) - @ApiBody({ type: FieldsDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", @@ -71,11 +67,6 @@ export class FieldsController { //search @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Fields list." }) - @ApiBody({ type: FieldsSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) @@ -88,9 +79,7 @@ export class FieldsController { @Body() fieldsSearchDto: FieldsSearchDto ) { let tenantid = headers["tenantid"]; - return this.fieldsAdapter - .buildFieldsAdapter() - .searchFields(tenantid, request, fieldsSearchDto); + return this.fieldsService.searchFields(tenantid, request, fieldsSearchDto); } diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 48588004..39dce7e8 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -38,9 +38,9 @@ export class FieldsService { let result = await this.fieldsRepository.save(fieldsData); return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, + statusCode: 200, + message: "Ok.", + data: result, }); } catch (e) { @@ -52,682 +52,41 @@ export class FieldsService { } } - public async getFields(tenantId: string, fieldsId: any) { - var axios = require("axios"); - - var data = { - query: `query GetFields($fieldsId:uuid!, $tenantId:uuid!) { - Fields( - where:{ - tenantId:{ - _eq:$tenantId - } - fieldId:{ - _eq:$fieldsId - }, - } - ){ - tenantId - fieldId - assetId - context - contextId - render - groupId - name - label - defaultValue - type - note - description - state - required - ordering - metadata - access - onlyUseInSubform - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - fieldsId: fieldsId, - tenantId: tenantId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } - - public async getFieldsContext( - request: any, - tenantId: string, - context: string, - contextId: string - ) { + async searchFields(tenantId: string, request: any, fieldsSearchDto: FieldsSearchDto) { try { - var axios = require("axios"); - - var data = { - query: `query GetFields($context:String!, $contextId:uuid!, $tenantId:uuid!) { - Fields( - where:{ - _or:[ - { - tenantId:{ - _eq:$tenantId - } - context:{ - _eq:$context - } - contextId:{ - _is_null:true - } - }, - { - tenantId:{ - _eq:$tenantId - } - context:{ - _eq:$context - } - contextId:{ - _eq:$contextId - } - } - ] - } - ){ - tenantId - fieldId - assetId - context - contextId - render - groupId - name - label - defaultValue - type - note - description - state - required - ordering - metadata - access - onlyUseInSubform - createdAt - updatedAt - createdBy - updatedBy - fieldValues: FieldValues( - where:{ - itemId:{ - _eq:$contextId - }, - } - ){ - value - fieldValuesId - itemId - fieldId - createdAt - updatedAt - createdBy - updatedBy - } - } - }`, - variables: { - context: context, - contextId: contextId, - tenantId: tenantId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } - } - async searchFields(request: any, tenantId: string, fieldsSearchDto: FieldsSearchDto) { - try { - var axios = require("axios"); + let { limit, page, filters } = fieldsSearchDto; let offset = 0; - if (fieldsSearchDto.page > 1) { - offset = parseInt(fieldsSearchDto.limit) * (fieldsSearchDto.page - 1); + if (page > 1) { + offset = parseInt(limit) * (page - 1); } - let temp_filters = fieldsSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - - Object.keys(fieldsSearchDto.filters).forEach((item) => { - Object.keys(fieldsSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchFields($filters:Fields_bool_exp,$limit:Int, $offset:Int) { - Fields(where:$filters, limit: $limit, offset: $offset,) { - tenantId - fieldId - assetId - context - contextId - render - groupId - name - label - defaultValue - type - note - description - state - required - ordering - metadata - access - onlyUseInSubform - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(fieldsSearchDto.limit), - offset: offset, - filters: fieldsSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } - } - - async updateFields(fieldsId: string, fieldsDto: FieldsDto) { - var axios = require("axios"); - - //add render json object - fieldsDto = await this.addRender(fieldsDto); - - let query = ""; - Object.keys(fieldsDto).forEach((e) => { - if (fieldsDto[e] && fieldsDto[e] != "") { - if (e === "render") { - query += `${e}: ${fieldsDto[e]}, `; - } else if (Array.isArray(fieldsDto[e])) { - query += `${e}: "${JSON.stringify(fieldsDto[e])}", `; - } else { - query += `${e}: "${fieldsDto[e]}", `; - } + if (limit.trim() === '') { + limit = '0'; } - }); - var data = { - query: ` - mutation UpdateFields($fieldsId:uuid!) { - update_Fields_by_pk( - pk_columns: { - fieldId: $fieldsId - }, - _set: { - ${query} + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); } - ) { - fieldId - } - } - `, - variables: { - fieldsId: fieldsId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - return response; - } - - //required functions - public async addRender(fieldsDto: FieldsDto) { - let fieldsDtoTemp = fieldsDto; - if (fieldsDtoTemp?.render) { - let renderObj = await this.createFieldSchema(fieldsDtoTemp?.render); - fieldsDtoTemp.render = JSON.stringify(JSON.stringify(renderObj)); - } - fieldsDto = fieldsDtoTemp; - return fieldsDto; - } - - public async setTypeProperties(schema, payload) { - switch (payload.type) { - case "string": - case "text": - schema.coreSchema.type = "string"; - break; - case "integer": - case "number": - schema.coreSchema.type = "integer"; - break; - case "password": - schema.coreSchema.type = "string"; - schema.uiSchema["ui:widget"] = "password"; - break; - case "email": - schema.coreSchema.type = "string"; - schema.uiSchema["ui:widget"] = "email"; - break; - case "textarea": - schema.coreSchema.type = "string"; - schema.uiSchema["ui:widget"] = "textarea"; - break; - case "radio": - schema.coreSchema.type = "boolean"; - schema.uiSchema["ui:widget"] = "radio"; - break; - case "checkbox": - schema.coreSchema.type = "array"; - if (payload.hasOwnProperty("items")) { - schema.coreSchema.items = payload.items; - schema.coreSchema.uniqueItems = payload.uniqueItems; - schema.uiSchema["ui:widget"] = "checkboxes"; - } - break; - case "select": - schema.coreSchema.type = payload.fieldType; - if ( - payload.hasOwnProperty("enum") && - Array.isArray(payload.enum) && - payload.hasOwnProperty("labels") && - Array.isArray(payload.labels) && - payload.enum.length === payload.labels.length - ) { - schema.coreSchema.enum = payload.enum; - schema.coreSchema.enumNames = payload.labels; - } - if (payload.hasOwnProperty("label")) { - schema.coreSchema.title = payload.label; - } - break; - } - - return schema; - } - - public async createFieldSchema(payload) { - let fieldSchema = { - required: false, - coreSchema: {}, - uiSchema: {}, - }; - fieldSchema = await this.setTypeProperties(fieldSchema, payload); - if (payload.label) { - fieldSchema.coreSchema["title"] = payload.label; - } - - if (payload.pattern) { - fieldSchema.coreSchema["pattern"] = payload.pattern; - } - - if (payload.hasOwnProperty("minLength")) { - fieldSchema.coreSchema["minLength"] = payload.minLength; - } - - if (payload.hasOwnProperty("maxLength")) { - fieldSchema.coreSchema["maxLength"] = payload.maxLength; - } - - if (payload.defaultValue) { - fieldSchema.coreSchema["default"] = payload.defaultValue; - } - if (payload.placeholder) { - fieldSchema.uiSchema["ui:placeholder"] = payload.placeholder; - } - if (payload.hasOwnProperty("required")) { - fieldSchema.required = true; - } - - if (payload.hasOwnProperty("oneOf")) { - fieldSchema.coreSchema["oneOf"] = payload.oneOf; - } - - return { - [payload.name]: fieldSchema, - }; - } - - //field values - async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { - try { - var axios = require("axios"); - - let query = ""; - Object.keys(fieldValuesDto).forEach((e) => { - if (fieldValuesDto[e] && fieldValuesDto[e] != "") { - if (Array.isArray(fieldValuesDto[e])) { - query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; - } else { - query += `${e}: "${fieldValuesDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateFieldValues { - insert_FieldValues_one(object: {${query}}) { - fieldValuesId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } - } - - async createFieldValuesBulk(field_values: any) { - var axios = require("axios"); - - var data_field_values = { - query: `mutation insert_multiple_fieldValues($objects: [FieldValues_insert_input!]!) { - insert_FieldValues(objects: $objects) { - returning { - fieldValuesId - } - } - } - `, - variables: { - objects: field_values, - }, - }; - - var config_field_value = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data_field_values, - }; - - const response = await axios(config_field_value); - return response; - } - - public async getFieldValues(id: any) { - var axios = require("axios"); - - var data = { - query: `query GetFieldValues($id:uuid!) { - FieldValues( - where:{ - fieldValuesId:{ - _eq:$id - }, - } - ){ - value - fieldValuesId - itemId - fieldId - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - id: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } - - public async getFieldValuesFieldsItemId(field_id: string, item_id: string) { - var axios = require("axios"); - - var data = { - query: `query GetFieldValuesItemId($field_id:uuid!,$item_id:uuid!) { - FieldValues( - where:{ - itemId:{ - _eq:$item_id - }, - fieldId:{ - _eq:$field_id - }, - } - ){ - value - fieldValuesId - itemId - fieldId - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - field_id: field_id, - item_id: item_id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } - - async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { - try { - var axios = require("axios"); - - let offset = 0; - if (fieldValuesSearchDto.page > 1) { - offset = - parseInt(fieldValuesSearchDto.limit) * (fieldValuesSearchDto.page - 1); + else { + whereClause['tenantId'] = tenantId; } - let filters = fieldValuesSearchDto.filters; - - Object.keys(fieldValuesSearchDto.filters).forEach((item) => { - Object.keys(fieldValuesSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchFieldValues($filters:FieldValues_bool_exp,$limit:Int, $offset:Int) { - FieldValues(where:$filters, limit: $limit, offset: $offset,) { - value - fieldValuesId - itemId - fieldId - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(fieldValuesSearchDto.limit), - offset: offset, - filters: fieldValuesSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, + const [results, totalCount] = await this.fieldsRepository.findAndCount({ + where: whereClause, + skip: offset, }); - } - } - async searchFieldValuesFilter(request: any, filter: any) { - try { - let obj_filter = []; - Object.keys(filter).forEach((item) => { - Object.keys(filter[item]).forEach((e) => { - let obj_val = new Object(); - obj_val[e] = filter[item][e]; - obj_filter.push({ - fieldId: { _eq: item }, - value: obj_val, - }); - }); + return new SuccessResponse({ + statusCode: 200, + message: 'Ok.', + totalCount, + data: results, }); - - let valuefilter = new Object({ _or: obj_filter }); - - var axios = require("axios"); - - var data = { - query: `query SearchFieldValuesFilter($valuefilter:FieldValues_bool_exp) { - FieldValues( - where:$valuefilter - ){ - itemId - } - }`, - variables: { valuefilter: valuefilter }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - return response; } catch (e) { console.error(e); return new ErrorResponse({ @@ -736,53 +95,4 @@ export class FieldsService { }); } } - - async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { - var axios = require("axios"); - - let query = ""; - Object.keys(fieldValuesDto).forEach((e) => { - if (fieldValuesDto[e] && fieldValuesDto[e] != "") { - if (Array.isArray(fieldValuesDto[e])) { - query += `${e}: "${JSON.stringify(fieldValuesDto[e])}", `; - } else { - query += `${e}: "${fieldValuesDto[e]}", `; - } - } - }); - - var data = { - query: ` - mutation UpdateFieldValues($id:uuid!) { - update_FieldValues_by_pk( - pk_columns: { - fieldValuesId: $id - }, - _set: { - ${query} - } - ) { - fieldValuesId - } - } - `, - variables: { - id: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - return response; - } } From b159ecbaf5c11bb495750fced77be098bec0136b Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 10:47:41 +0530 Subject: [PATCH 086/408] add --- src/fields/entities/fields-values.entity.ts | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/fields/entities/fields-values.entity.ts diff --git a/src/fields/entities/fields-values.entity.ts b/src/fields/entities/fields-values.entity.ts new file mode 100644 index 00000000..22655a4b --- /dev/null +++ b/src/fields/entities/fields-values.entity.ts @@ -0,0 +1,30 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm'; +// import { Field } from './Field'; // Assuming you have a Field entity defined + +@Entity({ name: 'FieldValues' }) +export class FieldValue { + + @PrimaryGeneratedColumn('uuid', { name: 'fieldValuesId' }) + fieldValuesId: string; + + @Column({ type: 'text', nullable: false }) + value: string; + + @Column({ type: 'uuid', nullable: false, default: () => 'gen_random_uuid()' }) + itemId: string; + + @Column({ type: 'uuid', nullable: false, name: 'fieldId' }) + fieldId: string; + + @CreateDateColumn({ name: 'createdAt', type: 'timestamp with time zone' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updatedAt', type: 'timestamp with time zone' }) + updatedAt: Date; + + @Column({ type: 'text', nullable: true, name: 'createdBy' }) + createdBy: string; + + @Column({ type: 'text', nullable: true, name: 'updatedBy' }) + updatedBy: string; +} From d4c1d52ebf1abeeb57972141ef14792c47c6adff Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 12:11:35 +0530 Subject: [PATCH 087/408] field values insert & search --- src/fields/entities/fields-values.entity.ts | 34 ++++--- src/fields/fields.controller.ts | 43 ++++++++- src/fields/fields.module.ts | 2 + src/fields/fields.service.ts | 102 +++++++++++++++++++- 4 files changed, 165 insertions(+), 16 deletions(-) diff --git a/src/fields/entities/fields-values.entity.ts b/src/fields/entities/fields-values.entity.ts index 22655a4b..84eeedcd 100644 --- a/src/fields/entities/fields-values.entity.ts +++ b/src/fields/entities/fields-values.entity.ts @@ -2,29 +2,41 @@ import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateCol // import { Field } from './Field'; // Assuming you have a Field entity defined @Entity({ name: 'FieldValues' }) -export class FieldValue { - - @PrimaryGeneratedColumn('uuid', { name: 'fieldValuesId' }) - fieldValuesId: string; +export class FieldValues { @Column({ type: 'text', nullable: false }) value: string; + @PrimaryGeneratedColumn('uuid', { name: 'fieldValuesId' }) + fieldValuesId: string; + @Column({ type: 'uuid', nullable: false, default: () => 'gen_random_uuid()' }) itemId: string; @Column({ type: 'uuid', nullable: false, name: 'fieldId' }) fieldId: string; - @CreateDateColumn({ name: 'createdAt', type: 'timestamp with time zone' }) + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) createdAt: Date; - @UpdateDateColumn({ name: 'updatedAt', type: 'timestamp with time zone' }) + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) updatedAt: Date; - @Column({ type: 'text', nullable: true, name: 'createdBy' }) - createdBy: string; - - @Column({ type: 'text', nullable: true, name: 'updatedBy' }) - updatedBy: string; + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdBy: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedBy: Date; } diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index a73618a3..3824702a 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -40,7 +40,7 @@ import { FieldsService } from "./fields.service"; export class FieldsController { constructor(private fieldsAdapter: FieldsAdapter, private readonly fieldsService: FieldsService - ) {} + ) { } //fields //create fields @@ -61,10 +61,10 @@ export class FieldsController { Object.assign(fieldsDto, payload); return this.fieldsService.createFields(request, fieldsDto); - + } - + //search @Post("/search") @SerializeOptions({ @@ -82,5 +82,40 @@ export class FieldsController { return this.fieldsService.searchFields(tenantid, request, fieldsSearchDto); } - + + //field values + //create fields values + @Post("/values") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ + description: "Fields Values has been created successfully.", + }) + @ApiBody({ type: FieldValuesDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + public async createFieldValues( + @Req() request: Request, + @Body() fieldValuesDto: FieldValuesDto + ) { + return this.fieldsService.createFieldValues(request, fieldValuesDto); + } + + //search fields values + @Post("/values/search") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Fields Values list." }) + @ApiBody({ type: FieldValuesSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + @SerializeOptions({ + strategy: "excludeAll", + }) + public async searchFieldValues( + @Req() request: Request, + @Body() fieldValuesSearchDto: FieldValuesSearchDto + ) { + return this.fieldsService.searchFieldValues(request, fieldValuesSearchDto); + } + + } diff --git a/src/fields/fields.module.ts b/src/fields/fields.module.ts index 533b7069..219a6f29 100644 --- a/src/fields/fields.module.ts +++ b/src/fields/fields.module.ts @@ -4,12 +4,14 @@ import { HttpModule } from "@nestjs/axios"; import { FieldsAdapter } from "./fieldsadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { Fields } from "./entities/fields.entity"; +import { FieldValues } from "./entities/fields-values.entity"; import { TypeOrmModule } from "@nestjs/typeorm"; import { FieldsService } from "./fields.service"; const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([Fields]), + TypeOrmModule.forFeature([FieldValues]), HttpModule, HasuraModule, CacheModule.register({ diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 39dce7e8..c103929d 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -6,6 +6,7 @@ import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; import jwt_decode from "jwt-decode"; import { ErrorResponse } from "src/error-response"; import { Fields } from "./entities/fields.entity"; +import { FieldValues } from "./entities/fields-values.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { SuccessResponse } from "src/success-response"; @@ -14,8 +15,9 @@ import { SuccessResponse } from "src/success-response"; export class FieldsService { constructor( @InjectRepository(Fields) - // @InjectRepository(FieldValues) private fieldsRepository: Repository, + @InjectRepository(FieldValues) + private fieldsValuesRepository: Repository, ) { } //fields @@ -95,4 +97,102 @@ export class FieldsService { }); } } + + async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { + try { + + const fieldsData: any = {}; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + fieldsData[e] = JSON.stringify(fieldValuesDto[e]); + } else { + fieldsData[e] = fieldValuesDto[e]; + } + } + }); + + console.log(fieldsData); + + let result = await this.fieldsValuesRepository.save(fieldsData); + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { + try { + + let { limit, page, filters } = fieldValuesSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + + console.log(whereClause); + + const [results, totalCount] = await this.fieldsValuesRepository.findAndCount({ + where: whereClause, + take: parseInt(limit), + skip: offset, + }); + + const mappedResponse = await this.mappedResponse(results); + + return new SuccessResponse({ + statusCode: 200, + message: 'Ok.', + totalCount, + data: mappedResponse, + }); + + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + public async mappedResponse(result: any) { + const fieldValueResponse = result.map((item: any) => { + const fieldValueMapping = { + value: item?.value ? `${item.value}` : "", + fieldValuesId: item?.fieldValuesId ? `${item.fieldValuesId}` : "", + itemId: item?.itemId ? `${item.itemId}` : "", + fieldId: item?.fieldId ? `${item.fieldId}` : "", + createdAt: item?.createdAt ? `${item.createdAt}` : "", + updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", + createdBy: item?.createdBy ? `${item.createdBy}` : "", + updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + }; + + return new FieldValuesDto(fieldValueMapping); + }); + + return fieldValueResponse; + } } From 367c0e580b3bf265b196c866f6c4ce129ea44fac Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 12:26:17 +0530 Subject: [PATCH 088/408] add --- src/cohort/cohort.controller.ts | 4 +- src/cohort/cohort.service.ts | 98 +++++++++++++++++++++++++++++++++ src/fields/fields.controller.ts | 1 + 3 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 94bcea26..bfac41aa 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -78,9 +78,7 @@ export class CohortController { }; Object.assign(cohortCreateDto, payload); - return this.cohortAdapter - .buildCohortAdapter() - .createCohort(request, cohortCreateDto); + return this.cohortService.createCohort(request, cohortCreateDto); } //get cohort diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 56e92a1f..3ae57cff 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -76,6 +76,104 @@ export class CohortService { } } + public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { + try{ + var axios = require("axios"); + + let query = ""; + Object.keys(cohortCreateDto).forEach((e) => { + if ( + cohortCreateDto[e] && + cohortCreateDto[e] != "" && + e != "fieldValues" + ) { + if (Array.isArray(cohortCreateDto[e])) { + query += `${e}: "${JSON.stringify(cohortCreateDto[e])}", `; + } else { + query += `${e}: "${cohortCreateDto[e]}", `; + } + } + }); + + var data = { + query: `mutation CreateCohort { + insert_Cohort_one(object: {${query}}) { + cohortId + } + } + `, + variables: {}, + }; + + var config = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + Authorization: request.headers.authorization, + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + if (response?.data?.errors) { + return new ErrorResponse({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + const result = response.data.data.insert_Cohort_one; + let fieldCreate = true; + let fieldError = null; + //create fields values + let cohortId = result?.cohortId; + let field_value_array = cohortCreateDto.fieldValues.split("|"); + + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + let fieldValues = field_value_array[i].split(":"); + field_values.push({ + value: fieldValues[1] ? fieldValues[1] : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0] : "", + createdBy: cohortCreateDto?.createdBy, + updatedBy: cohortCreateDto?.updatedBy, + }); + } + + const response_field_values = + await this.fieldsService.createFieldValuesBulk(field_values); + if (response_field_values?.data?.errors) { + fieldCreate = false; + fieldError = response_field_values?.data; + } + } + + if (fieldCreate) { + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: result, + }); + } else { + return new ErrorResponse({ + errorCode: fieldError?.errors[0]?.extensions?.code, + errorMessage: fieldError?.errors[0]?.message, + }); + } + } + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, + }); + } + } + + public async mappedResponse(result: any) { const cohortMapping = { tenantId: result?.tenantId ? `${result.tenantId}` : "", diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 3824702a..54b9582d 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -117,5 +117,6 @@ export class FieldsController { return this.fieldsService.searchFieldValues(request, fieldValuesSearchDto); } + } From dedabef8646486810a6a8f9488936705a23639b1 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 13:14:42 +0530 Subject: [PATCH 089/408] add --- src/cohort/cohort.module.ts | 5 +- src/cohort/cohort.service.ts | 129 ++++++++++++++--------------------- src/fields/fields.service.ts | 40 +++++++++-- 3 files changed, 92 insertions(+), 82 deletions(-) diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 6a17c041..3d079238 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -6,10 +6,13 @@ import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { CohortService } from "./cohort.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { Cohort } from "./entities/cohort.entity"; +import { FieldsService } from "../fields/fields.service"; +import { FieldValues } from "../fields/entities/fields-values.entity"; const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([Cohort]), + TypeOrmModule.forFeature([FieldValues]), HttpModule, HasuraModule, CacheModule.register({ @@ -17,6 +20,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [CohortController], - providers: [CohortAdapter, CohortService], + providers: [CohortAdapter, CohortService, FieldsService], }) export class CohortModule {} diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 3ae57cff..5f3d9c18 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -14,10 +14,11 @@ import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { InjectRepository } from "@nestjs/typeorm"; -import { FieldsService } from "src/adapters/hasura/services/fields.service"; +import { FieldsService } from "../fields/fields.service"; // import { FieldValues } from "src/fields/entities/field-values.entity"; import { response } from "express"; import APIResponse from "src/utils/response"; +import { FieldValues } from "../fields/entities/fields-values.entity"; @Injectable() export class CohortService { @@ -25,9 +26,10 @@ export class CohortService { constructor( @InjectRepository(Cohort) - // @InjectRepository(FieldValues) private cohortRepository: Repository, - // private readonly fieldsService: FieldsService + @InjectRepository(FieldValues) + private fieldsValuesRepository: Repository, + private readonly fieldsService: FieldsService, ) {} public async getCohort( @@ -78,92 +80,67 @@ export class CohortService { public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try{ - var axios = require("axios"); - let query = ""; + const cohortData: any = {}; Object.keys(cohortCreateDto).forEach((e) => { - if ( - cohortCreateDto[e] && - cohortCreateDto[e] != "" && - e != "fieldValues" - ) { - if (Array.isArray(cohortCreateDto[e])) { - query += `${e}: "${JSON.stringify(cohortCreateDto[e])}", `; - } else { - query += `${e}: "${cohortCreateDto[e]}", `; + if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { + if (Array.isArray(cohortCreateDto[e])) { + cohortData[e] = JSON.stringify(cohortCreateDto[e]); + } else { + cohortData[e] = cohortCreateDto[e]; + } } - } }); - var data = { - query: `mutation CreateCohort { - insert_Cohort_one(object: {${query}}) { - cohortId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); + const response = await this.cohortRepository.save(cohortData); if (response?.data?.errors) { return new ErrorResponse({ errorCode: response?.data?.errors[0]?.extensions?.code, errorMessage: response?.data?.errors[0]?.message, }); - } else { - const result = response.data.data.insert_Cohort_one; - let fieldCreate = true; - let fieldError = null; - //create fields values - let cohortId = result?.cohortId; - let field_value_array = cohortCreateDto.fieldValues.split("|"); + } + // else { + // const result = response.data.data.insert_Cohort_one; + // let fieldCreate = true; + // let fieldError = null; + // //create fields values + // let cohortId = result?.cohortId; + // let field_value_array = cohortCreateDto.fieldValues.split("|"); - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - field_values.push({ - value: fieldValues[1] ? fieldValues[1] : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0] : "", - createdBy: cohortCreateDto?.createdBy, - updatedBy: cohortCreateDto?.updatedBy, - }); - } + // if (field_value_array.length > 0) { + // let field_values = []; + // for (let i = 0; i < field_value_array.length; i++) { + // let fieldValues = field_value_array[i].split(":"); + // field_values.push({ + // value: fieldValues[1] ? fieldValues[1] : "", + // itemId: cohortId, + // fieldId: fieldValues[0] ? fieldValues[0] : "", + // createdBy: cohortCreateDto?.createdBy, + // updatedBy: cohortCreateDto?.updatedBy, + // }); + // } - const response_field_values = - await this.fieldsService.createFieldValuesBulk(field_values); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError = response_field_values?.data; - } - } + // const response_field_values = + // await this.fieldsService.createFieldValuesBulk(field_values); + // if (response_field_values?.data?.errors) { + // fieldCreate = false; + // fieldError = response_field_values?.data; + // } + // } - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } else { - return new ErrorResponse({ - errorCode: fieldError?.errors[0]?.extensions?.code, - errorMessage: fieldError?.errors[0]?.message, - }); - } - } + // if (fieldCreate) { + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } else { + // return new ErrorResponse({ + // errorCode: fieldError?.errors[0]?.extensions?.code, + // errorMessage: fieldError?.errors[0]?.message, + // }); + // } + // } }catch (e) { console.error(e); return new ErrorResponse({ diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index c103929d..05b7c418 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -112,8 +112,6 @@ export class FieldsService { } }); - console.log(fieldsData); - let result = await this.fieldsValuesRepository.save(fieldsData); return new SuccessResponse({ statusCode: 200, @@ -139,7 +137,7 @@ export class FieldsService { if (page > 1) { offset = parseInt(limit) * (page - 1); } - + if (limit.trim() === '') { limit = '0'; } @@ -152,13 +150,13 @@ export class FieldsService { } console.log(whereClause); - + const [results, totalCount] = await this.fieldsValuesRepository.findAndCount({ where: whereClause, take: parseInt(limit), skip: offset, }); - + const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ @@ -177,6 +175,38 @@ export class FieldsService { } } + async createFieldValuesBulk(field_values: any) { + var axios = require("axios"); + + var data_field_values = { + query: `mutation insert_multiple_fieldValues($objects: [FieldValues_insert_input!]!) { + insert_FieldValues(objects: $objects) { + returning { + fieldValuesId + } + } + } + `, + variables: { + objects: field_values, + }, + }; + + var config_field_value = { + method: "post", + url: process.env.REGISTRYHASURA, + headers: { + "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + "Content-Type": "application/json", + }, + data: data_field_values, + }; + + const response = await axios(config_field_value); + return response; + } + + public async mappedResponse(result: any) { const fieldValueResponse = result.map((item: any) => { const fieldValueMapping = { From 00b505800068c8a4e64eaeb27c816e40c17c9913 Mon Sep 17 00:00:00 2001 From: Shubham Date: Sat, 23 Mar 2024 14:18:30 +0530 Subject: [PATCH 090/408] Task #216180: Added AUTH service and Remove Adapters. --- src/adapters/auth/auth.adapter.ts | 39 ------------------ src/auth/auth-service.ts | 42 +++++++++++++++++++ src/auth/auth.controller.ts | 6 +-- src/auth/auth.module.ts | 4 +- src/auth/dto/auth-dto.ts | 5 +++ src/user/entities/user-create-entity.ts | 55 ------------------------- 6 files changed, 52 insertions(+), 99 deletions(-) delete mode 100644 src/adapters/auth/auth.adapter.ts create mode 100644 src/auth/auth-service.ts delete mode 100644 src/user/entities/user-create-entity.ts diff --git a/src/adapters/auth/auth.adapter.ts b/src/adapters/auth/auth.adapter.ts deleted file mode 100644 index fd0b0007..00000000 --- a/src/adapters/auth/auth.adapter.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { AuthDto } from "src/auth/dto/auth-dto"; - -@Injectable() -export class HasuraAuthService { - axios = require("axios"); - - constructor(private httpService: HttpService) {} - - public async login(request: any, response: any, loginDto: AuthDto) { - const qs = require("qs"); - console.log(loginDto); - const data = qs.stringify({ - username: loginDto.username, - password: loginDto.password, - grant_type: "password", - client_id: "hasura", - client_secret: process.env.KEYCLOAK_HASURA_CLIENT_SECRET, - }); - console.log(data); - const config = { - method: "post", - url: process.env.KEYCLOAK + process.env.KEYCLOAK_USER_TOKEN, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - data: data, - }; - - try { - const res = await this.axios(config); - return response.status(200).send(res.data); - } catch (error) { - console.error(error, "err"); - return error; - } - } -} diff --git a/src/auth/auth-service.ts b/src/auth/auth-service.ts new file mode 100644 index 00000000..65a4d8f8 --- /dev/null +++ b/src/auth/auth-service.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@nestjs/common'; +import axios from 'axios'; +import qs from 'qs' + + + +@Injectable() +@Injectable() +export class AuthService { + private axiosInstance; + constructor(){ + this.axiosInstance = axios.create(); + } + + async login(authDto,response){ + try{ + const { KEYCLOAK, KEYCLOAK_USER_TOKEN, KEYCLOAK_HASURA_CLIENT_SECRET } = process.env; + const data = qs.stringify({ + username: authDto.username, + password: authDto.password, + grant_type: "password", + client_id: "hasura", + client_secret: KEYCLOAK_HASURA_CLIENT_SECRET, + }); + + const axiosConfig = { + method: "post", + url: `${KEYCLOAK}${KEYCLOAK_USER_TOKEN}`, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + data: data, + }; + + const res = await this.axiosInstance(axiosConfig); + return response.status(200).send(res.data); + } catch (error) { + console.error(error); + return response.status(500).send({ message: 'An error occurred during login.' }); + } + } +} \ No newline at end of file diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 120a9704..117b9609 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -20,14 +20,14 @@ import { Response, Headers, } from "@nestjs/common"; -import { HasuraAuthService } from "src/adapters/auth/auth.adapter"; import { AuthDto } from "./dto/auth-dto"; +import { AuthService } from "./auth-service"; @ApiTags("Auth") @Controller("auth") export class AuthController { constructor( - private authService: HasuraAuthService + private authService:AuthService ) {} @Post("/login") @@ -43,6 +43,6 @@ export class AuthController { @Body() authDto: AuthDto ) { console.log(request) - return this.authService.login(request, response, authDto); + return this.authService.login(authDto,response); } } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index d64776fe..2a884be6 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,7 +1,7 @@ import { CacheModule, Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { AuthController } from "./auth.controller"; -import { HasuraAuthService } from "src/adapters/auth/auth.adapter"; +import { AuthService } from "./auth-service"; const ttl = process.env.TTL as never; @Module({ @@ -12,6 +12,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [AuthController], - providers: [HasuraAuthService], + providers: [AuthService], }) export class AuthModule {} diff --git a/src/auth/dto/auth-dto.ts b/src/auth/dto/auth-dto.ts index 0d998644..18b07837 100644 --- a/src/auth/dto/auth-dto.ts +++ b/src/auth/dto/auth-dto.ts @@ -1,16 +1,21 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import {IsString,IsNotEmpty} from 'class-validator' export class AuthDto { @ApiProperty({ type: String, description: "username", }) + @IsString() + @IsNotEmpty() username: string; @ApiProperty({ type: String, description: "password", }) + @IsString() + @IsNotEmpty() password: string; constructor(partial: Partial) { diff --git a/src/user/entities/user-create-entity.ts b/src/user/entities/user-create-entity.ts deleted file mode 100644 index 863a5a1b..00000000 --- a/src/user/entities/user-create-entity.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm"; - -@Entity({ name: "Users" }) -export class User { - @PrimaryColumn({ type: "uuid" }) - userId: string; - - @Column({ unique: true }) - username: string; - - @Column() - name: string; - - @Column() - role: string; - - @Column({ type: "date", nullable: true }) - dob: Date; - - @Column({ nullable: true }) - email: string; - - @Column({ nullable: true }) - district: string; - - @Column({ nullable: true }) - state: string; - - @Column({ nullable: true }) - address: string; - - @Column({ nullable: true }) - pincode: string; - - @CreateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) - createdAt: Date; - - @UpdateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) - updatedAt: Date; - -// @Column({ type: "numberic", nullable: true }) -// mobile: number; - - @Column({ nullable: true }) - createdBy: string; - - @Column({ nullable: true }) - updatedBy: string; - - @Column({ type: "uuid" }) - tenantId: string; - - @Column({ default: "active" }) - status: string; -} From 1466cae4f5f27e6a25a6d10fc3826617ab68a64a Mon Sep 17 00:00:00 2001 From: Shubham Date: Sat, 23 Mar 2024 14:21:10 +0530 Subject: [PATCH 091/408] Task #216181: View Profile API with Custom Fields --- src/common/database.module.ts | 2 +- src/user/entities/field-entity.ts | 79 +++++++++ ...ld-entities.ts => field-value-entities.ts} | 0 src/user/entities/user-entity.ts | 55 ++++++ src/user/user.controller.ts | 48 +++--- src/user/user.module.ts | 8 +- src/user/user.service.ts | 160 +++++++++++++----- 7 files changed, 277 insertions(+), 75 deletions(-) create mode 100644 src/user/entities/field-entity.ts rename src/user/entities/{field-entities.ts => field-value-entities.ts} (100%) create mode 100644 src/user/entities/user-entity.ts diff --git a/src/common/database.module.ts b/src/common/database.module.ts index 90010cf2..8cf44fc5 100644 --- a/src/common/database.module.ts +++ b/src/common/database.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { User } from 'src/user/entities/user-create-entity'; +import { User } from 'src/user/entities/user-entity'; @Module({ imports: [ diff --git a/src/user/entities/field-entity.ts b/src/user/entities/field-entity.ts new file mode 100644 index 00000000..bc5aaec8 --- /dev/null +++ b/src/user/entities/field-entity.ts @@ -0,0 +1,79 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; + +@Entity({ name: 'Fields', schema: 'public' }) +export class Field { + @PrimaryGeneratedColumn('uuid') + fieldId: string; + + @Column({ type: 'varchar', nullable: true }) + assetId: string; + + @Column({ type: 'varchar' }) + context: string; + + @Column({ type: 'varchar', nullable: true }) + groupId: string; + + @Column({ type: 'varchar' }) + name: string; + + @Column({ type: 'varchar' }) + label: string; + + @Column({ type: 'varchar', nullable: true }) + defaultValue: string; + + @Column({ type: 'varchar' }) + type: string; + + @Column({ type: 'text', nullable: true }) + note: string; + + @Column({ type: 'text', nullable: true }) + description: string; + + @Column({ type: 'text' }) + state: string; + + @Column({ type: 'boolean' }) + required: boolean; + + @Column({ type: 'integer' }) + ordering: number; + + @Column({ type: 'text' }) + metadata: string; + + @Column({ type: 'varchar', nullable: true }) + access: string; + + @Column({ type: 'boolean' }) + onlyUseInSubform: boolean; + + @Column({ type: 'uuid' }) + tenantId: string; + + @CreateDateColumn({ type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' }) + createdAt: Date; + + @UpdateDateColumn({ type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' }) + updatedAt: Date; + + @Column({ type: 'varchar', nullable: true }) + createdBy: string; + + @Column({ type: 'varchar', nullable: true }) + updatedBy: string; + + @Column({ type: 'uuid', nullable: true }) + contextId: string; + + @Column({ type: 'varchar', nullable: true }) + render: string; + + @Column({ type: 'varchar', nullable: true }) + contextType: string; + + @Column({ type: 'jsonb', nullable: true }) + fieldParams: object; +} diff --git a/src/user/entities/field-entities.ts b/src/user/entities/field-value-entities.ts similarity index 100% rename from src/user/entities/field-entities.ts rename to src/user/entities/field-value-entities.ts diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts new file mode 100644 index 00000000..863a5a1b --- /dev/null +++ b/src/user/entities/user-entity.ts @@ -0,0 +1,55 @@ +import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm"; + +@Entity({ name: "Users" }) +export class User { + @PrimaryColumn({ type: "uuid" }) + userId: string; + + @Column({ unique: true }) + username: string; + + @Column() + name: string; + + @Column() + role: string; + + @Column({ type: "date", nullable: true }) + dob: Date; + + @Column({ nullable: true }) + email: string; + + @Column({ nullable: true }) + district: string; + + @Column({ nullable: true }) + state: string; + + @Column({ nullable: true }) + address: string; + + @Column({ nullable: true }) + pincode: string; + + @CreateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + createdAt: Date; + + @UpdateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + updatedAt: Date; + +// @Column({ type: "numberic", nullable: true }) +// mobile: number; + + @Column({ nullable: true }) + createdBy: string; + + @Column({ nullable: true }) + updatedBy: string; + + @Column({ type: "uuid" }) + tenantId: string; + + @Column({ default: "active" }) + status: string; +} diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 3b16bbbf..ae3d78b8 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -45,13 +45,16 @@ export class UserController { private userService:UserService ) {} - // @Get('/shubham/:userId') - // @UseInterceptors(CacheInterceptor) - // async getUser1(@Param("userid") userId: string){ - // console.log("Hi"); - // return await this.userService1.getUsers(userId); - // } - + + /** + * Method to get The User Details and Custome Fields Data. + * + * @param userId $data User Id of User + * + * @return UserData Object containing all teh detals + * + * @since 1.6 + */ @Get("/:userid") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) @ApiBasicAuth("access-token") @@ -63,16 +66,20 @@ export class UserController { @ApiHeader({ name: "tenantid", }) - @ApiQuery({ name: "accessrole" }) public async getUser( @Headers() headers, @Param("userid") userId: string, - @Query("accessrole") accessRole: string, @Req() request: Request, @Res() response: Response ) { - const tenantId = headers["tenantid"]; - return this.userAdapter.buildUserAdapter().getUser(tenantId, userId, accessRole, request, response); + // const tenantId = headers["tenantid"]; Can be Used In future + // Context and ContextType can be taked from .env later + let userData = { + userId:userId, + context:"USERS", + contextType:"TEACHER" + } + return this.userService.getUsersDetailsById(userData,response); } @Get() @@ -100,18 +107,16 @@ export class UserController { @ApiHeader({ name: "tenantid", }) - public async createUser( + async createUser( @Headers() headers, @Req() request: Request, + @Res() response:Response, @Body() userCreateDto: UserCreateDto ) { - console.log(userCreateDto); userCreateDto.tenantId = headers["tenantid"]; - return this.userAdapter - .buildUserAdapter() - .checkAndAddUser(request, userCreateDto); + return this.userService.createUser(request, userCreateDto,response); } - + @Put("/:userid") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User has been updated successfully." }) @@ -175,14 +180,5 @@ export class UserController { .resetUserPassword(request, reqBody.username, reqBody.newPassword); } - @Post('/createShubhamUser') - async createShubhamUser( - @Headers() headers, - @Req() request: Request, - @Body() userCreateDto: UserCreateDto - ) { - userCreateDto.tenantId = headers["tenantid"]; - return this.userService.createShubhamUser(request, userCreateDto); - } } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index a114b913..e113ad28 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -5,15 +5,17 @@ import { UserAdapter } from "./useradapter"; import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { TypeOrmModule } from "@nestjs/typeorm"; -import { User } from "./entities/user-create-entity"; +import { User } from "./entities/user-entity"; import { UserService } from "./user.service"; -import { FieldValue } from "./entities/field-entities"; +import { FieldValue } from "./entities/field-value-entities"; +import { Field } from "./entities/field-entity"; const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([ User, - FieldValue + FieldValue, + Field ]), HttpModule, SunbirdModule, diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 33b6388d..1069bd89 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -1,6 +1,7 @@ -import { Injectable } from '@nestjs/common'; -import { User } from './entities/user-create-entity' -import { FieldValue } from './entities/field-entities'; +import { HttpStatus, Injectable } from '@nestjs/common'; +import { User } from './entities/user-entity' +import { FieldValue } from './entities/field-value-entities'; +import ApiResponse from '../utils/response' import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { UserCreateDto } from './dto/user-create.dto'; @@ -13,6 +14,8 @@ import { } from "../common/keycloak"; import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; +import { Field } from './entities/field-entity'; +import APIResponse from '../utils/response'; @Injectable() @@ -22,25 +25,85 @@ export class UserService { @InjectRepository(User) private usersRepository: Repository, @InjectRepository(FieldValue) - private fieldsValueRepository: Repository + private fieldsValueRepository: Repository, + @InjectRepository(Field) + private fieldsRepository : Repository ) {} + + async getUsersDetailsById(userData:Record,response){ + let apiId='api.users.getUsersDetails' + try { + const result = { + customFields: [] + }; - async getUsers(userID){ - let result = await this.usersRepository.findOne({ - where:{ - userId:userID - } - }); - console.log(result); + // const customFields = await this.findCustomFields(userData); + // const filledValues = await this.findFilledValues(userData?.userId); + const [customFields, filledValues,userDetails] = await Promise.all([ + this.findCustomFields(userData), + this.findFilledValues(userData.userId), + this.findUserDetails(userData.userId) + ]); + const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); + for (const data of customFields) { + const fieldValue = filledValuesMap.get(data.fieldId); + const customField = { + fieldId: data.fieldId, + label: data.label, + value: fieldValue || '', + options: data.fieldParams || {}, + type: data.type || '' + }; + result.customFields.push(customField); + } + result['userData']=userDetails; + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, result, 'OK')); + } catch (e) { + response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + 'Something went wrong In finding UserDetails', + e, + 'INTERNAL_SERVER_ERROR', + ), + ); + } +} + + async findUserDetails(userId){ + let userDetails = await this.usersRepository.findOne({ + where:{ + userId:userId + } + }) + return userDetails; + } + async findCustomFields(userData){ + let customFields = await this.fieldsRepository.find({ + where:{ + context:userData.context, + contextType:userData.contextType + } + }) + return customFields; + } + async findFilledValues(userId:string){ + let query = `SELECT U."userId",F."fieldId",F."value" FROM public."Users" U + LEFT JOIN public."FieldValues" F + ON U."userId" = F."itemId" where U."userId" =$1`; + let result = await this.usersRepository.query(query,[userId]); return result; } - public async createShubhamUser(request: any, userCreateDto: UserCreateDto) { + public async createUser(request: any, userCreateDto: UserCreateDto,response) { // It is considered that if user is not present in keycloak it is not present in database as well + let apiId='api.user.creatUser' try { - console.log("Hi"); const decoded: any = jwt_decode(request.headers.authorization); - // const userRoles = decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; userCreateDto.createdBy = userId userCreateDto.updatedBy = userId; @@ -51,9 +114,7 @@ export class UserService { let errKeycloak = ""; let resKeycloak = ""; - - // if (altUserRoles.includes("systemAdmin")) { - + const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; @@ -69,42 +130,51 @@ export class UserService { ); userCreateDto.userId = resKeycloak; return await this.createUserInDatabase(request, userCreateDto); } catch (e) { - console.error(e); - return e; + response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + ApiResponse.error( + apiId, + 'Something went wrong', + `Failure Posting Data. Error is: ${e}`, + 'INTERNAL_SERVER_ERROR', + ), + ); } } +// Can be Implemeneted after we know what are the unique entties +async checkUserinKeyCloakandDb(userDto){ + const keycloakResponse = await getKeycloakAdminToken(); + const token = keycloakResponse.data.access_token; + const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( + userDto.username, + token + ); + if(usernameExistsInKeycloak){ + return usernameExistsInKeycloak; + } +} + async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { - let result = await this.usersRepository.save(userCreateDto); + let userData = { + username:userCreateDto?.username, + name:userCreateDto?.name, + role:userCreateDto.role, + password:userCreateDto.password, + mobile:userCreateDto.mobile, + tenantId:userCreateDto.tenantId, + createdBy:userCreateDto.createdBy, + updatedby:userCreateDto.updatedBy, + userId:userCreateDto.userId, + } + let result = await this.usersRepository.create(userData); return new SuccessResponse({ statusCode: 200, message: "Ok.", data: result, - }); - } - // if(result){ - // let fieldCreate = true; - // let fieldError = null; - // //create fields values - // let userId = result?.userId; - // let field_value_array = userCreateDto.fieldValues?.split("|"); - // if (field_value_array?.length > 0) { - // console.log("Hi"); - // let field_values = []; - // for (let i = 0; i < field_value_array.length; i++) { - // let fieldValues = field_value_array[i].split(":"); - // field_values.push({ - // value: fieldValues[1] ? fieldValues[1] : "", - // itemId: userId, - // fieldId: fieldValues[0] ? fieldValues[0] : "", - // createdBy: userCreateDto?.createdBy, - // updatedBy: userCreateDto?.updatedBy, - // }); - // } - // console.log(field_values,"Checking"); - // const response_field_values = await this.fieldsValueRepository.save(field_values); - // console.log(response_field_values); - } + });} +} From a2bd5a83a71553b2f97f851a3fae07fe64de08da Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 17:20:04 +0530 Subject: [PATCH 092/408] cohort --- src/cohort/cohort.controller.ts | 13 ++- src/cohort/cohort.module.ts | 10 +- src/cohort/cohort.service.ts | 169 +++++++++++++++++++++++++++++++- src/user/user.module.ts | 1 + 4 files changed, 178 insertions(+), 15 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index bfac41aa..974ef5c0 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -36,13 +36,15 @@ import { Response, response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortService } from "./cohort.service"; +// import { FieldsService } from "../fields/fields.service"; @ApiTags("Cohort") @Controller("cohort") export class CohortController { constructor( private cohortAdapter: CohortAdapter, - private readonly cohortService: CohortService + private readonly cohortService: CohortService, + // private readonly fieldsService: FieldsService, ) {} //create cohort @@ -123,9 +125,7 @@ export class CohortController { @Res() res: Response ) { let tenantid = headers["tenantid"]; - return this.cohortAdapter - .buildCohortAdapter() - .searchCohort(tenantid, request, cohortSearchDto, res); + return this.cohortService.searchCohort(tenantid, request, cohortSearchDto, res); } //update @@ -156,8 +156,7 @@ export class CohortController { }; Object.assign(cohortCreateDto, response); - return this.cohortAdapter - .buildCohortAdapter() - .updateCohort(cohortId, request, cohortCreateDto); + return this.cohortService.updateCohort(cohortId, request, cohortCreateDto); + } } diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 3d079238..f3b0e713 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -6,13 +6,14 @@ import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { CohortService } from "./cohort.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { Cohort } from "./entities/cohort.entity"; -import { FieldsService } from "../fields/fields.service"; -import { FieldValues } from "../fields/entities/fields-values.entity"; +// import { FieldsModule } from "../fields/fields.module"; +// import { FieldValues } from "../fields/entities/fields-values.entity"; +// import { FieldsService } from "../fields/fields.service"; + const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([Cohort]), - TypeOrmModule.forFeature([FieldValues]), HttpModule, HasuraModule, CacheModule.register({ @@ -20,6 +21,7 @@ const ttl = process.env.TTL as never; }), ], controllers: [CohortController], - providers: [CohortAdapter, CohortService, FieldsService], + providers: [CohortAdapter, CohortService], }) export class CohortModule {} + diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 5f3d9c18..90a8d4f3 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -27,9 +27,9 @@ export class CohortService { constructor( @InjectRepository(Cohort) private cohortRepository: Repository, - @InjectRepository(FieldValues) - private fieldsValuesRepository: Repository, - private readonly fieldsService: FieldsService, + // @InjectRepository(FieldValues) + // private fieldsValuesRepository: Repository, + // private readonly fieldsService: FieldsService, ) {} public async getCohort( @@ -80,7 +80,6 @@ export class CohortService { public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try{ - const cohortData: any = {}; Object.keys(cohortCreateDto).forEach((e) => { if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { @@ -93,6 +92,7 @@ export class CohortService { }); const response = await this.cohortRepository.save(cohortData); + if (response?.data?.errors) { return new ErrorResponse({ errorCode: response?.data?.errors[0]?.extensions?.code, @@ -150,6 +150,167 @@ export class CohortService { } } + public async updateCohort( + cohortId: string, + request: any, + cohortUpdateDto: CohortCreateDto + ) { + const cohortUpdateData: any = {}; + + Object.keys(cohortUpdateDto).forEach((e) => { + if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" + ) { + if (Array.isArray(cohortUpdateDto[e])) { + cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + } else { + cohortUpdateData[e] = cohortUpdateDto[e]; + } + } + }); + + + const response = await this.cohortRepository.update(cohortId ,cohortUpdateData); + + // if (response?.data?.errors) { + // return new ErrorResponse({ + // errorCode: response?.data?.errors[0]?.extensions?.code, + // errorMessage: response?.data?.errors[0]?.message, + // }); + // } + // else { + // let result = response.data.update_Cohort_by_pk; + // let fieldCreate = true; + // let fieldError = []; + // //update fields values + // let field_value_array = cohortUpdateDto.fieldValues.split("|"); + // if (field_value_array.length > 0) { + // for (let i = 0; i < field_value_array.length; i++) { + // let fieldValues = field_value_array[i].split(":"); + // //update values + // let fieldValuesUpdate = new FieldValuesDto({ + // value: fieldValues[1] ? fieldValues[1] : "", + // }); + + // const response_field_values = + // await this.fieldsService.updateFieldValues( + // fieldValues[0] ? fieldValues[0] : "", + // fieldValuesUpdate + // ); + // if (response_field_values?.data?.errors) { + // fieldCreate = false; + // fieldError.push(response_field_values?.data); + // } + // } + // } + // if (fieldCreate) { + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } else { + // return new ErrorResponse({ + // errorCode: "filed value update error", + // errorMessage: JSON.stringify(fieldError), + // }); + // } + // } + } + + public async searchCohort( + tenantId: string, + request: any, + cohortSearchDto: CohortSearchDto, + res: any + ) { + try{ + let entityFilter = cohortSearchDto; + let filedsFilter = entityFilter?.filters["fields"]; + //remove fields from filter + delete entityFilter.filters["fields"]; + let newCohortSearchDto = null; + //check fields value present or not + if (filedsFilter) { + //apply filter on fields value + let response_fields_value = + await this.fieldsService.searchFieldValuesFilter(request,filedsFilter); + if (response_fields_value?.data?.errors) { + return res.status(200).send({ + errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, + errorMessage: response_fields_value?.data?.errors[0]?.message, + }); + } else { + //get filter result + let result_FieldValues = response_fields_value?.data?.data?.FieldValues; + //fetch cohot id list + let cohort_id_list = []; + for (let i = 0; i < result_FieldValues.length; i++) { + cohort_id_list.push(result_FieldValues[i].itemId); + } + //remove duplicate entries + cohort_id_list = cohort_id_list.filter( + (item, index) => cohort_id_list.indexOf(item) === index + ); + let cohort_filter = new Object(entityFilter.filters); + cohort_filter["cohortId"] = { + _in: cohort_id_list, + }; + newCohortSearchDto = new CohortSearchDto({ + limit: entityFilter.limit, + page: entityFilter.page, + filters: cohort_filter, + }); + } + } else { + newCohortSearchDto = new CohortSearchDto({ + limit: entityFilter.limit, + page: entityFilter.page, + filters: entityFilter.filters, + }); + } + if (newCohortSearchDto) { + const response = await this.searchCohortQuery( + request, + tenantId, + newCohortSearchDto + ); + if (response?.data?.errors) { + return res.status(200).send({ + errorCode: response?.data?.errors[0]?.extensions?.code, + errorMessage: response?.data?.errors[0]?.message, + }); + } else { + let result = response?.data?.data?.Cohort; + let cohortResponse = await this.mappedResponse(result); + //const count = cohortResponse.length; + const count = result.length; + //get cohort fields value + let result_data = await this.searchCohortFields( + request, + tenantId, + cohortResponse + ); + return res.status(200).send({ + statusCode: 200, + message: "Ok.", + totalCount: count, + data: result_data, + }); + } + } else { + return res.status(200).send({ + errorCode: "filter invalid", + errorMessage: "filter invalid", + }); + } + }catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, + }); + } + } public async mappedResponse(result: any) { const cohortMapping = { diff --git a/src/user/user.module.ts b/src/user/user.module.ts index a114b913..e2add0a5 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -26,3 +26,4 @@ const ttl = process.env.TTL as never; providers: [UserAdapter,UserService], }) export class UserModule {} + From 0f3fbda2f4da0ba0f06e47c8f480e53590d46822 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 17:27:05 +0530 Subject: [PATCH 093/408] add --- src/cohort/cohort.controller.ts | 47 ++++---- src/cohort/cohort.module.ts | 9 +- src/cohort/cohort.service.ts | 190 ++++++++++++++++---------------- 3 files changed, 122 insertions(+), 124 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 974ef5c0..f6dc8532 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -37,16 +37,13 @@ import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortService } from "./cohort.service"; // import { FieldsService } from "../fields/fields.service"; - @ApiTags("Cohort") @Controller("cohort") export class CohortController { constructor( private cohortAdapter: CohortAdapter, - private readonly cohortService: CohortService, - // private readonly fieldsService: FieldsService, + private readonly cohortService: CohortService ) {} - //create cohort @Post() @ApiConsumes("multipart/form-data") @@ -106,27 +103,27 @@ export class CohortController { } // search - @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort list." }) - @ApiBody({ type: CohortSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async searchCohort( - @Headers() headers, - @Req() request: Request, - @Body() cohortSearchDto: CohortSearchDto, - @Res() res: Response - ) { - let tenantid = headers["tenantid"]; - return this.cohortService.searchCohort(tenantid, request, cohortSearchDto, res); - } + // @Post("/search") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Cohort list." }) + // @ApiBody({ type: CohortSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async searchCohort( + // @Headers() headers, + // @Req() request: Request, + // @Body() cohortSearchDto: CohortSearchDto, + // @Res() res: Response + // ) { + // let tenantid = headers["tenantid"]; + // return this.cohortService.searchCohort(tenantid, request, cohortSearchDto, res); + // } //update @Put("/:id") diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index f3b0e713..f444a5d7 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -6,14 +6,13 @@ import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { CohortService } from "./cohort.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { Cohort } from "./entities/cohort.entity"; -// import { FieldsModule } from "../fields/fields.module"; -// import { FieldValues } from "../fields/entities/fields-values.entity"; -// import { FieldsService } from "../fields/fields.service"; - +import { FieldsService } from "../fields/fields.service"; +import { FieldValues } from "../fields/entities/fields-values.entity"; const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([Cohort]), + TypeOrmModule.forFeature([FieldValues]), HttpModule, HasuraModule, CacheModule.register({ @@ -21,7 +20,7 @@ const ttl = process.env.TTL as never; }), ], controllers: [CohortController], - providers: [CohortAdapter, CohortService], + providers: [CohortAdapter, CohortService, FieldsService], }) export class CohortModule {} diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 90a8d4f3..69a08ce1 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -24,9 +24,11 @@ import { FieldValues } from "../fields/entities/fields-values.entity"; export class CohortService { private cohort: CohortInterface; + constructor( @InjectRepository(Cohort) private cohortRepository: Repository, + private fieldsService: FieldsService // @InjectRepository(FieldValues) // private fieldsValuesRepository: Repository, // private readonly fieldsService: FieldsService, @@ -217,100 +219,100 @@ export class CohortService { // } } - public async searchCohort( - tenantId: string, - request: any, - cohortSearchDto: CohortSearchDto, - res: any - ) { - try{ - let entityFilter = cohortSearchDto; - let filedsFilter = entityFilter?.filters["fields"]; - //remove fields from filter - delete entityFilter.filters["fields"]; - let newCohortSearchDto = null; - //check fields value present or not - if (filedsFilter) { - //apply filter on fields value - let response_fields_value = - await this.fieldsService.searchFieldValuesFilter(request,filedsFilter); - if (response_fields_value?.data?.errors) { - return res.status(200).send({ - errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, - errorMessage: response_fields_value?.data?.errors[0]?.message, - }); - } else { - //get filter result - let result_FieldValues = response_fields_value?.data?.data?.FieldValues; - //fetch cohot id list - let cohort_id_list = []; - for (let i = 0; i < result_FieldValues.length; i++) { - cohort_id_list.push(result_FieldValues[i].itemId); - } - //remove duplicate entries - cohort_id_list = cohort_id_list.filter( - (item, index) => cohort_id_list.indexOf(item) === index - ); - let cohort_filter = new Object(entityFilter.filters); - cohort_filter["cohortId"] = { - _in: cohort_id_list, - }; - newCohortSearchDto = new CohortSearchDto({ - limit: entityFilter.limit, - page: entityFilter.page, - filters: cohort_filter, - }); - } - } else { - newCohortSearchDto = new CohortSearchDto({ - limit: entityFilter.limit, - page: entityFilter.page, - filters: entityFilter.filters, - }); - } - if (newCohortSearchDto) { - const response = await this.searchCohortQuery( - request, - tenantId, - newCohortSearchDto - ); - if (response?.data?.errors) { - return res.status(200).send({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response?.data?.data?.Cohort; - let cohortResponse = await this.mappedResponse(result); - //const count = cohortResponse.length; - const count = result.length; - //get cohort fields value - let result_data = await this.searchCohortFields( - request, - tenantId, - cohortResponse - ); - return res.status(200).send({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result_data, - }); - } - } else { - return res.status(200).send({ - errorCode: "filter invalid", - errorMessage: "filter invalid", - }); - } - }catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "401", - errorMessage: e, - }); - } - } + // public async searchCohort( + // tenantId: string, + // request: any, + // cohortSearchDto: CohortSearchDto, + // res: any + // ) { + // try{ + // let entityFilter = cohortSearchDto; + // let filedsFilter = entityFilter?.filters["fields"]; + // //remove fields from filter + // delete entityFilter.filters["fields"]; + // let newCohortSearchDto = null; + // //check fields value present or not + // if (filedsFilter) { + // //apply filter on fields value + // let response_fields_value = + // await this.fieldsService.searchFieldValuesFilter(request,filedsFilter); + // if (response_fields_value?.data?.errors) { + // return res.status(200).send({ + // errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, + // errorMessage: response_fields_value?.data?.errors[0]?.message, + // }); + // } else { + // //get filter result + // let result_FieldValues = response_fields_value?.data?.data?.FieldValues; + // //fetch cohot id list + // let cohort_id_list = []; + // for (let i = 0; i < result_FieldValues.length; i++) { + // cohort_id_list.push(result_FieldValues[i].itemId); + // } + // //remove duplicate entries + // cohort_id_list = cohort_id_list.filter( + // (item, index) => cohort_id_list.indexOf(item) === index + // ); + // let cohort_filter = new Object(entityFilter.filters); + // cohort_filter["cohortId"] = { + // _in: cohort_id_list, + // }; + // newCohortSearchDto = new CohortSearchDto({ + // limit: entityFilter.limit, + // page: entityFilter.page, + // filters: cohort_filter, + // }); + // } + // } else { + // newCohortSearchDto = new CohortSearchDto({ + // limit: entityFilter.limit, + // page: entityFilter.page, + // filters: entityFilter.filters, + // }); + // } + // if (newCohortSearchDto) { + // const response = await this.searchCohortQuery( + // request, + // tenantId, + // newCohortSearchDto + // ); + // if (response?.data?.errors) { + // return res.status(200).send({ + // errorCode: response?.data?.errors[0]?.extensions?.code, + // errorMessage: response?.data?.errors[0]?.message, + // }); + // } else { + // let result = response?.data?.data?.Cohort; + // let cohortResponse = await this.mappedResponse(result); + // //const count = cohortResponse.length; + // const count = result.length; + // //get cohort fields value + // let result_data = await this.searchCohortFields( + // request, + // tenantId, + // cohortResponse + // ); + // return res.status(200).send({ + // statusCode: 200, + // message: "Ok.", + // totalCount: count, + // data: result_data, + // }); + // } + // } else { + // return res.status(200).send({ + // errorCode: "filter invalid", + // errorMessage: "filter invalid", + // }); + // } + // }catch (e) { + // console.error(e); + // return new ErrorResponse({ + // errorCode: "401", + // errorMessage: e, + // }); + // } + // } public async mappedResponse(result: any) { const cohortMapping = { From d867bda449d55c150998d6a7abaead4cea826f46 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 19:36:09 +0530 Subject: [PATCH 094/408] add --- src/cohort/cohort.module.ts | 2 + src/cohort/cohort.service.ts | 88 +++++++++++++++++------------------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index f444a5d7..50d74d18 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -7,11 +7,13 @@ import { CohortService } from "./cohort.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { Cohort } from "./entities/cohort.entity"; import { FieldsService } from "../fields/fields.service"; +import { Fields } from "../fields/entities/fields.entity"; import { FieldValues } from "../fields/entities/fields-values.entity"; const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([Cohort]), + TypeOrmModule.forFeature([Fields]), TypeOrmModule.forFeature([FieldValues]), HttpModule, HasuraModule, diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 69a08ce1..c594a609 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -94,55 +94,51 @@ export class CohortService { }); const response = await this.cohortRepository.save(cohortData); - - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } - // else { - // const result = response.data.data.insert_Cohort_one; - // let fieldCreate = true; - // let fieldError = null; - // //create fields values - // let cohortId = result?.cohortId; - // let field_value_array = cohortCreateDto.fieldValues.split("|"); - // if (field_value_array.length > 0) { - // let field_values = []; - // for (let i = 0; i < field_value_array.length; i++) { - // let fieldValues = field_value_array[i].split(":"); - // field_values.push({ - // value: fieldValues[1] ? fieldValues[1] : "", - // itemId: cohortId, - // fieldId: fieldValues[0] ? fieldValues[0] : "", - // createdBy: cohortCreateDto?.createdBy, - // updatedBy: cohortCreateDto?.updatedBy, - // }); - // } + // const result = response.data.data.insert_Cohort_one; + // let fieldCreate = true; + // let fieldError = null; + // //create fields values + let cohortId = response?.cohortId; + + let field_value_array = cohortCreateDto.fieldValues.split("|"); + + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + let fieldValues = field_value_array[i].split(":"); + field_values.push({ + value: fieldValues[1] ? fieldValues[1] : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0] : "", + createdBy: cohortCreateDto?.createdBy, + updatedBy: cohortCreateDto?.updatedBy, + }); + } - // const response_field_values = - // await this.fieldsService.createFieldValuesBulk(field_values); - // if (response_field_values?.data?.errors) { - // fieldCreate = false; - // fieldError = response_field_values?.data; - // } - // } + console.log(field_values); + + // const response_field_values = + // await this.fieldsService.createFieldValuesBulk(field_values); + // if (response_field_values?.data?.errors) { + // fieldCreate = false; + // fieldError = response_field_values?.data; + // } + } - // if (fieldCreate) { - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } else { - // return new ErrorResponse({ - // errorCode: fieldError?.errors[0]?.extensions?.code, - // errorMessage: fieldError?.errors[0]?.message, - // }); - // } - // } + // if (fieldCreate) { + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } else { + // return new ErrorResponse({ + // errorCode: fieldError?.errors[0]?.extensions?.code, + // errorMessage: fieldError?.errors[0]?.message, + // }); + // } + }catch (e) { console.error(e); return new ErrorResponse({ From 2e331a50a19ac991e0cc636e5b973914a0767264 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Sat, 23 Mar 2024 20:21:32 +0530 Subject: [PATCH 095/408] Fix[Attendance API dto fix] --- src/attendance/attendance.service.ts | 10 +++------- src/attendance/dto/attendance.dto.ts | 1 + 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 08d6d194..6ae3c1bd 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -118,8 +118,6 @@ export class AttendanceService { const userId = decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - attendanceDto.createdBy = userId; - attendanceDto.updatedBy = userId; const attendanceToSearch = new AttendanceSearchDto({}); @@ -222,10 +220,8 @@ export class AttendanceService { */ public async createAttendance(request: any, attendanceDto: AttendanceDto) { - console.log("created") try { - - const attendance = this.attendanceRepository.create(attendanceDto); + const attendance = this.attendanceRepository.create(attendanceDto); const result = await this.attendanceRepository.save(attendance); return new SuccessResponse({ @@ -325,7 +321,7 @@ export class AttendanceService { let count = 1; for (const attendance of attendanceData) { - if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance) { + if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance && attendance.contextId) { attendance.tenantId = tenantId; const attendanceRes: any = await this.updateAttendanceRecord( @@ -345,7 +341,7 @@ export class AttendanceService { else { errors.push({ - message: `userId should not be empty null or undefined for record or attendance date should not be of future for ${count} or attendance should be valid enum value[present,absent,halfday]` + message: `userId should not be empty null or undefined for record or attendance date should not be of future for ${count} or attendance should be valid enum value[present,absent,halfday] or contextId should be present` }); count++; diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 65f8377e..226fc27a 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -118,6 +118,7 @@ export class AttendanceDto { description: "The contextId of the attendance", default: "", }) + @IsNotEmpty() @Expose() contextId: string; From 1e1fafa2e4d3901305a986f3389617b5b2282fc6 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 20:27:35 +0530 Subject: [PATCH 096/408] add --- src/fields/fields.service.ts | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 05b7c418..636b8c75 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -175,36 +175,36 @@ export class FieldsService { } } - async createFieldValuesBulk(field_values: any) { - var axios = require("axios"); - - var data_field_values = { - query: `mutation insert_multiple_fieldValues($objects: [FieldValues_insert_input!]!) { - insert_FieldValues(objects: $objects) { - returning { - fieldValuesId - } - } - } - `, - variables: { - objects: field_values, - }, - }; - - var config_field_value = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data_field_values, - }; - - const response = await axios(config_field_value); - return response; - } + // async createFieldValuesBulk(field_values: any) { + // var axios = require("axios"); + + // var data_field_values = { + // query: `mutation insert_multiple_fieldValues($objects: [FieldValues_insert_input!]!) { + // insert_FieldValues(objects: $objects) { + // returning { + // fieldValuesId + // } + // } + // } + // `, + // variables: { + // objects: field_values, + // }, + // }; + + // var config_field_value = { + // method: "post", + // url: process.env.REGISTRYHASURA, + // headers: { + // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + // "Content-Type": "application/json", + // }, + // data: data_field_values, + // }; + + // const response = await axios(config_field_value); + // return response; + // } public async mappedResponse(result: any) { From e19f3b829ef61bbe353c2d590f3dfc2f5f58e965 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 20:30:39 +0530 Subject: [PATCH 097/408] add --- src/cohort/cohort.service.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 56e92a1f..ad64f28f 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -15,7 +15,6 @@ import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { FieldsService } from "src/adapters/hasura/services/fields.service"; -// import { FieldValues } from "src/fields/entities/field-values.entity"; import { response } from "express"; import APIResponse from "src/utils/response"; @@ -25,9 +24,7 @@ export class CohortService { constructor( @InjectRepository(Cohort) - // @InjectRepository(FieldValues) private cohortRepository: Repository, - // private readonly fieldsService: FieldsService ) {} public async getCohort( @@ -44,7 +41,7 @@ export class CohortService { }); if (!cohort) { return response - .status(HttpStatus.NOT_FOUND) // Change status to 404 Not Found + .status(HttpStatus.NOT_FOUND) .send( APIResponse.error( apiId, @@ -58,7 +55,7 @@ export class CohortService { return response.status(HttpStatus.OK).send( APIResponse.success( apiId, - cohort, // Send cohort data + cohort, "Cohort Retrieved Successfully" ) ); From f227c2e56e6a40fee73b366319dcf0059642c9d1 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 20:36:33 +0530 Subject: [PATCH 098/408] pull updated code --- src/fields/fields.controller.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index a73618a3..cf523523 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -45,6 +45,10 @@ export class FieldsController { //fields //create fields @Post() + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Fields has been created successfully." }) + @ApiBody({ type: FieldsDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", @@ -67,6 +71,11 @@ export class FieldsController { //search @Post("/search") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Fields list." }) + @ApiBody({ type: FieldsSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) From 613c70f90ecc03375b7f68532c94e60604a8e2ee Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 21:18:25 +0530 Subject: [PATCH 099/408] add --- src/cohort/cohort.service.ts | 98 ++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 56 deletions(-) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index c594a609..efd0c5f4 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -24,7 +24,7 @@ import { FieldValues } from "../fields/entities/fields-values.entity"; export class CohortService { private cohort: CohortInterface; - + constructor( @InjectRepository(Cohort) private cohortRepository: Repository, @@ -32,7 +32,7 @@ export class CohortService { // @InjectRepository(FieldValues) // private fieldsValuesRepository: Repository, // private readonly fieldsService: FieldsService, - ) {} + ) { } public async getCohort( tenantId: string, @@ -81,65 +81,51 @@ export class CohortService { } public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { - try{ + try { const cohortData: any = {}; Object.keys(cohortCreateDto).forEach((e) => { - if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { - if (Array.isArray(cohortCreateDto[e])) { - cohortData[e] = JSON.stringify(cohortCreateDto[e]); - } else { - cohortData[e] = cohortCreateDto[e]; - } + if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { + if (Array.isArray(cohortCreateDto[e])) { + cohortData[e] = JSON.stringify(cohortCreateDto[e]); + } else { + cohortData[e] = cohortCreateDto[e]; } + } }); const response = await this.cohortRepository.save(cohortData); - // const result = response.data.data.insert_Cohort_one; - // let fieldCreate = true; - // let fieldError = null; - // //create fields values - let cohortId = response?.cohortId; - - let field_value_array = cohortCreateDto.fieldValues.split("|"); - - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - field_values.push({ - value: fieldValues[1] ? fieldValues[1] : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0] : "", - createdBy: cohortCreateDto?.createdBy, - updatedBy: cohortCreateDto?.updatedBy, - }); - } + let cohortId = response?.cohortId; - console.log(field_values); - - // const response_field_values = - // await this.fieldsService.createFieldValuesBulk(field_values); - // if (response_field_values?.data?.errors) { - // fieldCreate = false; - // fieldError = response_field_values?.data; - // } - } + let field_value_array = cohortCreateDto.fieldValues.split("|"); + + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + + let fieldValues = field_value_array[i].split(":"); + let fieldValueDto: FieldValuesDto = { + fieldValuesId: "", // Provide a value for fieldValuesId + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortCreateDto?.createdBy, + updatedBy: cohortCreateDto?.updatedBy, + createdAt: new Date().toISOString(), // Provide appropriate values for createdAt and updatedAt + updatedAt: new Date().toISOString(), + }; - // if (fieldCreate) { - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } else { - // return new ErrorResponse({ - // errorCode: fieldError?.errors[0]?.extensions?.code, - // errorMessage: fieldError?.errors[0]?.message, - // }); - // } + await this.fieldsService.createFieldValues(request, fieldValueDto); + } + } - }catch (e) { + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: response, + }); + + } catch (e) { console.error(e); return new ErrorResponse({ errorCode: "401", @@ -159,15 +145,15 @@ export class CohortService { if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" ) { if (Array.isArray(cohortUpdateDto[e])) { - cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); } else { - cohortUpdateData[e] = cohortUpdateDto[e]; + cohortUpdateData[e] = cohortUpdateDto[e]; } } }); - - const response = await this.cohortRepository.update(cohortId ,cohortUpdateData); + + const response = await this.cohortRepository.update(cohortId, cohortUpdateData); // if (response?.data?.errors) { // return new ErrorResponse({ @@ -309,7 +295,7 @@ export class CohortService { // }); // } // } - + public async mappedResponse(result: any) { const cohortMapping = { tenantId: result?.tenantId ? `${result.tenantId}` : "", From 3ca4ec463630cf53ef89d9c4bebe4e3846f64699 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Sat, 23 Mar 2024 21:36:42 +0530 Subject: [PATCH 100/408] Fix[import change for User entity] --- src/attendance/dto/attendance.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 226fc27a..ee9af021 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -3,7 +3,7 @@ import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, ValidationArg import { Exclude, Expose, Transform } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsObject } from 'class-validator'; -import { User } from 'src/user/entities/user-create-entity'; +import { User } from 'src/user/entities/user-entity'; import { format, isAfter } from 'date-fns'; // Import isAfter function from date-fns import { HttpException, HttpStatus } from '@nestjs/common'; From 352ad4fbeb97dbce93aa31f5f5bf046f7c7fd4b5 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 23 Mar 2024 21:45:33 +0530 Subject: [PATCH 101/408] fields Value changes --- src/fields/entities/fields-values.entity.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/fields/entities/fields-values.entity.ts b/src/fields/entities/fields-values.entity.ts index 84eeedcd..0f4f7d86 100644 --- a/src/fields/entities/fields-values.entity.ts +++ b/src/fields/entities/fields-values.entity.ts @@ -1,6 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm'; -// import { Field } from './Field'; // Assuming you have a Field entity defined - +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; @Entity({ name: 'FieldValues' }) export class FieldValues { From 2a60ac1beccc78958c17343ed114397fe78e0f16 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Sat, 23 Mar 2024 23:59:39 +0530 Subject: [PATCH 102/408] Fix[latest pull] --- src/cohort/cohort.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index ad64f28f..531e9852 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -24,6 +24,7 @@ export class CohortService { constructor( @InjectRepository(Cohort) + private cohortRepository: Repository, ) {} From 6a6a536a3f8cfd545db7a72517d7694ff3fc51d6 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sun, 24 Mar 2024 01:32:13 +0530 Subject: [PATCH 103/408] add --- src/cohort/cohort.controller.ts | 41 +++-- src/cohort/cohort.service.ts | 262 +++++++++++++------------------- src/fields/fields.service.ts | 63 ++++---- 3 files changed, 161 insertions(+), 205 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index f6dc8532..c777df99 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -103,27 +103,26 @@ export class CohortController { } // search - // @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Cohort list." }) - // @ApiBody({ type: CohortSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - // @SerializeOptions({ - // strategy: "excludeAll", - // }) - // @ApiHeader({ - // name: "tenantid", - // }) - // public async searchCohort( - // @Headers() headers, - // @Req() request: Request, - // @Body() cohortSearchDto: CohortSearchDto, - // @Res() res: Response - // ) { - // let tenantid = headers["tenantid"]; - // return this.cohortService.searchCohort(tenantid, request, cohortSearchDto, res); - // } + @Post("/search") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Cohort list." }) + @ApiBody({ type: CohortSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async searchCohort( + @Headers() headers, + @Req() request: Request, + @Body() cohortSearchDto: CohortSearchDto, + ) { + let tenantid = headers["tenantid"]; + return this.cohortService.searchCohort(tenantid, request, cohortSearchDto); + } //update @Put("/:id") diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index efd0c5f4..274e9994 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -118,7 +118,7 @@ export class CohortService { await this.fieldsService.createFieldValues(request, fieldValueDto); } } - + return new SuccessResponse({ statusCode: 200, message: "Ok.", @@ -139,162 +139,118 @@ export class CohortService { request: any, cohortUpdateDto: CohortCreateDto ) { - const cohortUpdateData: any = {}; - - Object.keys(cohortUpdateDto).forEach((e) => { - if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" - ) { - if (Array.isArray(cohortUpdateDto[e])) { - cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); - } else { - cohortUpdateData[e] = cohortUpdateDto[e]; + try { + const cohortUpdateData: any = {}; + + Object.keys(cohortUpdateDto).forEach((e) => { + if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" + ) { + if (Array.isArray(cohortUpdateDto[e])) { + cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + } else { + cohortUpdateData[e] = cohortUpdateDto[e]; + } + } + }); + + const response = await this.cohortRepository.update(cohortId, cohortUpdateData); + console.log(response); + + + let field_value_array = cohortUpdateDto.fieldValues.split("|"); + + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + + let fieldValues = field_value_array[i].split(":"); + let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + const rowid = fieldVauesRowId.fieldValuesId; + + let fieldValueDto: FieldValuesDto = { + fieldValuesId: rowid, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.updateFieldValues(rowid, fieldValueDto); } } - }); - - - const response = await this.cohortRepository.update(cohortId, cohortUpdateData); - - // if (response?.data?.errors) { - // return new ErrorResponse({ - // errorCode: response?.data?.errors[0]?.extensions?.code, - // errorMessage: response?.data?.errors[0]?.message, - // }); - // } - // else { - // let result = response.data.update_Cohort_by_pk; - // let fieldCreate = true; - // let fieldError = []; - // //update fields values - // let field_value_array = cohortUpdateDto.fieldValues.split("|"); - // if (field_value_array.length > 0) { - // for (let i = 0; i < field_value_array.length; i++) { - // let fieldValues = field_value_array[i].split(":"); - // //update values - // let fieldValuesUpdate = new FieldValuesDto({ - // value: fieldValues[1] ? fieldValues[1] : "", - // }); - - // const response_field_values = - // await this.fieldsService.updateFieldValues( - // fieldValues[0] ? fieldValues[0] : "", - // fieldValuesUpdate - // ); - // if (response_field_values?.data?.errors) { - // fieldCreate = false; - // fieldError.push(response_field_values?.data); - // } - // } - // } - // if (fieldCreate) { - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } else { - // return new ErrorResponse({ - // errorCode: "filed value update error", - // errorMessage: JSON.stringify(fieldError), - // }); - // } - // } + + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: { + rowCount: response.affected, + } + }); + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, + }); + } } - // public async searchCohort( - // tenantId: string, - // request: any, - // cohortSearchDto: CohortSearchDto, - // res: any - // ) { - // try{ - // let entityFilter = cohortSearchDto; - // let filedsFilter = entityFilter?.filters["fields"]; - // //remove fields from filter - // delete entityFilter.filters["fields"]; - // let newCohortSearchDto = null; - // //check fields value present or not - // if (filedsFilter) { - // //apply filter on fields value - // let response_fields_value = - // await this.fieldsService.searchFieldValuesFilter(request,filedsFilter); - // if (response_fields_value?.data?.errors) { - // return res.status(200).send({ - // errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, - // errorMessage: response_fields_value?.data?.errors[0]?.message, - // }); - // } else { - // //get filter result - // let result_FieldValues = response_fields_value?.data?.data?.FieldValues; - // //fetch cohot id list - // let cohort_id_list = []; - // for (let i = 0; i < result_FieldValues.length; i++) { - // cohort_id_list.push(result_FieldValues[i].itemId); - // } - // //remove duplicate entries - // cohort_id_list = cohort_id_list.filter( - // (item, index) => cohort_id_list.indexOf(item) === index - // ); - // let cohort_filter = new Object(entityFilter.filters); - // cohort_filter["cohortId"] = { - // _in: cohort_id_list, - // }; - // newCohortSearchDto = new CohortSearchDto({ - // limit: entityFilter.limit, - // page: entityFilter.page, - // filters: cohort_filter, - // }); - // } - // } else { - // newCohortSearchDto = new CohortSearchDto({ - // limit: entityFilter.limit, - // page: entityFilter.page, - // filters: entityFilter.filters, - // }); - // } - // if (newCohortSearchDto) { - // const response = await this.searchCohortQuery( - // request, - // tenantId, - // newCohortSearchDto - // ); - // if (response?.data?.errors) { - // return res.status(200).send({ - // errorCode: response?.data?.errors[0]?.extensions?.code, - // errorMessage: response?.data?.errors[0]?.message, - // }); - // } else { - // let result = response?.data?.data?.Cohort; - // let cohortResponse = await this.mappedResponse(result); - // //const count = cohortResponse.length; - // const count = result.length; - // //get cohort fields value - // let result_data = await this.searchCohortFields( - // request, - // tenantId, - // cohortResponse - // ); - // return res.status(200).send({ - // statusCode: 200, - // message: "Ok.", - // totalCount: count, - // data: result_data, - // }); - // } - // } else { - // return res.status(200).send({ - // errorCode: "filter invalid", - // errorMessage: "filter invalid", - // }); - // } - // }catch (e) { - // console.error(e); - // return new ErrorResponse({ - // errorCode: "401", - // errorMessage: e, - // }); - // } - // } + public async searchCohort( + tenantId: string, + request: any, + cohortSearchDto: CohortSearchDto, + ) { + try { + + + let { limit, page, filters } = cohortSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + else { + whereClause['tenantId'] = tenantId; + } + + + + const [results, totalCount] = await this.cohortRepository.findAndCount({ + where: whereClause, + skip: offset, + }); + + console.log(results); + + return new SuccessResponse({ + statusCode: 200, + message: 'Ok.', + totalCount, + data: results, + }); + + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, + }); + } + } public async mappedResponse(result: any) { const cohortMapping = { diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 636b8c75..66de19d2 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -175,38 +175,39 @@ export class FieldsService { } } - // async createFieldValuesBulk(field_values: any) { - // var axios = require("axios"); - - // var data_field_values = { - // query: `mutation insert_multiple_fieldValues($objects: [FieldValues_insert_input!]!) { - // insert_FieldValues(objects: $objects) { - // returning { - // fieldValuesId - // } - // } - // } - // `, - // variables: { - // objects: field_values, - // }, - // }; - - // var config_field_value = { - // method: "post", - // url: process.env.REGISTRYHASURA, - // headers: { - // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - // "Content-Type": "application/json", - // }, - // data: data_field_values, - // }; - - // const response = await axios(config_field_value); - // return response; - // } - + async searchFieldValueId(cohortId: string, fieldId: string){ + const response = await this.fieldsValuesRepository.findOne({ + where: { itemId: cohortId, fieldId: fieldId }, + }); + return response; + } + async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { + + try { + const fieldsData: any = {}; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + fieldsData[e] = JSON.stringify(fieldValuesDto[e]); + } else { + fieldsData[e] = fieldValuesDto[e]; + } + } + }); + const response = await this.fieldsValuesRepository.update(id, fieldValuesDto); + + return response; + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + public async mappedResponse(result: any) { const fieldValueResponse = result.map((item: any) => { const fieldValueMapping = { From 5ccc47835939976a12eb223fc4c9fd1b35b25791 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sun, 24 Mar 2024 01:37:31 +0530 Subject: [PATCH 104/408] add --- src/user/user.module.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/user/user.module.ts b/src/user/user.module.ts index d1a30ab0..e113ad28 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -28,4 +28,3 @@ const ttl = process.env.TTL as never; providers: [UserAdapter,UserService], }) export class UserModule {} - From 0cdc1c694a6290407027a3d14430bcf7b252b17f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sun, 24 Mar 2024 02:46:04 +0530 Subject: [PATCH 105/408] add --- package-lock.json | 7169 +++++++++++++++++++++++----------- src/cohort/cohort.service.ts | 52 +- src/fields/fields.service.ts | 45 +- 3 files changed, 4864 insertions(+), 2402 deletions(-) diff --git a/package-lock.json b/package-lock.json index 842f7f9a..95a563a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,90 @@ { "name": "shiksha-backend-v2", "version": "0.0.1", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@ampproject/remapping": { + "packages": { + "": { + "name": "shiksha-backend-v2", + "version": "0.0.1", + "license": "UNLICENSED", + "dependencies": { + "@nestjs/axios": "^0.0.7", + "@nestjs/common": "^8.4.2", + "@nestjs/config": "^2.0.0", + "@nestjs/core": "^8.0.0", + "@nestjs/jwt": "^8.0.0", + "@nestjs/platform-express": "^8.0.0", + "@nestjs/schedule": "^1.1.0", + "@nestjs/swagger": "^5.2.0", + "@nestjs/typeorm": "^10.0.2", + "axios": "^0.26.1", + "cache-manager": "^3.6.1", + "class-transformer": "^0.5.1", + "class-validator": "^0.13.2", + "date-fns": "^3.6.0", + "dotenv": "^16.0.0", + "express": "^4.17.3", + "form-data": "^4.0.0", + "graphql-tag": "^2.12.6", + "jwt-decode": "^3.1.2", + "moment": "^2.29.3", + "multer": "^1.4.4", + "node-cron": "^3.0.1", + "node-schedule": "^2.1.0", + "object-resolve-path": "^1.1.1", + "pg": "^8.11.3", + "reflect-metadata": "^0.1.13", + "rimraf": "^3.0.2", + "rxjs": "^7.2.0", + "swagger-ui-express": "^4.3.0", + "templates.js": "^0.3.11", + "typeorm": "^0.3.20" + }, + "devDependencies": { + "@nestjs/cli": "^8.0.0", + "@nestjs/schematics": "^8.0.0", + "@nestjs/testing": "^8.0.0", + "@types/cache-manager": "^3.4.3", + "@types/cron": "^1.7.3", + "@types/express": "^4.17.13", + "@types/jest": "27.4.1", + "@types/node": "^16.0.0", + "@types/supertest": "^2.0.11", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^27.2.5", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "supertest": "^6.1.3", + "ts-jest": "^27.0.3", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "^3.10.1", + "typescript": "^4.3.5" + } + }, + "node_modules/@ampproject/remapping": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/trace-mapping": "^0.3.0" + }, + "engines": { + "node": ">=6.0.0" } }, - "@angular-devkit/core": { + "node_modules/@angular-devkit/core": { "version": "13.2.6", "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.6.tgz", "integrity": "sha512-8h2mWdBTN/dYwZuzKMg2IODlOWMdbJcpQG4XVrkk9ejCPP+3aX5Aa3glCe/voN6eBNiRfs8YDM0jxmpN2aWVtg==", "dev": true, - "requires": { + "dependencies": { "ajv": "8.9.0", "ajv-formats": "2.1.1", "fast-json-stable-stringify": "2.1.0", @@ -26,101 +92,120 @@ "rxjs": "6.6.7", "source-map": "0.7.3" }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/core/node_modules/ajv": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", + "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/core/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { "ajv": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", - "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - } - } - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "optional": true } } }, - "@angular-devkit/schematics": { + "node_modules/@angular-devkit/core/node_modules/ajv-formats/node_modules/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/core/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@angular-devkit/core/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/schematics": { "version": "13.2.6", "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.6.tgz", "integrity": "sha512-mPgSqdnZRuPSMeUA+T+mwVCrq2yhXpcYm1/Rjbhy09CyHs4wSrFv21WHCrE6shlvXpcmwr0n+I0DIeagAPmjUA==", "dev": true, - "requires": { + "dependencies": { "@angular-devkit/core": "13.2.6", "jsonc-parser": "3.0.0", "magic-string": "0.25.7", "ora": "5.4.1", "rxjs": "6.6.7" }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "@angular-devkit/schematics-cli": { + "node_modules/@angular-devkit/schematics-cli": { "version": "13.2.6", "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-13.2.6.tgz", "integrity": "sha512-VdMLn4DoTswjk+1RL+pod8EwLkzh8pMT2OBJ9dhsITru1sr0/2nhsqRwZzZylAXjrFwdfPj1E/vfcAfSkmMGvw==", "dev": true, - "requires": { + "dependencies": { "@angular-devkit/core": "13.2.6", "@angular-devkit/schematics": "13.2.6", "ansi-colors": "4.1.1", @@ -128,52 +213,85 @@ "minimist": "1.2.5", "symbol-observable": "4.0.0" }, + "bin": { + "schematics": "bin/schematics.js" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, "dependencies": { - "inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - } - } + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" } }, - "@babel/code-frame": { + "node_modules/@angular-devkit/schematics/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@babel/code-frame": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dev": true, - "requires": { + "dependencies": { "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/compat-data": { + "node_modules/@babel/compat-data": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/core": { + "node_modules/@babel/core": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.7.tgz", "integrity": "sha512-djHlEfFHnSnTAcPb7dATbiM5HxGOP98+3JLBZtjRb5I7RXrw7kFRoG2dXM8cm3H+o11A8IFH/uprmJpwFynRNQ==", "dev": true, - "requires": { + "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.7", @@ -190,107 +308,141 @@ "json5": "^2.1.2", "semver": "^6.3.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "@babel/generator": { + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-compilation-targets": { + "node_modules/@babel/helper-compilation-targets": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", "dev": true, - "requires": { + "dependencies": { "@babel/compat-data": "^7.17.7", "@babel/helper-validator-option": "^7.16.7", "browserslist": "^4.17.5", "semver": "^6.3.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-environment-visitor": { + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-function-name": { + "node_modules/@babel/helper-function-name": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-get-function-arity": "^7.16.7", "@babel/template": "^7.16.7", "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-get-function-arity": { + "node_modules/@babel/helper-get-function-arity": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-hoist-variables": { + "node_modules/@babel/helper-hoist-variables": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-module-imports": { + "node_modules/@babel/helper-module-imports": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-module-transforms": { + "node_modules/@babel/helper-module-transforms": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", "@babel/helper-simple-access": "^7.17.7", @@ -299,258 +451,346 @@ "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.3", "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-plugin-utils": { + "node_modules/@babel/helper-plugin-utils": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helper-simple-access": { + "node_modules/@babel/helper-simple-access": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-split-export-declaration": { + "node_modules/@babel/helper-split-export-declaration": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-validator-identifier": { + "node_modules/@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helper-validator-option": { + "node_modules/@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helpers": { + "node_modules/@babel/helpers": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.7.tgz", "integrity": "sha512-TKsj9NkjJfTBxM7Phfy7kv6yYc4ZcOo+AaWGqQOKTPDOmcGkIFb5xNA746eKisQkm4yavUYh4InYM9S+VnO01w==", "dev": true, - "requires": { + "dependencies": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.3", "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/highlight": { + "node_modules/@babel/highlight": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" } }, - "@babel/parser": { + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.7.tgz", "integrity": "sha512-bm3AQf45vR4gKggRfvJdYJ0gFLoCbsPxiFLSH6hTVYABptNHY6l9NrhnucVjQ/X+SPtLANT9lc0fFhikj+VBRA==", - "dev": true + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } }, - "@babel/plugin-syntax-async-generators": { + "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-bigint": { + "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-class-properties": { + "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-import-meta": { + "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-json-strings": { + "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-logical-assignment-operators": { + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-nullish-coalescing-operator": { + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-numeric-separator": { + "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-object-rest-spread": { + "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-catch-binding": { + "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-chaining": { + "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-top-level-await": { + "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-typescript": { + "node_modules/@babel/plugin-syntax-typescript": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/template": { + "node_modules/@babel/template": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/traverse": { + "node_modules/@babel/traverse": { "version": "7.17.3", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.3", "@babel/helper-environment-visitor": "^7.16.7", @@ -562,52 +802,65 @@ "debug": "^4.1.0", "globals": "^11.1.0" }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } + "engines": { + "node": ">=6.9.0" } }, - "@babel/types": { + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { "version": "7.17.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@bcoe/v8-coverage": { + "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@cspotcode/source-map-consumer": { + "node_modules/@cspotcode/source-map-consumer": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true + "devOptional": true, + "engines": { + "node": ">= 12" + } }, - "@cspotcode/source-map-support": { + "node_modules/@cspotcode/source-map-support": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "dev": true, - "requires": { + "devOptional": true, + "dependencies": { "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" } }, - "@eslint/eslintrc": { + "node_modules/@eslint/eslintrc": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, - "requires": { + "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.3.1", @@ -617,30 +870,36 @@ "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "@humanwhocodes/config-array": { + "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "dev": true, - "requires": { + "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" } }, - "@humanwhocodes/object-schema": { + "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "@isaacs/cliui": { + "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "requires": { + "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", @@ -648,104 +907,145 @@ "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "@istanbuljs/load-nyc-config": { + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "requires": { + "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - } + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" } }, - "@istanbuljs/schema": { + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "@jest/console": { + "node_modules/@jest/console": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", @@ -753,21 +1053,22 @@ "jest-util": "^27.5.1", "slash": "^3.0.0" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/core": { + "node_modules/@jest/console/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@jest/core": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", "dev": true, - "requires": { + "dependencies": { "@jest/console": "^27.5.1", "@jest/reporters": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -797,41 +1098,51 @@ "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "@jest/environment": { + "node_modules/@jest/core/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@jest/environment": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", "dev": true, - "requires": { + "dependencies": { "@jest/fake-timers": "^27.5.1", "@jest/types": "^27.5.1", "@types/node": "*", "jest-mock": "^27.5.1" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/fake-timers": { + "node_modules/@jest/environment/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@jest/fake-timers": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "@sinonjs/fake-timers": "^8.0.1", "@types/node": "*", @@ -839,32 +1150,36 @@ "jest-mock": "^27.5.1", "jest-util": "^27.5.1" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/globals": { + "node_modules/@jest/fake-timers/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@jest/globals": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^27.5.1", "@jest/types": "^27.5.1", "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/reporters": { + "node_modules/@jest/reporters": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", "dev": true, - "requires": { + "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -891,56 +1206,74 @@ "terminal-link": "^2.0.0", "v8-to-istanbul": "^8.1.0" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "@jest/source-map": { + "node_modules/@jest/reporters/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", "dev": true, - "requires": { + "dependencies": { "callsites": "^3.0.0", "graceful-fs": "^4.2.9", "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/test-result": { + "node_modules/@jest/test-result": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", "dev": true, - "requires": { + "dependencies": { "@jest/console": "^27.5.1", "@jest/types": "^27.5.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/test-sequencer": { + "node_modules/@jest/test-sequencer": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", "dev": true, - "requires": { + "dependencies": { "@jest/test-result": "^27.5.1", "graceful-fs": "^4.2.9", "jest-haste-map": "^27.5.1", "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/transform": { + "node_modules/@jest/transform": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.1.0", "@jest/types": "^27.5.1", "babel-plugin-istanbul": "^6.1.1", @@ -956,75 +1289,85 @@ "slash": "^3.0.0", "source-map": "^0.6.1", "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jest/types": { + "node_modules/@jest/types": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", "dev": true, - "requires": { + "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^16.0.0", "chalk": "^4.0.0" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jridgewell/resolve-uri": { + "node_modules/@jest/types/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@jridgewell/resolve-uri": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.0.0" + } }, - "@jridgewell/sourcemap-codec": { + "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", "dev": true }, - "@jridgewell/trace-mapping": { + "node_modules/@jridgewell/trace-mapping": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "@nestjs/axios": { + "node_modules/@nestjs/axios": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.0.7.tgz", "integrity": "sha512-at8nj+1Nb8UleHcIN5QqZYeWX54m4m9s9gxzVE1qWy00neX2rg0+h2TfbWsnDi2tc23zIxqexanxMOJZbzO0CA==", - "requires": { + "dependencies": { "axios": "0.26.0" }, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/@nestjs/axios/node_modules/axios": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", + "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", "dependencies": { - "axios": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", - "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", - "requires": { - "follow-redirects": "^1.14.8" - } - } + "follow-redirects": "^1.14.8" } }, - "@nestjs/cli": { + "node_modules/@nestjs/cli": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-8.2.3.tgz", "integrity": "sha512-p//DACefn40VClXroxzS+2pkSdaXYvKKcr4bFOUBMTdJqT9he+U9ifcJUkg/h1bFU/Y8SS2cUsTyl0ZBHHHRcw==", "dev": true, - "requires": { + "dependencies": { "@angular-devkit/core": "13.2.6", "@angular-devkit/schematics": "13.2.6", "@angular-devkit/schematics-cli": "13.2.6", @@ -1048,46 +1391,82 @@ "webpack": "5.70.0", "webpack-node-externals": "3.0.0" }, + "bin": { + "nest": "bin/nest.js" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0" + } + }, + "node_modules/@nestjs/cli/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "@nestjs/common": { + "node_modules/@nestjs/common": { "version": "8.4.3", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-8.4.3.tgz", "integrity": "sha512-QIhWykB7IPOwHQB/K9wMwmQKibQ5dhg9dt8ySOoD36uFFwN3RJQelzMFF9Rtu7hrMPk6pSyismEUKQ8BZMUD9w==", - "requires": { + "dependencies": { "axios": "0.26.1", "iterare": "1.2.1", "tslib": "2.3.1", "uuid": "8.3.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "cache-manager": "*", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "cache-manager": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } } }, - "@nestjs/config": { + "node_modules/@nestjs/config": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.0.0.tgz", "integrity": "sha512-Hi1k/1S5ogsS5c0OtNm72thiLSngijOaLDFaGI5ZPxNGpF23lctPg6ox3pYIOhXVRX/u+eiUIp71gswH2k8YNw==", - "requires": { + "dependencies": { "dotenv": "16.0.0", "dotenv-expand": "8.0.2", "lodash": "4.17.21", "uuid": "8.3.2" + }, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^6.0.0 || ^7.2.0" } }, - "@nestjs/core": { + "node_modules/@nestjs/core": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-8.4.1.tgz", "integrity": "sha512-JUV2cy/5z8MS2SRwszLmyOCclMMlyumxIbC1YFFlnSInhu7ODhrHLIMztyGmyAIuaehbOnyXPtHkjl01rHxc5w==", - "requires": { + "hasInstallScript": true, + "dependencies": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", @@ -1095,277 +1474,436 @@ "path-to-regexp": "3.2.0", "tslib": "2.3.1", "uuid": "8.3.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0", + "@nestjs/microservices": "^8.0.0", + "@nestjs/platform-express": "^8.0.0", + "@nestjs/websockets": "^8.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } } }, - "@nestjs/jwt": { + "node_modules/@nestjs/jwt": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-8.0.0.tgz", "integrity": "sha512-fz2LQgYY2zmuD8S+8UE215anwKyXlnB/1FwJQLVR47clNfMeFMK8WCxmn6xdPhF5JKuV1crO6FVabb1qWzDxqQ==", - "requires": { + "dependencies": { "@types/jsonwebtoken": "8.5.4", "jsonwebtoken": "8.5.1" + }, + "peerDependencies": { + "@nestjs/common": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "@nestjs/mapped-types": { + "node_modules/@nestjs/mapped-types": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz", - "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==" + "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==", + "peerDependencies": { + "@nestjs/common": "^7.0.8 || ^8.0.0", + "class-transformer": "^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0", + "class-validator": "^0.11.1 || ^0.12.0 || ^0.13.0", + "reflect-metadata": "^0.1.12" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } }, - "@nestjs/platform-express": { + "node_modules/@nestjs/platform-express": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-8.4.1.tgz", "integrity": "sha512-c18zuhoegJsS1vZueGaNyvU8mLyFtS+6FJ2WAzDOXNpchpq0okrEPdKBifIisWuxgffQYKIufoK73vEfXSfDLg==", - "requires": { + "dependencies": { "body-parser": "1.19.2", "cors": "2.8.5", "express": "4.17.3", "multer": "1.4.4", "tslib": "2.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0", + "@nestjs/core": "^8.0.0" } }, - "@nestjs/schedule": { + "node_modules/@nestjs/schedule": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-1.1.0.tgz", "integrity": "sha512-0QpbwClUildXqlyoaygG+aIQZNNMv31XDyQxX+Ob1zw/3I8+AVrDlBwZHQ+tlhIcJFR8aG+VTH8xwIjXwtS1UA==", - "requires": { + "dependencies": { "cron": "1.8.2", "uuid": "8.3.2" + }, + "peerDependencies": { + "@nestjs/common": "^6.10.11 || ^7.0.0 || ^8.0.0", + "@nestjs/core": "^7.0.0 || ^8.0.0", + "reflect-metadata": "^0.1.12" } }, - "@nestjs/schematics": { + "node_modules/@nestjs/schematics": { "version": "8.0.8", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-8.0.8.tgz", "integrity": "sha512-xIIb5YnMQN/OJQ68+MCapy2bXvTxSWgINoqQbyZWkLL/yTIuROvZCdtV850NPGyr7f7l93VBP0ZPitbFIexy3Q==", "dev": true, - "requires": { + "dependencies": { "@angular-devkit/core": "13.2.5", "@angular-devkit/schematics": "13.2.5", "fs-extra": "10.0.1", "jsonc-parser": "3.0.0", "pluralize": "8.0.0" }, + "peerDependencies": { + "typescript": "^3.4.5 || ^4.3.5" + } + }, + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { + "version": "13.2.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.5.tgz", + "integrity": "sha512-WuWp/1R0FtCHPBcJLF13lTLHETtDGFUX0ULfGPRaYB5OVCSQcovVp5UbZTTy/Ss3ub3EOEmJlU8kMJfBrWuq+A==", + "dev": true, "dependencies": { - "@angular-devkit/core": { - "version": "13.2.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.5.tgz", - "integrity": "sha512-WuWp/1R0FtCHPBcJLF13lTLHETtDGFUX0ULfGPRaYB5OVCSQcovVp5UbZTTy/Ss3ub3EOEmJlU8kMJfBrWuq+A==", - "dev": true, - "requires": { - "ajv": "8.9.0", - "ajv-formats": "2.1.1", - "fast-json-stable-stringify": "2.1.0", - "magic-string": "0.25.7", - "rxjs": "6.6.7", - "source-map": "0.7.3" - } - }, - "@angular-devkit/schematics": { - "version": "13.2.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.5.tgz", - "integrity": "sha512-kAye6VYiF9JQAoeO+BYhy8eT2QOmhB+WLziRjXoFCBxh5+yXTygTVfs9fD5jmIpHmeu4hd2ErSh69yT5xWcD9g==", - "dev": true, - "requires": { - "@angular-devkit/core": "13.2.5", - "jsonc-parser": "3.0.0", - "magic-string": "0.25.7", - "ora": "5.4.1", - "rxjs": "6.6.7" - } - }, + "ajv": "8.9.0", + "ajv-formats": "2.1.1", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { + "version": "13.2.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.5.tgz", + "integrity": "sha512-kAye6VYiF9JQAoeO+BYhy8eT2QOmhB+WLziRjXoFCBxh5+yXTygTVfs9fD5jmIpHmeu4hd2ErSh69yT5xWcD9g==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "13.2.5", + "jsonc-parser": "3.0.0", + "magic-string": "0.25.7", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@nestjs/schematics/node_modules/ajv": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", + "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@nestjs/schematics/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { "ajv": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", - "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - } - } - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "optional": true } } }, - "@nestjs/swagger": { + "node_modules/@nestjs/schematics/node_modules/ajv-formats/node_modules/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@nestjs/schematics/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@nestjs/schematics/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nestjs/schematics/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@nestjs/swagger": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-5.2.1.tgz", "integrity": "sha512-7dNa08WCnTsW/oAk3Ujde+z64JMfNm19DhpXasFR8oJp/9pggYAbYU927HpA+GJsSFJX6adjIRZsCKUqaGWznw==", - "requires": { + "dependencies": { "@nestjs/mapped-types": "1.0.1", "lodash": "4.17.21", "path-to-regexp": "3.2.0" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0", + "@nestjs/core": "^8.0.0", + "fastify-swagger": "*", + "reflect-metadata": "^0.1.12", + "swagger-ui-express": "*" + }, + "peerDependenciesMeta": { + "fastify-swagger": { + "optional": true + }, + "swagger-ui-express": { + "optional": true + } } }, - "@nestjs/testing": { + "node_modules/@nestjs/testing": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-8.4.1.tgz", "integrity": "sha512-LOvsLuNh2eRwAtyeoIZWmUZ08wt7QrPrKQujWuRyv+vBYtC+FLHjqreWLpwG2yulNEoQs9Qlr2ubPvFGT1953g==", "dev": true, - "requires": { + "dependencies": { "optional": "0.1.4", "tslib": "2.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0", + "@nestjs/core": "^8.0.0", + "@nestjs/microservices": "^8.0.0", + "@nestjs/platform-express": "^8.0.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + } } }, - "@nestjs/typeorm": { + "node_modules/@nestjs/typeorm": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", - "requires": { + "dependencies": { "uuid": "9.0.1" }, - "dependencies": { - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - } - } - }, - "@nodelib/fs.scandir": { + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.2.0", + "typeorm": "^0.3.0" + } + }, + "node_modules/@nestjs/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "requires": { + "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" } }, - "@nodelib/fs.stat": { + "node_modules/@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "dev": true, + "engines": { + "node": ">= 8" + } }, - "@nodelib/fs.walk": { + "node_modules/@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "requires": { + "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "@nuxtjs/opencollective": { + "node_modules/@nuxtjs/opencollective": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "requires": { + "dependencies": { "chalk": "^4.1.0", "consola": "^2.15.0", "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" } }, - "@pkgjs/parseargs": { + "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true + "optional": true, + "engines": { + "node": ">=14" + } }, - "@sinonjs/commons": { + "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, - "requires": { + "dependencies": { "type-detect": "4.0.8" } }, - "@sinonjs/fake-timers": { + "node_modules/@sinonjs/fake-timers": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", "dev": true, - "requires": { + "dependencies": { "@sinonjs/commons": "^1.7.0" } }, - "@sqltools/formatter": { + "node_modules/@sqltools/formatter": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" }, - "@tootallnate/once": { + "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "@tsconfig/node10": { + "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "devOptional": true }, - "@tsconfig/node12": { + "node_modules/@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "devOptional": true }, - "@tsconfig/node14": { + "node_modules/@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "devOptional": true }, - "@tsconfig/node16": { + "node_modules/@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "devOptional": true }, - "@types/babel__core": { + "node_modules/@types/babel__core": { "version": "7.1.18", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.18.tgz", "integrity": "sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==", "dev": true, - "requires": { + "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0", "@types/babel__generator": "*", @@ -1373,326 +1911,314 @@ "@types/babel__traverse": "*" } }, - "@types/babel__generator": { + "node_modules/@types/babel__generator": { "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.0.0" } }, - "@types/babel__template": { + "node_modules/@types/babel__template": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, - "requires": { + "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, - "@types/babel__traverse": { + "node_modules/@types/babel__traverse": { "version": "7.14.2", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.3.0" } }, - "@types/body-parser": { + "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, - "requires": { + "dependencies": { "@types/connect": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } } }, - "@types/cache-manager": { + "node_modules/@types/body-parser/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@types/cache-manager": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-3.4.3.tgz", "integrity": "sha512-71aBXoFYXZW4TnDHHH8gExw2lS28BZaWeKefgsiJI7QYZeJfUEbMKw6CQtzGjlYQcGIWwB76hcCrkVA3YHSvsw==", "dev": true }, - "@types/connect": { + "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dev": true, - "requires": { - "@types/node": "*" - }, "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "@types/node": "*" } }, - "@types/cookiejar": { + "node_modules/@types/connect/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@types/cookiejar": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", "dev": true }, - "@types/cron": { + "node_modules/@types/cron": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@types/cron/-/cron-1.7.3.tgz", "integrity": "sha512-iPmUXyIJG1Js+ldPYhOQcYU3kCAQ2FWrSkm1FJPoii2eYSn6wEW6onPukNTT0bfiflexNSRPl6KWmAIqS+36YA==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*", "moment": ">=2.14.0" } }, - "@types/eslint": { + "node_modules/@types/eslint": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", "dev": true, - "requires": { + "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, - "@types/eslint-scope": { + "node_modules/@types/eslint-scope": { "version": "3.7.3", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dev": true, - "requires": { + "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, - "@types/estree": { + "node_modules/@types/estree": { "version": "0.0.51", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, - "@types/express": { + "node_modules/@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", "dev": true, - "requires": { + "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", "@types/qs": "*", "@types/serve-static": "*" } }, - "@types/express-serve-static-core": { + "node_modules/@types/express-serve-static-core": { "version": "4.17.28", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } } }, - "@types/graceful-fs": { + "node_modules/@types/express-serve-static-core/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", "dev": true, - "requires": { - "@types/node": "*" - }, "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "@types/node": "*" } }, - "@types/istanbul-lib-coverage": { + "node_modules/@types/graceful-fs/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, - "@types/istanbul-lib-report": { + "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, - "requires": { + "dependencies": { "@types/istanbul-lib-coverage": "*" } }, - "@types/istanbul-reports": { + "node_modules/@types/istanbul-reports": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, - "requires": { + "dependencies": { "@types/istanbul-lib-report": "*" } }, - "@types/jest": { + "node_modules/@types/jest": { "version": "27.4.1", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", "dev": true, - "requires": { + "dependencies": { "jest-matcher-utils": "^27.0.0", "pretty-format": "^27.0.0" } }, - "@types/json-schema": { + "node_modules/@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, - "@types/json5": { + "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "@types/jsonwebtoken": { + "node_modules/@types/jsonwebtoken": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", "integrity": "sha512-4L8msWK31oXwdtC81RmRBAULd0ShnAHjBuKT9MRQpjP0piNrZdXyTRcKY9/UIfhGeKIT4PvF5amOOUbbT/9Wpg==", - "requires": { + "dependencies": { "@types/node": "*" } }, - "@types/mime": { + "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, - "@types/node": { + "node_modules/@types/node": { "version": "16.11.26", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==" }, - "@types/parse-json": { + "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, - "@types/prettier": { + "node_modules/@types/prettier": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==", "dev": true }, - "@types/qs": { + "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", "dev": true }, - "@types/range-parser": { + "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, - "@types/serve-static": { + "node_modules/@types/serve-static": { "version": "1.13.10", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", "dev": true, - "requires": { + "dependencies": { "@types/mime": "^1", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } } }, - "@types/stack-utils": { + "node_modules/@types/serve-static/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "@types/superagent": { + "node_modules/@types/superagent": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", "dev": true, - "requires": { + "dependencies": { "@types/cookiejar": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } } }, - "@types/supertest": { + "node_modules/@types/superagent/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@types/supertest": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.11.tgz", "integrity": "sha512-uci4Esokrw9qGb9bvhhSVEjd6rkny/dk5PK/Qz4yxKiyppEI+dOPlNrZBahE3i+PoKFYyDxChVXZ/ysS/nrm1Q==", "dev": true, - "requires": { + "dependencies": { "@types/superagent": "*" } }, - "@types/yargs": { + "node_modules/@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, - "requires": { + "dependencies": { "@types/yargs-parser": "*" } }, - "@types/yargs-parser": { + "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, - "@typescript-eslint/eslint-plugin": { + "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", "dev": true, - "requires": { + "dependencies": { "@typescript-eslint/scope-manager": "5.15.0", "@typescript-eslint/type-utils": "5.15.0", "@typescript-eslint/utils": "5.15.0", @@ -1702,53 +2228,113 @@ "regexpp": "^3.2.0", "semver": "^7.3.5", "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "@typescript-eslint/parser": { + "node_modules/@typescript-eslint/parser": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", "dev": true, - "requires": { + "dependencies": { "@typescript-eslint/scope-manager": "5.15.0", "@typescript-eslint/types": "5.15.0", "@typescript-eslint/typescript-estree": "5.15.0", "debug": "^4.3.2" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/scope-manager": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", "dev": true, - "requires": { + "dependencies": { "@typescript-eslint/types": "5.15.0", "@typescript-eslint/visitor-keys": "5.15.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "@typescript-eslint/type-utils": { + "node_modules/@typescript-eslint/type-utils": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", "dev": true, - "requires": { + "dependencies": { "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "@typescript-eslint/types": { + "node_modules/@typescript-eslint/types": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", - "dev": true + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "@typescript-eslint/typescript-estree": { + "node_modules/@typescript-eslint/typescript-estree": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", "dev": true, - "requires": { + "dependencies": { "@typescript-eslint/types": "5.15.0", "@typescript-eslint/visitor-keys": "5.15.0", "debug": "^4.3.2", @@ -1756,119 +2342,148 @@ "is-glob": "^4.0.3", "semver": "^7.3.5", "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "@typescript-eslint/utils": { + "node_modules/@typescript-eslint/utils": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", "dev": true, - "requires": { + "dependencies": { "@types/json-schema": "^7.0.9", "@typescript-eslint/scope-manager": "5.15.0", "@typescript-eslint/types": "5.15.0", "@typescript-eslint/typescript-estree": "5.15.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "@typescript-eslint/visitor-keys": { + "node_modules/@typescript-eslint/visitor-keys": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", "dev": true, - "requires": { + "dependencies": { "@typescript-eslint/types": "5.15.0", "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "@webassemblyjs/ast": { + "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/helper-numbers": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, - "@webassemblyjs/floating-point-hex-parser": { + "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", "dev": true }, - "@webassemblyjs/helper-api-error": { + "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", "dev": true }, - "@webassemblyjs/helper-buffer": { + "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", "dev": true }, - "@webassemblyjs/helper-numbers": { + "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.1", "@webassemblyjs/helper-api-error": "1.11.1", "@xtuc/long": "4.2.2" } }, - "@webassemblyjs/helper-wasm-bytecode": { + "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", "dev": true }, - "@webassemblyjs/helper-wasm-section": { + "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1", "@webassemblyjs/wasm-gen": "1.11.1" } }, - "@webassemblyjs/ieee754": { + "node_modules/@webassemblyjs/ieee754": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "dev": true, - "requires": { + "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, - "@webassemblyjs/leb128": { + "node_modules/@webassemblyjs/leb128": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "dev": true, - "requires": { + "dependencies": { "@xtuc/long": "4.2.2" } }, - "@webassemblyjs/utf8": { + "node_modules/@webassemblyjs/utf8": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", "dev": true }, - "@webassemblyjs/wasm-edit": { + "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1", @@ -1879,12 +2494,12 @@ "@webassemblyjs/wast-printer": "1.11.1" } }, - "@webassemblyjs/wasm-gen": { + "node_modules/@webassemblyjs/wasm-gen": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1", "@webassemblyjs/ieee754": "1.11.1", @@ -1892,24 +2507,24 @@ "@webassemblyjs/utf8": "1.11.1" } }, - "@webassemblyjs/wasm-opt": { + "node_modules/@webassemblyjs/wasm-opt": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", "@webassemblyjs/wasm-gen": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1" } }, - "@webassemblyjs/wasm-parser": { + "node_modules/@webassemblyjs/wasm-parser": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-api-error": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1", @@ -1918,240 +2533,305 @@ "@webassemblyjs/utf8": "1.11.1" } }, - "@webassemblyjs/wast-printer": { + "node_modules/@webassemblyjs/wast-printer": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", "dev": true, - "requires": { + "dependencies": { "@webassemblyjs/ast": "1.11.1", "@xtuc/long": "4.2.2" } }, - "@xtuc/ieee754": { + "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true }, - "@xtuc/long": { + "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, - "abab": { + "node_modules/abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true }, - "accepts": { + "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { + "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "acorn": { + "node_modules/acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true + "devOptional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "acorn-globals": { + "node_modules/acorn-globals": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, - "requires": { + "dependencies": { "acorn": "^7.1.1", "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - } + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals/node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" } }, - "acorn-import-assertions": { + "node_modules/acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true + "dev": true, + "peerDependencies": { + "acorn": "^8" + } }, - "acorn-jsx": { + "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, - "acorn-walk": { + "node_modules/acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true + "devOptional": true, + "engines": { + "node": ">=0.4.0" + } }, - "agent-base": { + "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, - "requires": { + "dependencies": { "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" } }, - "ajv": { + "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "requires": { + "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, - "dependencies": { - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "ajv-keywords": { + "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ajv/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "ansi-colors": { + "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "ansi-escapes": { + "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, - "requires": { + "dependencies": { "type-fest": "^0.21.3" }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "ansi-regex": { + "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } }, - "ansi-styles": { + "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { + "dependencies": { "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "any-promise": { + "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, - "anymatch": { + "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, - "requires": { + "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "app-root-path": { + "node_modules/app-root-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==" + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } }, - "append-field": { + "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" }, - "arg": { + "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, - "argparse": { + "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "array-flatten": { + "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "array-union": { + "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "asap": { + "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", "dev": true }, - "async": { + "node_modules/async": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, - "asynckit": { + "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "axios": { + "node_modules/axios": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { + "dependencies": { "follow-redirects": "^1.14.8" } }, - "babel-jest": { + "node_modules/babel-jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", "dev": true, - "requires": { + "dependencies": { "@jest/transform": "^27.5.1", "@jest/types": "^27.5.1", "@types/babel__core": "^7.1.14", @@ -2160,39 +2840,51 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "babel-plugin-istanbul": { + "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "babel-plugin-jest-hoist": { + "node_modules/babel-plugin-jest-hoist": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", "dev": true, - "requires": { + "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", "@types/babel__core": "^7.0.0", "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "babel-preset-current-node-syntax": { + "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, - "requires": { + "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.8.3", @@ -2205,72 +2897,99 @@ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "babel-preset-jest": { + "node_modules/babel-preset-jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", "dev": true, - "requires": { + "dependencies": { "babel-plugin-jest-hoist": "^27.5.1", "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "balanced-match": { + "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "base64-js": { + "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "binary-extensions": { + "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "bl": { + "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, - "requires": { + "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - } + "safe-buffer": "~5.2.0" } }, - "body-parser": { + "node_modules/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "requires": { + "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", @@ -2282,236 +3001,318 @@ "raw-body": "2.4.3", "type-is": "~1.6.18" }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "ms": "2.0.0" } }, - "brace-expansion": { + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "braces": { + "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "requires": { + "dependencies": { "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" } }, - "browser-process-hrtime": { + "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, - "browserslist": { + "node_modules/browserslist": { "version": "4.20.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz", "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==", "dev": true, - "requires": { + "dependencies": { "caniuse-lite": "^1.0.30001313", "electron-to-chromium": "^1.4.76", "escalade": "^3.1.1", "node-releases": "^2.0.2", "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" } }, - "bs-logger": { + "node_modules/bs-logger": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, - "requires": { + "dependencies": { "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" } }, - "bser": { + "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, - "requires": { + "dependencies": { "node-int64": "^0.4.0" } }, - "buffer": { + "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, - "requires": { + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, - "buffer-equal-constant-time": { + "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, - "buffer-from": { + "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "buffer-writer": { + "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } }, - "busboy": { + "node_modules/busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "requires": { + "dependencies": { "dicer": "0.2.5", "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" } }, - "bytes": { + "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } }, - "cache-manager": { + "node_modules/cache-manager": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-3.6.1.tgz", "integrity": "sha512-jxJvGYhN5dUgpriAdsDnnYbKse4dEXI5i3XpwTfPq5utPtXH1uYXWyGLHGlbSlh9Vq4ytrgAUVwY+IodNeKigA==", - "requires": { + "dependencies": { "async": "3.2.3", "lodash": "^4.17.21", "lru-cache": "6.0.0" } }, - "call-bind": { + "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { + "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "callsites": { + "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "camelcase": { + "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "caniuse-lite": { + "node_modules/caniuse-lite": { "version": "1.0.30001317", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz", "integrity": "sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==", - "dev": true + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } }, - "chalk": { + "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { + "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "char-regex": { + "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + } }, - "chardet": { + "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "chokidar": { + "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "chrome-trace-event": { + "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.0" + } }, - "ci-info": { + "node_modules/ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", "dev": true }, - "cjs-module-lexer": { + "node_modules/cjs-module-lexer": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, - "class-transformer": { + "node_modules/class-transformer": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" }, - "class-validator": { + "node_modules/class-validator": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz", "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==", - "requires": { + "dependencies": { "libphonenumber-js": "^1.9.43", "validator": "^13.7.0" } }, - "cli-cursor": { + "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, - "requires": { + "dependencies": { "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" } }, - "cli-highlight": { + "node_modules/cli-highlight": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "requires": { + "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", @@ -2519,591 +3320,740 @@ "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, - "dependencies": { - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - } + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" } }, - "cli-spinners": { + "node_modules/cli-highlight/node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/cli-spinners": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "cli-table3": { + "node_modules/cli-table3": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", "dev": true, - "requires": { - "colors": "1.4.0", + "dependencies": { "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "colors": "1.4.0" } }, - "cli-width": { + "node_modules/cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 10" + } }, - "cliui": { + "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { + "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, - "clone": { + "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8" + } }, - "co": { + "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } }, - "collect-v8-coverage": { + "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, - "color-convert": { + "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { + "dependencies": { "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "color-name": { + "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "colors": { + "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, - "optional": true + "optional": true, + "engines": { + "node": ">=0.1.90" + } }, - "combined-stream": { + "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { + "dependencies": { "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "commander": { + "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "component-emitter": { + "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, - "concat-map": { + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "concat-stream": { + "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { + "engines": [ + "node >= 0.8" + ], + "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "consola": { + "node_modules/consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, - "content-disposition": { + "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { + "dependencies": { "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" } }, - "content-type": { + "node_modules/content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } }, - "convert-source-map": { + "node_modules/convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - }, "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } + "safe-buffer": "~5.1.1" } }, - "cookie": { + "node_modules/convert-source-map/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } }, - "cookie-signature": { + "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, - "cookiejar": { + "node_modules/cookiejar": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", "dev": true }, - "core-util-is": { + "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, - "cors": { + "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { + "dependencies": { "object-assign": "^4", "vary": "^1" + }, + "engines": { + "node": ">= 0.10" } }, - "cosmiconfig": { + "node_modules/cosmiconfig": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, - "requires": { + "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" } }, - "create-require": { + "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, - "cron": { + "node_modules/cron": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz", "integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==", - "requires": { + "dependencies": { "moment-timezone": "^0.5.x" } }, - "cron-parser": { + "node_modules/cron-parser": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", - "requires": { + "dependencies": { "is-nan": "^1.3.2", "luxon": "^1.26.0" + }, + "engines": { + "node": ">=0.8" } }, - "cross-spawn": { + "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { + "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "cssom": { + "node_modules/cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", "dev": true }, - "cssstyle": { + "node_modules/cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, - "requires": { + "dependencies": { "cssom": "~0.3.6" }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } + "engines": { + "node": ">=8" } }, - "data-urls": { + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", "dev": true, - "requires": { + "dependencies": { "abab": "^2.0.3", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" } }, - "date-fns": { + "node_modules/date-fns": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } }, - "dayjs": { + "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" }, - "debug": { + "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { + "dependencies": { "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "decimal.js": { + "node_modules/decimal.js": { "version": "10.3.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, - "dedent": { + "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, - "deep-is": { + "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "deepmerge": { + "node_modules/deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "defaults": { + "node_modules/defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, - "requires": { + "dependencies": { "clone": "^1.0.2" } }, - "define-properties": { + "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "requires": { + "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "delayed-stream": { + "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } }, - "depd": { + "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } }, - "destroy": { + "node_modules/destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, - "detect-newline": { + "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "dezalgo": { + "node_modules/dezalgo": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", "dev": true, - "requires": { + "dependencies": { "asap": "^2.0.0", "wrappy": "1" } }, - "dicer": { + "node_modules/dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "requires": { + "dependencies": { "readable-stream": "1.1.x", "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" } }, - "diff": { + "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "devOptional": true, + "engines": { + "node": ">=0.3.1" + } }, - "diff-sequences": { + "node_modules/diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } }, - "dir-glob": { + "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "requires": { + "dependencies": { "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "doctrine": { + "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "requires": { + "dependencies": { "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "domexception": { + "node_modules/domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, - "requires": { + "dependencies": { "webidl-conversions": "^5.0.0" }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, + "engines": { + "node": ">=8" } }, - "dotenv": { + "node_modules/dotenv": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", - "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", + "engines": { + "node": ">=12" + } }, - "dotenv-expand": { + "node_modules/dotenv-expand": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.2.tgz", - "integrity": "sha512-vKKAk+VOzAWOV/dPIeSYqhgC/TQY+6L6Ibkzfsr8xd1stdBsTuGu9asCOXgbYbBeS+f2Y6lqqEuw7riOA+xEUQ==" + "integrity": "sha512-vKKAk+VOzAWOV/dPIeSYqhgC/TQY+6L6Ibkzfsr8xd1stdBsTuGu9asCOXgbYbBeS+f2Y6lqqEuw7riOA+xEUQ==", + "engines": { + "node": ">=12" + } }, - "eastasianwidth": { + "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, - "ecdsa-sig-formatter": { + "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { + "dependencies": { "safe-buffer": "^5.0.1" } }, - "ee-first": { + "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, - "electron-to-chromium": { + "node_modules/electron-to-chromium": { "version": "1.4.84", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.84.tgz", "integrity": "sha512-b+DdcyOiZtLXHdgEG8lncYJdxbdJWJvclPNMg0eLUDcSOSO876WA/pYjdSblUTd7eJdIs4YdIxHWGazx7UPSJw==", "dev": true }, - "emittery": { + "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } }, - "emoji-regex": { + "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "encodeurl": { + "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } }, - "end-of-stream": { + "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, - "requires": { + "dependencies": { "once": "^1.4.0" } }, - "enhanced-resolve": { + "node_modules/enhanced-resolve": { "version": "5.9.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" } }, - "error-ex": { + "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, - "requires": { + "dependencies": { "is-arrayish": "^0.2.1" } }, - "es-module-lexer": { + "node_modules/es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", "dev": true }, - "escalade": { + "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } }, - "escape-html": { + "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "escodegen": { + "node_modules/escodegen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", "dev": true, - "requires": { + "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, "dependencies": { - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - } + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" } }, - "eslint": { + "node_modules/eslint": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, - "requires": { + "dependencies": { "@eslint/eslintrc": "^1.2.1", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", @@ -3140,154 +4090,236 @@ "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - } + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "eslint-config-prettier": { + "node_modules/eslint-config-prettier": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } }, - "eslint-plugin-prettier": { + "node_modules/eslint-plugin-prettier": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "dev": true, - "requires": { + "dependencies": { "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "eslint-scope": { + "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "requires": { + "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" } }, - "eslint-utils": { + "node_modules/eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, - "requires": { + "dependencies": { "eslint-visitor-keys": "^2.0.0" }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" } }, - "eslint-visitor-keys": { + "node_modules/eslint-visitor-keys": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } }, - "espree": { + "node_modules/espree": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, - "requires": { + "dependencies": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "esprima": { + "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } }, - "esquery": { + "node_modules/esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, - "requires": { + "dependencies": { "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "esrecurse": { + "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "requires": { + "dependencies": { "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.0" + } }, - "esutils": { + "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "etag": { + "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } }, - "events": { + "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.x" + } }, - "execa": { + "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, - "requires": { + "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", @@ -3297,31 +4329,43 @@ "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "exit": { + "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "expect": { + "node_modules/expect": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "jest-get-type": "^27.5.1", "jest-matcher-utils": "^27.5.1", "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "express": { + "node_modules/express": { "version": "4.17.3", "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "requires": { + "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.19.2", @@ -3353,130 +4397,149 @@ "utils-merge": "1.0.1", "vary": "~1.1.2" }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - } + "ms": "2.0.0" } }, - "external-editor": { + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, - "requires": { + "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" } }, - "fast-deep-equal": { + "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "fast-diff": { + "node_modules/fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, - "fast-glob": { + "node_modules/fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, - "requires": { + "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" } }, - "fast-json-stable-stringify": { + "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "fast-levenshtein": { + "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fast-safe-stringify": { + "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, - "fastq": { + "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, - "requires": { + "dependencies": { "reusify": "^1.0.4" } }, - "fb-watchman": { + "node_modules/fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", "dev": true, - "requires": { + "dependencies": { "bser": "2.1.1" } }, - "figures": { + "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, - "requires": { + "dependencies": { "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "file-entry-cache": { + "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, - "requires": { + "dependencies": { "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "fill-range": { + "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "requires": { + "dependencies": { "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "finalhandler": { + "node_modules/finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { + "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -3485,75 +4548,106 @@ "statuses": "~1.5.0", "unpipe": "~1.0.0" }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "ms": "2.0.0" } }, - "find-up": { + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "requires": { + "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "flat-cache": { + "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, - "requires": { + "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "flatted": { + "node_modules/flatted": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, - "follow-redirects": { + "node_modules/follow-redirects": { "version": "1.14.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } }, - "foreground-child": { + "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "requires": { + "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - } + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "fork-ts-checker-webpack-plugin": { + "node_modules/fork-ts-checker-webpack-plugin": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.1.tgz", "integrity": "sha512-uOfQdg/iQ8iokQ64qcbu8iZb114rOmaKLQFu7hU14/eJaKgsP91cQ7ts7v2iiDld6TzDe84Meksha8/MkWiCyw==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.16.7", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3566,393 +4660,573 @@ "semver": "^7.3.5", "tapable": "^2.2.1" }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "vue-template-compiler": "*", + "webpack": "^5.11.0" + }, + "peerDependenciesMeta": { + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } + "optional": true } } }, - "form-data": { + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { + "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, - "formidable": { + "node_modules/formidable": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz", "integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==", "dev": true, - "requires": { + "dependencies": { "dezalgo": "1.0.3", "hexoid": "1.0.0", "once": "1.4.0", "qs": "6.9.3" }, - "dependencies": { - "qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==", - "dev": true - } + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/formidable/node_modules/qs": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "forwarded": { + "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } }, - "fresh": { + "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } }, - "fs-extra": { + "node_modules/fs-extra": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" } }, - "fs-monkey": { + "node_modules/fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", "dev": true }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fsevents": { + "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "optional": true + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, - "function-bind": { + "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "functional-red-black-tree": { + "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "gensync": { + "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "get-caller-file": { + "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "get-intrinsic": { + "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { + "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "get-package-type": { + "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=8.0.0" + } }, - "get-stream": { + "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "glob": { + "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "requires": { + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "glob-parent": { + "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "requires": { + "dependencies": { "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "glob-to-regexp": { + "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "globals": { + "node_modules/globals": { "version": "13.12.1", "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", "dev": true, - "requires": { + "dependencies": { "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "globby": { + "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, - "requires": { + "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "graceful-fs": { + "node_modules/graceful-fs": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, - "graphql-tag": { + "node_modules/graphql-tag": { "version": "2.12.6", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "requires": { + "dependencies": { "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "has": { + "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { + "dependencies": { "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "has-flag": { + "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } }, - "has-property-descriptors": { + "node_modules/has-property-descriptors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "requires": { + "dependencies": { "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "has-symbols": { + "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "hexoid": { + "node_modules/hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "highlight.js": { + "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } }, - "html-encoding-sniffer": { + "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", "dev": true, - "requires": { + "dependencies": { "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" } }, - "html-escaper": { + "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "http-errors": { + "node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { + "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" } }, - "http-proxy-agent": { + "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "dev": true, - "requires": { + "dependencies": { "@tootallnate/once": "1", "agent-base": "6", "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "https-proxy-agent": { + "node_modules/https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dev": true, - "requires": { + "dependencies": { "agent-base": "6", "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "human-signals": { + "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true + "dev": true, + "engines": { + "node": ">=10.17.0" + } }, - "iconv-lite": { + "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { + "dependencies": { "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" } }, - "ieee754": { + "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "ignore": { + "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 4" + } }, - "import-fresh": { + "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "requires": { + "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" } }, - "import-local": { + "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, - "requires": { + "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "imurmurhash": { + "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.19" + } }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "inquirer": { + "node_modules/inquirer": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, - "requires": { + "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", @@ -3967,241 +5241,337 @@ "strip-ansi": "^6.0.0", "through": "^2.3.6" }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/inquirer/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" } }, - "interpret": { + "node_modules/inquirer/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.10" + } }, - "ipaddr.js": { + "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } }, - "is-arrayish": { + "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-binary-path": { + "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "requires": { + "dependencies": { "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "is-core-module": { + "node_modules/is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dev": true, - "requires": { + "dependencies": { "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-extglob": { + "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "is-fullwidth-code-point": { + "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } }, - "is-generator-fn": { + "node_modules/is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "is-glob": { + "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "requires": { + "dependencies": { "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "is-interactive": { + "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "is-nan": { + "node_modules/is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "requires": { + "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-number": { + "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.12.0" + } }, - "is-potential-custom-element-name": { + "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, - "is-stream": { + "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "is-typedarray": { + "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-unicode-supported": { + "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "isarray": { + "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, - "isexe": { + "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "istanbul-lib-coverage": { + "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "istanbul-lib-instrument": { + "node_modules/istanbul-lib-instrument": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "istanbul-lib-report": { + "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, - "requires": { + "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "istanbul-lib-source-maps": { + "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, - "requires": { + "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" } }, - "istanbul-reports": { + "node_modules/istanbul-reports": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", "dev": true, - "requires": { + "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "iterare": { + "node_modules/iterare": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==" + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "engines": { + "node": ">=6" + } }, - "jackspeak": { + "node_modules/jackspeak": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "requires": { - "@isaacs/cliui": "^8.0.2", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, - "jest": { + "node_modules/jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", "dev": true, - "requires": { + "dependencies": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "jest-changed-files": { + "node_modules/jest-changed-files": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "execa": "^5.0.0", "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-circus": { + "node_modules/jest-circus": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^27.5.1", "@jest/test-result": "^27.5.1", "@jest/types": "^27.5.1", @@ -4222,21 +5592,22 @@ "stack-utils": "^2.0.3", "throat": "^6.0.1" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-cli": { + "node_modules/jest-circus/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-cli": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", "dev": true, - "requires": { + "dependencies": { "@jest/core": "^27.5.1", "@jest/test-result": "^27.5.1", "@jest/types": "^27.5.1", @@ -4249,14 +5620,28 @@ "jest-validate": "^27.5.1", "prompts": "^2.0.1", "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "jest-config": { + "node_modules/jest-config": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.8.0", "@jest/test-sequencer": "^27.5.1", "@jest/types": "^27.5.1", @@ -4281,48 +5666,68 @@ "pretty-format": "^27.5.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } } }, - "jest-diff": { + "node_modules/jest-diff": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^27.5.1", "jest-get-type": "^27.5.1", "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-docblock": { + "node_modules/jest-docblock": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", "dev": true, - "requires": { + "dependencies": { "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-each": { + "node_modules/jest-each": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "chalk": "^4.0.0", "jest-get-type": "^27.5.1", "jest-util": "^27.5.1", "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-environment-jsdom": { + "node_modules/jest-environment-jsdom": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", "@jest/types": "^27.5.1", @@ -4331,21 +5736,22 @@ "jest-util": "^27.5.1", "jsdom": "^16.6.0" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-environment-node": { + "node_modules/jest-environment-jsdom/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-environment-node": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", "@jest/types": "^27.5.1", @@ -4353,33 +5759,36 @@ "jest-mock": "^27.5.1", "jest-util": "^27.5.1" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-get-type": { + "node_modules/jest-environment-node/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-get-type": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } }, - "jest-haste-map": { + "node_modules/jest-haste-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^27.5.1", "jest-serializer": "^27.5.1", @@ -4388,21 +5797,25 @@ "micromatch": "^4.0.4", "walker": "^1.0.7" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "jest-jasmine2": { + "node_modules/jest-haste-map/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-jasmine2": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^27.5.1", "@jest/source-map": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -4421,43 +5834,50 @@ "pretty-format": "^27.5.1", "throat": "^6.0.1" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-leak-detector": { + "node_modules/jest-jasmine2/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-leak-detector": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", "dev": true, - "requires": { + "dependencies": { "jest-get-type": "^27.5.1", "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-matcher-utils": { + "node_modules/jest-matcher-utils": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.0.0", "jest-diff": "^27.5.1", "jest-get-type": "^27.5.1", "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-message-util": { + "node_modules/jest-message-util": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^27.5.1", "@types/stack-utils": "^2.0.0", @@ -4467,44 +5887,62 @@ "pretty-format": "^27.5.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-mock": { + "node_modules/jest-mock": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "@types/node": "*" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-pnp-resolver": { + "node_modules/jest-mock/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-pnp-resolver": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } }, - "jest-regex-util": { + "node_modules/jest-regex-util": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "dev": true + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } }, - "jest-resolve": { + "node_modules/jest-resolve": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -4515,25 +5953,31 @@ "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-resolve-dependencies": { + "node_modules/jest-resolve-dependencies": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "jest-regex-util": "^27.5.1", "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-runner": { + "node_modules/jest-runner": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", "dev": true, - "requires": { + "dependencies": { "@jest/console": "^27.5.1", "@jest/environment": "^27.5.1", "@jest/test-result": "^27.5.1", @@ -4556,21 +6000,22 @@ "source-map-support": "^0.5.6", "throat": "^6.0.1" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-runtime": { + "node_modules/jest-runner/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-runtime": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", "@jest/globals": "^27.5.1", @@ -4594,39 +6039,44 @@ "slash": "^3.0.0", "strip-bom": "^4.0.0" }, - "dependencies": { - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" } }, - "jest-serializer": { + "node_modules/jest-serializer": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*", "graceful-fs": "^4.2.9" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-snapshot": { + "node_modules/jest-serializer/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-snapshot": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.7.2", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", @@ -4649,14 +6099,17 @@ "natural-compare": "^1.4.0", "pretty-format": "^27.5.1", "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-util": { + "node_modules/jest-util": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "@types/node": "*", "chalk": "^4.0.0", @@ -4664,35 +6117,39 @@ "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-validate": { + "node_modules/jest-util/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-validate": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^27.5.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^27.5.1", "leven": "^3.1.0", "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-watcher": { + "node_modules/jest-watcher": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", "dev": true, - "requires": { + "dependencies": { "@jest/test-result": "^27.5.1", "@jest/types": "^27.5.1", "@types/node": "*", @@ -4701,64 +6158,75 @@ "jest-util": "^27.5.1", "string-length": "^4.0.1" }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-worker": { + "node_modules/jest-watcher/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "js-tokens": { + "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "js-yaml": { + "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "requires": { + "dependencies": { "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "jsdom": { + "node_modules/jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, - "requires": { + "dependencies": { "abab": "^2.0.5", "acorn": "^8.2.4", "acorn-globals": "^6.0.0", @@ -4787,80 +6255,106 @@ "ws": "^7.4.6", "xml-name-validator": "^3.0.0" }, - "dependencies": { - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true } } }, - "jsesc": { + "node_modules/jsdom/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } }, - "json-parse-better-errors": { + "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-parse-even-better-errors": { + "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-schema-traverse": { + "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "json-stable-stringify-without-jsonify": { + "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json5": { + "node_modules/json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, - "requires": { + "dependencies": { "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, - "jsonc-parser": { + "node_modules/jsonc-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", "dev": true }, - "jsonfile": { + "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, - "requires": { - "graceful-fs": "^4.1.6", + "dependencies": { "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "jsonwebtoken": { + "node_modules/jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { + "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", @@ -4872,350 +6366,445 @@ "ms": "^2.1.1", "semver": "^5.6.0" }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" } }, - "jwa": { + "node_modules/jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { + "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, - "jws": { + "node_modules/jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { + "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, - "jwt-decode": { + "node_modules/jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, - "kleur": { + "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "leven": { + "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "levn": { + "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "requires": { + "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/levn/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/levn/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - } + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "libphonenumber-js": { + "node_modules/libphonenumber-js": { "version": "1.9.50", "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.50.tgz", "integrity": "sha512-cCzQPChw2XbordcO2LKiw5Htx5leHVfFk/EXkxNHqJfFo7Fndcb1kF5wPJpc316vCJhhikedYnVysMh3Sc7Ocw==" }, - "lines-and-columns": { + "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "loader-runner": { + "node_modules/loader-runner": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.11.5" + } }, - "locate-path": { + "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "requires": { + "dependencies": { "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "lodash": { + "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "lodash.includes": { + "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" }, - "lodash.isboolean": { + "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" }, - "lodash.isinteger": { + "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" }, - "lodash.isnumber": { + "node_modules/lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" }, - "lodash.isplainobject": { + "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" }, - "lodash.isstring": { + "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" }, - "lodash.memoize": { + "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, - "lodash.merge": { + "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.once": { + "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, - "log-symbols": { + "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "long-timeout": { + "node_modules/long-timeout": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==" }, - "lru-cache": { + "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { + "dependencies": { "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "luxon": { + "node_modules/luxon": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", - "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==" + "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==", + "engines": { + "node": "*" + } }, - "macos-release": { + "node_modules/macos-release": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "magic-string": { + "node_modules/magic-string": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", "dev": true, - "requires": { + "dependencies": { "sourcemap-codec": "^1.4.4" } }, - "make-dir": { + "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, - "requires": { + "dependencies": { "semver": "^6.0.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "make-error": { + "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, - "makeerror": { + "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, - "requires": { + "dependencies": { "tmpl": "1.0.5" } }, - "media-typer": { + "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } }, - "memfs": { + "node_modules/memfs": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", "dev": true, - "requires": { + "dependencies": { "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" } }, - "merge-descriptors": { + "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, - "merge-stream": { + "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "merge2": { + "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 8" + } }, - "methods": { + "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } }, - "micromatch": { + "node_modules/micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, - "requires": { + "dependencies": { "braces": "^3.0.1", "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" } }, - "mime": { + "node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } }, - "mime-db": { + "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } }, - "mime-types": { + "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { + "dependencies": { "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, - "mimic-fn": { + "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "minimatch": { + "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "minimist": { + "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "minipass": { + "node_modules/minipass": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, - "mkdirp": { + "node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { + "dependencies": { "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "moment": { + "node_modules/moment": { "version": "2.29.3", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "engines": { + "node": "*" + } }, - "moment-timezone": { + "node_modules/moment-timezone": { "version": "0.5.34", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", - "requires": { + "dependencies": { "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" } }, - "ms": { + "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "multer": { + "node_modules/multer": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "requires": { + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", + "dependencies": { "append-field": "^1.0.0", "busboy": "^0.2.11", "concat-stream": "^1.5.2", @@ -5225,199 +6814,248 @@ "type-is": "^1.6.4", "xtend": "^4.0.0" }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/multer/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - } + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "mute-stream": { + "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "mz": { + "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { + "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, - "natural-compare": { + "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "negotiator": { + "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } }, - "neo-async": { + "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node-cron": { + "node_modules/node-cron": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.1.tgz", - "integrity": "sha512-RAWZTNn2M5KDIUV/389UX0EXsqvdFAwc9QwHQceh0Ga56dygqSRthqIjwpgZsoDspHGt2rkHdk9Z4RgfPMdALw==" + "integrity": "sha512-RAWZTNn2M5KDIUV/389UX0EXsqvdFAwc9QwHQceh0Ga56dygqSRthqIjwpgZsoDspHGt2rkHdk9Z4RgfPMdALw==", + "engines": { + "node": ">=6.0.0" + } }, - "node-emoji": { + "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "dev": true, - "requires": { + "dependencies": { "lodash": "^4.17.21" } }, - "node-fetch": { + "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { + "dependencies": { "whatwg-url": "^5.0.0" }, - "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true } } }, - "node-int64": { + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", "dev": true }, - "node-releases": { + "node_modules/node-releases": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", "dev": true }, - "node-schedule": { + "node_modules/node-schedule": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.0.tgz", "integrity": "sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==", - "requires": { + "dependencies": { "cron-parser": "^3.5.0", "long-timeout": "0.1.1", "sorted-array-functions": "^1.3.0" + }, + "engines": { + "node": ">=6" } }, - "normalize-path": { + "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "npm-run-path": { + "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, - "requires": { + "dependencies": { "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "nwsapi": { + "node_modules/nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, - "object-assign": { + "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } }, - "object-hash": { + "node_modules/object-hash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } }, - "object-inspect": { + "node_modules/object-inspect": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "object-keys": { + "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } }, - "object-resolve-path": { + "node_modules/object-resolve-path": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-resolve-path/-/object-resolve-path-1.1.1.tgz", "integrity": "sha1-p/j5Poogr4DkQhe6fbVDFtnRIjI=" }, - "on-finished": { + "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { + "dependencies": { "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { + "dependencies": { "wrappy": "1" } }, - "onetime": { + "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "requires": { + "dependencies": { "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "optional": { + "node_modules/optional": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/optional/-/optional-0.1.4.tgz", "integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==", "dev": true }, - "optionator": { + "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, - "requires": { + "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", @@ -5425,30 +7063,37 @@ "type-check": "^0.4.0", "word-wrap": "^1.2.3" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - } + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "ora": { + "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, - "requires": { + "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", @@ -5458,560 +7103,814 @@ "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "os-name": { + "node_modules/os-name": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", "dev": true, - "requires": { + "dependencies": { "macos-release": "^2.5.0", "windows-release": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "os-tmpdir": { + "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "p-limit": { + "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "requires": { + "dependencies": { "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-locate": { + "node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "requires": { + "dependencies": { "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "p-try": { + "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "packet-reader": { + "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" }, - "parent-module": { + "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "requires": { + "dependencies": { "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "parse-json": { + "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "parse5": { + "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, - "parse5-htmlparser2-tree-adapter": { + "node_modules/parse5-htmlparser2-tree-adapter": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "requires": { + "dependencies": { "parse5": "^6.0.1" } }, - "parseurl": { + "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } }, - "path-exists": { + "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } }, - "path-key": { + "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } }, - "path-parse": { + "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-scurry": { + "node_modules/path-scurry": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "requires": { + "dependencies": { "lru-cache": "^9.1.1 || ^10.0.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, - "dependencies": { - "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" - } + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" } }, - "path-to-regexp": { + "node_modules/path-to-regexp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" }, - "path-type": { + "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "pg": { + "node_modules/pg": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", - "requires": { + "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", "pg-connection-string": "^2.6.2", "pg-pool": "^3.6.1", "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } } }, - "pg-cloudflare": { + "node_modules/pg-cloudflare": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", "optional": true }, - "pg-connection-string": { + "node_modules/pg-connection-string": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" }, - "pg-int8": { + "node_modules/pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } }, - "pg-pool": { + "node_modules/pg-pool": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==" + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } }, - "pg-protocol": { + "node_modules/pg-protocol": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" }, - "pg-types": { + "node_modules/pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { + "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" } }, - "pgpass": { + "node_modules/pgpass": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "requires": { + "dependencies": { "split2": "^4.1.0" } }, - "picocolors": { + "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, - "picomatch": { + "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, - "pirates": { + "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "pkg-dir": { + "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "requires": { + "dependencies": { "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "pluralize": { + "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "postgres-array": { + "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } }, - "postgres-bytea": { + "node_modules/postgres-bytea": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } }, - "postgres-date": { + "node_modules/postgres-date": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } }, - "postgres-interval": { + "node_modules/postgres-interval": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { + "dependencies": { "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "prelude-ls": { + "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "prettier": { + "node_modules/prettier": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } }, - "prettier-linter-helpers": { + "node_modules/prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, - "requires": { + "dependencies": { "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "pretty-format": { + "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "process-nextick-args": { + "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "prompts": { + "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, - "requires": { + "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" } }, - "proxy-addr": { + "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { + "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" } }, - "psl": { + "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, - "pump": { + "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, - "requires": { + "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "punycode": { + "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "qs": { + "node_modules/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "queue-microtask": { + "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "randombytes": { + "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "^5.1.0" } }, - "range-parser": { + "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } }, - "raw-body": { + "node_modules/raw-body": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "requires": { + "dependencies": { "bytes": "3.1.2", "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "react-is": { + "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "readable-stream": { + "node_modules/readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { + "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, - "readdirp": { + "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "requires": { + "dependencies": { "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "rechoir": { + "node_modules/rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, - "requires": { + "dependencies": { "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" } }, - "reflect-metadata": { + "node_modules/reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, - "regexpp": { + "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } }, - "require-directory": { + "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } }, - "require-from-string": { + "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "resolve": { + "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, - "requires": { + "dependencies": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "resolve-cwd": { + "node_modules/resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, - "requires": { + "dependencies": { "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "resolve-from": { + "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "resolve.exports": { + "node_modules/resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + } }, - "restore-cursor": { + "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, - "requires": { + "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" } }, - "reusify": { + "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } }, - "rimraf": { + "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { + "dependencies": { "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "run-async": { + "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.12.0" + } }, - "run-parallel": { + "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, - "requires": { + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { "queue-microtask": "^1.2.2" } }, - "rxjs": { + "node_modules/rxjs": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", - "requires": { + "dependencies": { "tslib": "^2.1.0" } }, - "safe-buffer": { + "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "safer-buffer": { + "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "saxes": { + "node_modules/saxes": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", "dev": true, - "requires": { + "dependencies": { "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" } }, - "schema-utils": { + "node_modules/schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, - "requires": { + "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "semver": { + "node_modules/semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, - "requires": { + "dependencies": { "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "send": { + "node_modules/send": { "version": "0.17.2", "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "requires": { + "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", @@ -6026,261 +7925,330 @@ "range-parser": "~1.2.1", "statuses": "~1.5.0" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" } }, - "serialize-javascript": { + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, - "requires": { + "dependencies": { "randombytes": "^2.1.0" } }, - "serve-static": { + "node_modules/serve-static": { "version": "1.14.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "requires": { + "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "setprototypeof": { + "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "sha.js": { + "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { + "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" } }, - "shebang-command": { + "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { + "dependencies": { "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "shebang-regex": { + "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } }, - "shelljs": { + "node_modules/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, - "requires": { + "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" } }, - "side-channel": { + "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "signal-exit": { + "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "sisteransi": { + "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, - "slash": { + "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "sorted-array-functions": { + "node_modules/sorted-array-functions": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" }, - "source-map": { + "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "source-map-support": { + "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "requires": { + "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "sourcemap-codec": { + "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", "dev": true }, - "split2": { + "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } }, - "sprintf-js": { + "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "stack-utils": { + "node_modules/stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, - "requires": { + "dependencies": { "escape-string-regexp": "^2.0.0" }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" } }, - "statuses": { + "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } }, - "streamsearch": { + "node_modules/streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, - "string-length": { + "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, - "requires": { + "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" } }, - "string-width": { + "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "strip-ansi": { + "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" } }, - "strip-bom": { + "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "strip-final-newline": { + "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "strip-json-comments": { + "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "superagent": { + "node_modules/superagent": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz", "integrity": "sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ==", "dev": true, - "requires": { + "dependencies": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.3", "debug": "^4.3.3", @@ -6293,277 +8261,379 @@ "readable-stream": "^3.6.0", "semver": "^7.3.5" }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/superagent/node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dev": true, "dependencies": { - "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - } + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "supertest": { + "node_modules/superagent/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/superagent/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/supertest": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz", "integrity": "sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==", "dev": true, - "requires": { + "dependencies": { "methods": "^1.1.2", "superagent": "^7.1.0" + }, + "engines": { + "node": ">=6.0.0" } }, - "supports-color": { + "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { + "dependencies": { "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "supports-hyperlinks": { + "node_modules/supports-hyperlinks": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" } }, - "supports-preserve-symlinks-flag": { + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "swagger-ui-dist": { + "node_modules/swagger-ui-dist": { "version": "4.10.3", "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.10.3.tgz", "integrity": "sha512-eR4vsd7sYo0Sx7ZKRP5Z04yij7JkNmIlUQfrDQgC+xO5ABYx+waabzN+nDsQTLAJ4Z04bjkRd8xqkJtbxr3G7w==" }, - "swagger-ui-express": { + "node_modules/swagger-ui-express": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.3.0.tgz", "integrity": "sha512-jN46SEEe9EoXa3ZgZoKgnSF6z0w3tnM1yqhO4Y+Q4iZVc8JOQB960EZpIAz6rNROrDApVDwcMHR0mhlnc/5Omw==", - "requires": { + "dependencies": { "swagger-ui-dist": ">=4.1.3" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0" } }, - "symbol-observable": { + "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10" + } }, - "symbol-tree": { + "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "tapable": { + "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "templates.js": { + "node_modules/templates.js": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/templates.js/-/templates.js-0.3.11.tgz", - "integrity": "sha1-qAtXgaoySmHpK+GmlHDVATQd6QQ=" + "integrity": "sha1-qAtXgaoySmHpK+GmlHDVATQd6QQ=", + "engines": { + "node": ">=0.6" + } }, - "terminal-link": { + "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", "dev": true, - "requires": { + "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "terser": { + "node_modules/terser": { "version": "5.12.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", "dev": true, - "requires": { + "dependencies": { "acorn": "^8.5.0", "commander": "^2.20.0", "source-map": "~0.7.2", "source-map-support": "~0.5.20" }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" } }, - "terser-webpack-plugin": { + "node_modules/terser-webpack-plugin": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", "dev": true, - "requires": { + "dependencies": { "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "test-exclude": { + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "requires": { + "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" } }, - "text-table": { + "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "thenify": { + "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { + "dependencies": { "any-promise": "^1.0.0" } }, - "thenify-all": { + "node_modules/thenify-all": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "requires": { + "dependencies": { "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" } }, - "throat": { + "node_modules/throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, - "through": { + "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "tmp": { + "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, - "requires": { + "dependencies": { "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" } }, - "tmpl": { + "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "to-fast-properties": { + "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "to-regex-range": { + "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "requires": { + "dependencies": { "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "toidentifier": { + "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } }, - "tough-cookie": { + "node_modules/tough-cookie": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "dev": true, - "requires": { + "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.1.2" }, - "dependencies": { - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" } }, - "tr46": { + "node_modules/tr46": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", "dev": true, - "requires": { + "dependencies": { "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" } }, - "tree-kill": { + "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true + "dev": true, + "bin": { + "tree-kill": "cli.js" + } }, - "ts-jest": { + "node_modules/ts-jest": { "version": "27.1.3", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.3.tgz", "integrity": "sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA==", "dev": true, - "requires": { + "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^27.0.0", @@ -6572,26 +8642,61 @@ "make-error": "1.x", "semver": "7.x", "yargs-parser": "20.x" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@types/jest": "^27.0.0", + "babel-jest": ">=27.0.0 <28", + "esbuild": "~0.14.0", + "jest": "^27.0.0", + "typescript": ">=3.8 <5.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } } }, - "ts-loader": { + "node_modules/ts-loader": { "version": "9.2.8", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.0.0", "micromatch": "^4.0.0", "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" } }, - "ts-node": { + "node_modules/ts-node": { "version": "10.7.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", - "dev": true, - "requires": { + "devOptional": true, + "dependencies": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", @@ -6605,113 +8710,155 @@ "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "tsconfig-paths": { + "node_modules/tsconfig-paths": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.0.tgz", "integrity": "sha512-cg/1jAZoL57R39+wiw4u/SCC6Ic9Q5NqjBOb+9xISedOYurfog9ZNmKJSxAnb2m/5Bq4lE9lhUcau33Ml8DM0g==", "dev": true, - "requires": { + "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.1", "minimist": "^1.2.0", "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } } }, - "tsconfig-paths-webpack-plugin": { + "node_modules/tsconfig-paths-webpack-plugin": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz", "integrity": "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.7.0", "tsconfig-paths": "^3.9.0" } }, - "tslib": { + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, - "tsutils": { + "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "requires": { + "dependencies": { "tslib": "^1.8.1" }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "type-check": { + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, - "requires": { + "dependencies": { "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "type-detect": { + "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "type-fest": { + "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "type-is": { + "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { + "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, - "typedarray": { + "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, - "typedarray-to-buffer": { + "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, - "requires": { + "dependencies": { "is-typedarray": "^1.0.0" } }, - "typeorm": { + "node_modules/typeorm": { "version": "0.3.20", "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", - "requires": { + "dependencies": { "@sqltools/formatter": "^1.2.5", "app-root-path": "^3.1.0", "buffer": "^6.0.3", @@ -6728,240 +8875,420 @@ "uuid": "^9.0.0", "yargs": "^17.6.2" }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">=16.13.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0", + "@sap/hana-client": "^2.12.25", + "better-sqlite3": "^7.1.2 || ^8.0.0 || ^9.0.0", + "hdb-pool": "^0.1.6", + "ioredis": "^5.0.4", + "mongodb": "^5.8.0", + "mssql": "^9.1.1 || ^10.0.1", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^6.3.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } + "ioredis": { + "optional": true }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } + "mongodb": { + "optional": true }, - "dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + "mssql": { + "optional": true }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } + "mysql2": { + "optional": true }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } + "oracledb": { + "optional": true }, - "mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==" + "pg": { + "optional": true }, - "reflect-metadata": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", - "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" + "pg-native": { + "optional": true }, - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "pg-query-stream": { + "optional": true }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typeorm/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/typeorm/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/typeorm/node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/typeorm/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/reflect-metadata": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" + }, + "node_modules/typeorm/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/typeorm/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/typeorm/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" } }, - "typescript": { + "node_modules/typescript": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", - "dev": true + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } }, - "universalify": { + "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 10.0.0" + } }, - "unpipe": { + "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } }, - "uri-js": { + "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "requires": { + "dependencies": { "punycode": "^2.1.0" } }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "utils-merge": { + "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } }, - "uuid": { + "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } }, - "v8-compile-cache": { + "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "v8-compile-cache-lib": { + "node_modules/v8-compile-cache-lib": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", - "dev": true + "devOptional": true }, - "v8-to-istanbul": { + "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", "dev": true, - "requires": { + "dependencies": { "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0", "source-map": "^0.7.3" }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" } }, - "validator": { + "node_modules/validator": { "version": "13.7.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } }, - "vary": { + "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } }, - "w3c-hr-time": { + "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", "dev": true, - "requires": { + "dependencies": { "browser-process-hrtime": "^1.0.0" } }, - "w3c-xmlserializer": { + "node_modules/w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", "dev": true, - "requires": { + "dependencies": { "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" } }, - "walker": { + "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, - "requires": { + "dependencies": { "makeerror": "1.0.12" } }, - "watchpack": { + "node_modules/watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "dev": true, - "requires": { + "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" } }, - "wcwidth": { + "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, - "requires": { + "dependencies": { "defaults": "^1.0.3" } }, - "webidl-conversions": { + "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true + "dev": true, + "engines": { + "node": ">=10.4" + } }, - "webpack": { + "node_modules/webpack": { "version": "5.70.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", "dev": true, - "requires": { + "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", @@ -6986,184 +9313,267 @@ "terser-webpack-plugin": "^5.1.3", "watchpack": "^2.3.1", "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "webpack-node-externals": { + "node_modules/webpack-node-externals": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "webpack-sources": { + "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true + "dev": true, + "engines": { + "node": ">=10.13.0" + } }, - "whatwg-encoding": { + "node_modules/whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "dev": true, - "requires": { + "dependencies": { "iconv-lite": "0.4.24" } }, - "whatwg-mimetype": { + "node_modules/whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", "dev": true }, - "whatwg-url": { + "node_modules/whatwg-url": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, - "requires": { + "dependencies": { "lodash": "^4.7.0", "tr46": "^2.1.0", "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" } }, - "which": { + "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "windows-release": { + "node_modules/windows-release": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", "dev": true, - "requires": { + "dependencies": { "execa": "^4.0.2" }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/windows-release/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "dependencies": { - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - } + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" } }, - "word-wrap": { + "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "write-file-atomic": { + "node_modules/write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, - "requires": { + "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", "signal-exit": "^3.0.2", "typedarray-to-buffer": "^3.1.5" } }, - "ws": { + "node_modules/ws": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, - "xml-name-validator": { + "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, - "xmlchars": { + "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "xtend": { + "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } }, - "y18n": { + "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } }, - "yallist": { + "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "yaml": { + "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "yargs": { + "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "requires": { + "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", @@ -7171,18 +9581,27 @@ "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" } }, - "yargs-parser": { + "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } }, - "yn": { + "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "devOptional": true, + "engines": { + "node": ">=6" + } } } } diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 217cfb53..e1f22d4a 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -205,7 +205,6 @@ export class CohortService { ) { try { - let { limit, page, filters } = cohortSearchDto; let offset = 0; @@ -227,20 +226,18 @@ export class CohortService { whereClause['tenantId'] = tenantId; } - - const [results, totalCount] = await this.cohortRepository.findAndCount({ where: whereClause, skip: offset, }); - console.log(results); + const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ - statusCode: 200, - message: 'Ok.', - totalCount, - data: results, + statusCode: 200, + message: 'Ok.', + totalCount, + data: mappedResponse, }); } catch (e) { @@ -253,23 +250,26 @@ export class CohortService { } public async mappedResponse(result: any) { - const cohortMapping = { - tenantId: result?.tenantId ? `${result.tenantId}` : "", - programId: result?.programId ? `${result.programId}` : "", - cohortId: result?.cohortId ? `${result.cohortId}` : "", - parentId: result?.parentId ? `${result.parentId}` : "", - name: result?.name ? `${result.name}` : "", - type: result?.type ? `${result.type}` : "", - status: result?.status ? `${result.status}` : "", - image: result?.image ? `${result.image}` : "", - createdAt: result?.createdAt ? `${result.createdAt}` : "", - updatedAt: result?.updatedAt ? `${result.updatedAt}` : "", - createdBy: result?.createdBy ? `${result.createdBy}` : "", - updatedBy: result?.updatedBy ? `${result.updatedBy}` : "", - referenceId: result?.referenceId ? `${result.referenceId}` : "", - metadata: result?.metadata ? `${result.metadata}` : "", - }; - - return new CohortDto(cohortMapping); + const cohortValueResponse = result.map((item: any) => { + const cohortMapping = { + tenantId: item?.tenantId ? `${item.tenantId}` : "", + programId: item?.programId ? `${item.programId}` : "", + cohortId: item?.cohortId ? `${item.cohortId}` : "", + parentId: item?.parentId ? `${item.parentId}` : "", + name: item?.name ? `${item.name}` : "", + type: item?.type ? `${item.type}` : "", + status: item?.status ? `${item.status}` : "", + image: item?.image ? `${item.image}` : "", + createdAt: item?.createdAt ? `${item.createdAt}` : "", + updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", + createdBy: item?.createdBy ? `${item.createdBy}` : "", + updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + referenceId: item?.referenceId ? `${item.referenceId}` : "", + metadata: item?.metadata ? `${item.metadata}` : "", + }; + return new CohortDto(cohortMapping); + }) + return cohortValueResponse; + } } diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 66de19d2..d9259122 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -83,12 +83,18 @@ export class FieldsService { skip: offset, }); + // console.log(results); + + + const mappedResponse = await this.mappedResponseField(results); + return new SuccessResponse({ statusCode: 200, message: 'Ok.', totalCount, - data: results, + data: mappedResponse, }); + } catch (e) { console.error(e); return new ErrorResponse({ @@ -226,4 +232,41 @@ export class FieldsService { return fieldValueResponse; } + + public async mappedResponseField(result: any) { + const fieldResponse = result.map((item: any) => { + + const fieldMapping = { + fieldId: item?.fieldId ? `${item.fieldId}` : "", + assetId: item?.assetId ? `${item.assetId}` : "", + context: item?.context ? `${item.context}` : "", + groupId: item?.groupId ? `${item.groupId}` : "", + name: item?.name ? `${item.name}` : "", + label: item?.label ? `${item.label}` : "", + defaultValue: item?.defaultValue ? `${item.defaultValue}` : "", + type: item?.type ? `${item.type}` : "", + note: item?.note ? `${item.note}` : "", + description: item?.description ? `${item.description}` : "", + state: item?.state ? `${item.state}` : "", + required: item?.required ? `${item.required}` : "", + ordering: item?.ordering ? `${item.ordering}` : "", + metadata: item?.metadata ? `${item.metadata}` : "", + access: item?.access ? `${item.access}` : "", + onlyUseInSubform: item?.onlyUseInSubform ? `${item.onlyUseInSubform}` : "", + tenantId: item?.tenantId ? `${item.tenantId}` : "", + createdAt: item?.createdAt ? `${item.createdAt}` : "", + updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", + createdBy: item?.createdBy ? `${item.createdBy}` : "", + updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + contextId: item?.contextId ? `${item.contextId}` : "", + render: item?.render ? `${item.render}` : "", + contextType: item?.contextType ? `${item.contextType}` : "", + fieldParams: item?.fieldParams ? JSON.stringify(item.fieldParams) : "" + }; + + return new FieldsDto(fieldMapping); + }); + + return fieldResponse; + } } From 4e6b10e417c1eb8302812c83b40b552bf9202fb3 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sun, 24 Mar 2024 04:07:21 +0530 Subject: [PATCH 106/408] add --- src/cohort/entities/cohort.entity.ts | 6 ++ src/cohortMembers/cohortMember.service.ts | 93 +++++++++++++++++++ src/cohortMembers/cohortMembers.controller.ts | 10 +- src/cohortMembers/cohortMembers.module.ts | 6 +- .../entities/cohort-member.entity.ts | 57 ++++++++++++ 5 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 src/cohortMembers/cohortMember.service.ts create mode 100644 src/cohortMembers/entities/cohort-member.entity.ts diff --git a/src/cohort/entities/cohort.entity.ts b/src/cohort/entities/cohort.entity.ts index c190de8d..a18abd1e 100644 --- a/src/cohort/entities/cohort.entity.ts +++ b/src/cohort/entities/cohort.entity.ts @@ -4,7 +4,9 @@ import { Column, CreateDateColumn, UpdateDateColumn, + ManyToMany, } from "typeorm"; +import { CohortMembers } from "../../cohortMembers/entities/cohort-member.entity"; @Entity({ name: "Cohort" }) export class Cohort { @@ -64,4 +66,8 @@ export class Cohort { default: () => "CURRENT_TIMESTAMP", }) updatedBy: Date; + + @ManyToMany(() => CohortMembers, cohortMember => cohortMember.cohorts) + cohortMembers: CohortMembers[]; + } diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts new file mode 100644 index 00000000..32ce7833 --- /dev/null +++ b/src/cohortMembers/cohortMember.service.ts @@ -0,0 +1,93 @@ +import { Injectable } from "@nestjs/common"; +import { HttpService } from "@nestjs/axios"; +import { SuccessResponse } from "src/success-response"; +import { ErrorResponse } from "src/error-response"; +const resolvePath = require("object-resolve-path"); +import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; +import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-search.dto"; +import { CohortMembers } from "./entities/cohort-member.entity"; +import { InjectRepository } from "@nestjs/typeorm"; +import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; + +@Injectable() +export class CohortMembersService { + + constructor( + @InjectRepository(CohortMembers) + private cohortMemberRepository: Repository, + ) { } + + + public async searchCohortMembers( + tenantId: string, + request: any, + cohortMembersSearchDto: CohortMembersSearchDto + ) { + try { + + let { limit, page, filters } = cohortMembersSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + else { + whereClause['tenantId'] = tenantId; + } + + const [results, totalCount] = await this.cohortMemberRepository.findAndCount({ + where: whereClause, + skip: offset, + // relations: ['cohorts'], + }); + + const mappedResponse = await this.mappedResponse(results); + + return new SuccessResponse({ + statusCode: 200, + message: 'Ok.', + totalCount, + data: mappedResponse, + }); + + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, + }); + } + } + + + + public async mappedResponse(result: any) { + const cohortMembersResponse = result.map((obj: any) => { + const cohortMembersMapping = { + tenantId: obj?.tenantId ? `${obj.tenantId}` : "", + cohortMembershipId: obj?.cohortMembershipId? `${obj.cohortMembershipId}`: "", + cohortId: obj?.cohortId ? `${obj.cohortId}` : "", + userId: obj?.userId ? `${obj.userId}` : "", + role: obj?.role ? `${obj.role}` : "", + createdAt: obj?.createdAt ? `${obj.createdAt}` : "", + updatedAt: obj?.updatedAt ? `${obj.updatedAt}` : "", + createdBy: obj?.createdBy ? `${obj.createdBy}` : "", + updatedBy: obj?.updatedBy ? `${obj.updatedBy}` : "", + }; + return new CohortMembersDto(cohortMembersMapping); + }); + + return cohortMembersResponse; + } +} diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 1abdffd1..8ca34c7b 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -25,11 +25,15 @@ import { CohortMembersSearchDto } from "./dto/cohortMembers-search.dto"; import { Request } from "@nestjs/common"; import { CohortMembersDto } from "./dto/cohortMembers.dto"; import { CohortMembersAdapter } from "./cohortMembersadapter"; +import { CohortMembersService } from "./cohortMember.service"; @ApiTags("Cohort Members") @Controller("cohortmembers") export class CohortMembersController { - constructor(private cohortMembersAdapter: CohortMembersAdapter) {} + constructor( + private cohortMembersAdapter: CohortMembersAdapter, + private readonly cohortMembersService: CohortMembersService + ) {} //create cohort members @Post() @@ -101,9 +105,7 @@ export class CohortMembersController { @Body() cohortMembersSearchDto: CohortMembersSearchDto ) { let tenantid = headers["tenantid"]; - return this.cohortMembersAdapter - .buildCohortMembersAdapter() - .searchCohortMembers(tenantid, request, cohortMembersSearchDto); + return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto); } //update diff --git a/src/cohortMembers/cohortMembers.module.ts b/src/cohortMembers/cohortMembers.module.ts index eb0f145f..09252024 100644 --- a/src/cohortMembers/cohortMembers.module.ts +++ b/src/cohortMembers/cohortMembers.module.ts @@ -3,9 +3,13 @@ import { CohortMembersController } from "./cohortMembers.controller"; import { HttpModule } from "@nestjs/axios"; import { CohortMembersAdapter } from "./cohortMembersadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { CohortMembers } from "./entities/cohort-member.entity"; +import { CohortMembersService } from "./cohortMember.service"; const ttl = process.env.TTL as never; @Module({ imports: [ + TypeOrmModule.forFeature([CohortMembers]), HttpModule, HasuraModule, CacheModule.register({ @@ -13,6 +17,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [CohortMembersController], - providers: [CohortMembersAdapter], + providers: [CohortMembersAdapter, CohortMembersService], }) export class CohortMembersModule {} diff --git a/src/cohortMembers/entities/cohort-member.entity.ts b/src/cohortMembers/entities/cohort-member.entity.ts new file mode 100644 index 00000000..211e986b --- /dev/null +++ b/src/cohortMembers/entities/cohort-member.entity.ts @@ -0,0 +1,57 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToMany, + JoinTable, +} from 'typeorm'; + +import { Cohort } from "../../cohort/entities/cohort.entity"; + +@Entity({ name: 'CohortMembers' }) +export class CohortMembers { + @PrimaryGeneratedColumn('uuid') + cohortMembershipId: string; + + @Column({ type: 'varchar', length: 255 }) + role: string; + + @Column({ type: 'uuid' }) + tenantId: string; + + @Column({ type: 'uuid', nullable: true }) + cohortId: string | null; + + @Column({ type: 'uuid', nullable: true }) + userId: string | null; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdBy: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedBy: Date; + + @ManyToMany(() => Cohort, cohort => cohort.cohortMembers) + @JoinTable({ name: 'cohort_members_cohort' }) // Specify the join table name here + cohorts: Cohort[]; +} From aabfbec8a0fee592427785f4d65da5a7c27b5974 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sun, 24 Mar 2024 13:34:44 +0530 Subject: [PATCH 107/408] Search Cohort Using UserId --- src/cohortMembers/cohortMember.service.ts | 53 +++++++------------ src/cohortMembers/cohortMembers.controller.ts | 4 +- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 32ce7833..83ad371e 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -8,6 +8,7 @@ import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-sear import { CohortMembers } from "./entities/cohort-member.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; +import { CohortDto } from "../cohort/dto/cohort.dto"; @Injectable() export class CohortMembersService { @@ -21,7 +22,8 @@ export class CohortMembersService { public async searchCohortMembers( tenantId: string, request: any, - cohortMembersSearchDto: CohortMembersSearchDto + cohortMembersSearchDto: CohortMembersSearchDto, + res: any, ) { try { @@ -46,20 +48,24 @@ export class CohortMembersService { whereClause['tenantId'] = tenantId; } - const [results, totalCount] = await this.cohortMemberRepository.findAndCount({ - where: whereClause, - skip: offset, - // relations: ['cohorts'], - }); + // const [results, totalCount] = await this.cohortMemberRepository.findAndCount({ + // where: whereClause, + // skip: offset, + // // relations: ['cohorts'], + // }); + // console.log(whereClause); + let userId; + if (whereClause['userId']) { + userId = whereClause['userId']; - const mappedResponse = await this.mappedResponse(results); + } + + let query = `SELECT C."cohortId",C."attendanceCaptureImage", C."parentId", C."type", C."programId", C."name",CM."userId" FROM public."CohortMembers" CM + LEFT JOIN public."Cohort" C + ON C."cohortId" = CM."cohortId" where CM."userId" =$1`; - return new SuccessResponse({ - statusCode: 200, - message: 'Ok.', - totalCount, - data: mappedResponse, - }); + const results = await this.cohortMemberRepository.query(query, [userId]); + res.status(200).json(results); } catch (e) { console.error(e); @@ -69,25 +75,4 @@ export class CohortMembersService { }); } } - - - - public async mappedResponse(result: any) { - const cohortMembersResponse = result.map((obj: any) => { - const cohortMembersMapping = { - tenantId: obj?.tenantId ? `${obj.tenantId}` : "", - cohortMembershipId: obj?.cohortMembershipId? `${obj.cohortMembershipId}`: "", - cohortId: obj?.cohortId ? `${obj.cohortId}` : "", - userId: obj?.userId ? `${obj.userId}` : "", - role: obj?.role ? `${obj.role}` : "", - createdAt: obj?.createdAt ? `${obj.createdAt}` : "", - updatedAt: obj?.updatedAt ? `${obj.updatedAt}` : "", - createdBy: obj?.createdBy ? `${obj.createdBy}` : "", - updatedBy: obj?.updatedBy ? `${obj.updatedBy}` : "", - }; - return new CohortMembersDto(cohortMembersMapping); - }); - - return cohortMembersResponse; - } } diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 8ca34c7b..0c1bb75d 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -20,6 +20,7 @@ import { Req, CacheInterceptor, Headers, + Res, } from "@nestjs/common"; import { CohortMembersSearchDto } from "./dto/cohortMembers-search.dto"; import { Request } from "@nestjs/common"; @@ -102,10 +103,11 @@ export class CohortMembersController { public async searchCohortMembers( @Headers() headers, @Req() request: Request, + @Res() res: Response, @Body() cohortMembersSearchDto: CohortMembersSearchDto ) { let tenantid = headers["tenantid"]; - return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto); + return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto,res); } //update From 8cbd1701fa93af37f517091e52f9a41eacc85821 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sun, 24 Mar 2024 13:40:35 +0530 Subject: [PATCH 108/408] Search Cohort Using UserId --- src/cohortMembers/cohortMember.service.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 83ad371e..e66724ea 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -48,23 +48,21 @@ export class CohortMembersService { whereClause['tenantId'] = tenantId; } - // const [results, totalCount] = await this.cohortMemberRepository.findAndCount({ - // where: whereClause, - // skip: offset, - // // relations: ['cohorts'], - // }); - // console.log(whereClause); - let userId; + let searchData; + let searchField; if (whereClause['userId']) { - userId = whereClause['userId']; - + searchData = whereClause['userId']; + searchField = `CM."userId" =$1` + }else if(whereClause['cohortId']){ + searchData = whereClause['cohortId']; + searchField = `CM."cohortId" =$1` } let query = `SELECT C."cohortId",C."attendanceCaptureImage", C."parentId", C."type", C."programId", C."name",CM."userId" FROM public."CohortMembers" CM LEFT JOIN public."Cohort" C - ON C."cohortId" = CM."cohortId" where CM."userId" =$1`; + ON C."cohortId" = CM."cohortId" where ${searchField}`; - const results = await this.cohortMemberRepository.query(query, [userId]); + const results = await this.cohortMemberRepository.query(query, [searchData]); res.status(200).json(results); } catch (e) { From 83f1f7918e7fbb6543da1c5194874c4ed4b5339c Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Sun, 24 Mar 2024 23:25:25 +0530 Subject: [PATCH 109/408] Fix[attendance report API] --- src/attendance/attendance.controller.ts | 23 ++++++++++++ src/attendance/attendance.service.ts | 37 ++++++++++++++++++++ src/attendance/dto/attendance-stats.dto.ts | 32 +++++++++++++++++ src/attendance/dto/attendance.dto.ts | 1 + src/attendance/entities/attendance.entity.ts | 8 ++++- 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/attendance/dto/attendance-stats.dto.ts diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 0c6672b5..d26dfa97 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -38,6 +38,7 @@ import { AttendanceHasuraService } from "src/adapters/hasura/attendance.adapter" import { AttendaceAdapter } from "./attendanceadapter"; import { AttendanceDateDto } from "./dto/attendance-date.dto"; import { AttendanceService } from './attendance.service'; +import { AttendanceStatsDto } from "./dto/attendance-stats.dto"; @ApiTags("Attendance") @Controller("attendance") @@ -198,6 +199,28 @@ export class AttendanceController { .multipleAttendance(tenantid, request, attendanceDtos); } + @Post("/report") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Attendance list." }) + @ApiBody({ type: AttendanceSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + @SerializeOptions({ + strategy: "excludeAll", + }) + @UsePipes(ValidationPipe) + + + public async report( + @Headers() headers, + @Req() request: Request, + @Body() attendanceStatsDto: AttendanceStatsDto + ) { + let tenantid = headers["tenantid"]; + return this.attendaceService + .attendanceReport(attendanceStatsDto.contextId); + } + /** No longer required in Shiksha 2.0 */ /* @Get("usersegment/:attendance") diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 6ae3c1bd..9dc8e134 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -12,6 +12,8 @@ import { SuccessResponse } from 'src/success-response'; import { AttendanceDto } from './dto/attendance.dto'; import { AttendanceDateDto } from './dto/attendance-date.dto'; import { Between } from 'typeorm'; +import { AttendanceStatsDto } from './dto/attendance-stats.dto'; +import { User } from 'src/user/entities/user-entity'; @@ -71,6 +73,29 @@ export class AttendanceService { } } + async attendanceReport(contextId:string) { + const query = ` + SELECT + u."name", + COUNT(CASE WHEN aa."attendance" = 'Present' THEN 1 END) * 100.0 / COUNT(aa."attendance") AS attendance_percentage +FROM + public."Attendance" AS aa +INNER JOIN + public."Users" AS u ON aa."userId" = u."userId" +WHERE + aa."attendance" IN ('Present', 'Absent') + AND u."role" = 'student' + AND aa."contextId" = $1 +GROUP BY + u."name", + u."role"; + `; + + const result = await this.attendanceRepository.query(query,[contextId]); + return await this.mapResponseforReport(result); + + } + public async mappedResponse(result: any) { const attendanceResponse = result.map((item: any) => { const attendanceMapping = { @@ -100,6 +125,18 @@ export class AttendanceService { return attendanceResponse; } + public async mapResponseforReport(result: any) { + const attendanceReport = result.map((item: any) => { + const attendanceReportMapping = { + name: item?.name ? `${item.name}` : "", + attendance_percentage: item?.attendance_percentage ? `${item.attendance_percentage}` : "", + }; + + return new AttendanceStatsDto(attendanceReportMapping); + }); + + return attendanceReport; + } /* Method to create,update or add attendance for valid user in attendance table @body an object of details consisting of attendance details of user (attendance dto) diff --git a/src/attendance/dto/attendance-stats.dto.ts b/src/attendance/dto/attendance-stats.dto.ts new file mode 100644 index 00000000..a07adb4a --- /dev/null +++ b/src/attendance/dto/attendance-stats.dto.ts @@ -0,0 +1,32 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { Expose } from "class-transformer"; +import { IsNotEmpty, IsNumberString, IsString, IsUUID } from 'class-validator'; + +export class AttendanceStatsDto { + @ApiProperty({ + type: String, + description: "The name of the person", + }) + @Expose() + name: string; + + @ApiProperty({ + type: String, + description: "The name of the person", + }) + @IsNotEmpty() + @IsUUID() + @Expose() + contextId: string; + + @ApiProperty({ + type: String, + description: "The attendance percentage of the person", + }) + @Expose() + attendance_percentage: string; + + constructor(obj: Partial) { + Object.assign(this, obj); + } +} diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index ee9af021..d3f28988 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -119,6 +119,7 @@ export class AttendanceDto { default: "", }) @IsNotEmpty() + @IsUUID() @Expose() contextId: string; diff --git a/src/attendance/entities/attendance.entity.ts b/src/attendance/entities/attendance.entity.ts index faa60c3c..92f65564 100644 --- a/src/attendance/entities/attendance.entity.ts +++ b/src/attendance/entities/attendance.entity.ts @@ -1,4 +1,6 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; +import { Cohort } from 'src/cohort/entities/cohort.entity'; +import { User } from 'src/user/entities/user-entity'; +import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, JoinColumn } from 'typeorm'; @Entity({name:"Attendance"}) export class AttendanceEntity { @@ -11,6 +13,10 @@ export class AttendanceEntity { @Column() userId: string; + @ManyToOne(() => User, {nullable:true}) + @JoinColumn({ name: 'userId' }) + user: User; + @Column({ type: 'date' }) attendanceDate: Date; From ff20661399594517fda9f5334a3da76e19f39d98 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Sun, 24 Mar 2024 23:31:07 +0530 Subject: [PATCH 110/408] Fix[error handling] --- src/attendance/attendance.service.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 9dc8e134..bec05720 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -74,6 +74,7 @@ export class AttendanceService { } async attendanceReport(contextId:string) { + try{ const query = ` SELECT u."name", @@ -92,7 +93,23 @@ GROUP BY `; const result = await this.attendanceRepository.query(query,[contextId]); - return await this.mapResponseforReport(result); + const report= await this.mapResponseforReport(result); + + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: report, + }); + } + catch(error){ + + return new ErrorResponse({ + errorCode: "500", + errorMessage: error, + }); + + + } } From a2d922839043828d16272421acab4d81389894a0 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 25 Mar 2024 00:14:57 +0530 Subject: [PATCH 111/408] Fix[attendance validation for bulk attendance] --- src/attendance/attendance.service.ts | 2 +- src/attendance/dto/attendance.dto.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index bec05720..f80d6bef 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -375,7 +375,7 @@ GROUP BY let count = 1; for (const attendance of attendanceData) { - if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance && attendance.contextId) { + if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance &&(attendance.attendance === "present" || attendance.attendance === "absent") && attendance.contextId) { attendance.tenantId = tenantId; const attendanceRes: any = await this.updateAttendanceRecord( diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index d3f28988..990ca5a2 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -11,7 +11,6 @@ import { HttpException, HttpStatus } from '@nestjs/common'; enum Attendance{ present="present", absent="absent", - halfDay="halfday" } export class AttendanceDto { From 917a2b291e4d8b0e5877a8cf0d8b73badb8fef83 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 25 Mar 2024 10:52:37 +0530 Subject: [PATCH 112/408] Fix[Removed enum validation for attendance] --- src/attendance/attendance.service.ts | 2 +- src/attendance/dto/attendance.dto.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index f80d6bef..c6de6542 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -375,7 +375,7 @@ GROUP BY let count = 1; for (const attendance of attendanceData) { - if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance &&(attendance.attendance === "present" || attendance.attendance === "absent") && attendance.contextId) { + if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance && attendance.contextId) { attendance.tenantId = tenantId; const attendanceRes: any = await this.updateAttendanceRecord( diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 990ca5a2..6babc011 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -8,10 +8,10 @@ import { format, isAfter } from 'date-fns'; // Import isAfter function from date import { HttpException, HttpStatus } from '@nestjs/common'; -enum Attendance{ - present="present", - absent="absent", -} +// enum Attendance{ +// present="present", +// absent="absent", +// } export class AttendanceDto { @Expose() @@ -52,7 +52,7 @@ export class AttendanceDto { }) @Expose() @IsNotEmpty() - @IsEnum(Attendance,{message:"Please enter valid enum [present or absent]"}) + // @IsEnum(Attendance,{message:"Please enter valid enum [present or absent]"}) attendance: string; @ApiProperty({ From 8677966989775d8e8ca905d643537eafd444a518 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 25 Mar 2024 11:05:02 +0530 Subject: [PATCH 113/408] Fix[change in enum values] --- src/attendance/attendance.service.ts | 2 +- src/attendance/dto/attendance.dto.ts | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index c6de6542..7ab402f9 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -375,7 +375,7 @@ GROUP BY let count = 1; for (const attendance of attendanceData) { - if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance && attendance.contextId) { + if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance &&(attendance.attendance === "present" || attendance.attendance === "absent" ) && attendance.contextId) { attendance.tenantId = tenantId; const attendanceRes: any = await this.updateAttendanceRecord( diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 6babc011..75f68adb 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -7,11 +7,14 @@ import { User } from 'src/user/entities/user-entity'; import { format, isAfter } from 'date-fns'; // Import isAfter function from date-fns import { HttpException, HttpStatus } from '@nestjs/common'; - -// enum Attendance{ -// present="present", -// absent="absent", -// } +//for student valid enum are[present,absent] +//for teacher valid enum are[present,on-leave,half-day] +enum Attendance{ + present="present", + absent="absent", + onLeave="on-leave", + halfDay="half-day" +} export class AttendanceDto { @Expose() @@ -52,7 +55,7 @@ export class AttendanceDto { }) @Expose() @IsNotEmpty() - // @IsEnum(Attendance,{message:"Please enter valid enum [present or absent]"}) + @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) attendance: string; @ApiProperty({ From 5dab80d389e108af902463114d3452c04c5b29b1 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Mon, 25 Mar 2024 20:33:14 +0530 Subject: [PATCH 114/408] Added create ,get, search cohort member API --- src/cohortMembers/cohortMember.service.ts | 202 +++++++++++++----- src/cohortMembers/cohortMembers.controller.ts | 43 ++-- .../entities/cohort-member.entity.ts | 96 ++++----- 3 files changed, 223 insertions(+), 118 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index e66724ea..bf90e99a 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -9,68 +9,168 @@ import { CohortMembers } from "./entities/cohort-member.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { CohortDto } from "../cohort/dto/cohort.dto"; +import APIResponse from "src/utils/response"; +import { HttpStatus } from "@nestjs/common"; +import response from "src/utils/response"; +import { User } from "src/user/entities/user-entity"; @Injectable() export class CohortMembersService { + constructor( + @InjectRepository(CohortMembers) + private cohortMembersRepository: Repository + ) {} - constructor( - @InjectRepository(CohortMembers) - private cohortMemberRepository: Repository, - ) { } + public async getCohortMembers( + tenantId: string, + cohortMembershipId: any, + response: any, + request: any + ) { + const apiId = "api.cohortMember.getCohortMembers"; + try { + const cohortMembers = await this.cohortMembersRepository.find({ + where: { + tenantId: tenantId, + cohortMembershipId: cohortMembershipId, + }, + }); + if (!cohortMembers || cohortMembers.length === 0) { + return response + .status(HttpStatus.NOT_FOUND) + .send( + APIResponse.error( + apiId, + `Cohort Member Id is wrong`, + `Cohort Member not found`, + "COHORT_Member_NOT_FOUND" + ) + ); + } + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + cohortMembers, + "Cohort Member Retrieved Successfully" + ) + ); + } catch (error) { + return response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong", + `Failure Retrieving Cohort Member. Error is: ${error}`, + "INTERNAL_SERVER_ERROR" + ) + ); + } + } + + public async searchCohortMembers( + tenantId: string, + request: any, + cohortMembersSearchDto: CohortMembersSearchDto, + response: any + ) { + const apiId = "api.cohortMember.searchCohortMembers"; + + try { + let offset = 0; + if (cohortMembersSearchDto.page > 1) { + offset = + parseInt(cohortMembersSearchDto.limit) * + (cohortMembersSearchDto.page - 1); + } - public async searchCohortMembers( - tenantId: string, - request: any, - cohortMembersSearchDto: CohortMembersSearchDto, - res: any, - ) { - try { + let filters: any = { tenantId: tenantId || "" }; + const tempFilters = { ...cohortMembersSearchDto.filters }; - let { limit, page, filters } = cohortMembersSearchDto; + // Convert filter keys to match TypeORM column names + Object.keys(tempFilters).forEach((item) => { + Object.keys(tempFilters[item]).forEach((e) => { + if (!e.startsWith("_")) { + tempFilters[item][`_${e}`] = tempFilters[item][e]; + delete tempFilters[item][e]; + } + }); + }); - let offset = 0; - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } + filters = { ...filters, ...tempFilters }; - if (limit.trim() === '') { - limit = '0'; - } + const takeLimit = parseInt(cohortMembersSearchDto.limit); // Parse limit value here + + const [cohortMembers, count] = + await this.cohortMembersRepository.findAndCount({ + where: filters, + take: takeLimit, // Use parsed limit value here + skip: offset, + }); + const responseData = { + totalCount: count, + cohortMembers: cohortMembers, + }; + + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + responseData, + "Cohort Member Retrieved Successfully" + ) + ); + } catch (error) { + return response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong", + `Failure Retrieving Cohort Member. Error is: ${error}`, + "INTERNAL_SERVER_ERROR" + ) + ); + } + } - const whereClause = {}; - if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } - else { - whereClause['tenantId'] = tenantId; - } - - let searchData; - let searchField; - if (whereClause['userId']) { - searchData = whereClause['userId']; - searchField = `CM."userId" =$1` - }else if(whereClause['cohortId']){ - searchData = whereClause['cohortId']; - searchField = `CM."cohortId" =$1` - } - - let query = `SELECT C."cohortId",C."attendanceCaptureImage", C."parentId", C."type", C."programId", C."name",CM."userId" FROM public."CohortMembers" CM - LEFT JOIN public."Cohort" C - ON C."cohortId" = CM."cohortId" where ${searchField}`; + public async createCohortMembers( + request: any, + cohortMembers: CohortMembersDto, + response: any + ) { + const apiId = "api.cohortMember.getCohortMembers"; - const results = await this.cohortMemberRepository.query(query, [searchData]); - res.status(200).json(results); + try { + // Create a new CohortMembers entity and populate it with cohortMembers data + const savedCohortMember = await this.cohortMembersRepository.save( + cohortMembers + ); - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "401", - errorMessage: e, - }); - } + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + savedCohortMember, + "Cohort Member created Successfully" + ) + ); + } catch (error) { + return response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong", + `Failure creating Cohort Member. Error is: ${error}`, + "INTERNAL_SERVER_ERROR" + ) + ); } + } } diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 0c1bb75d..d5f83889 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -27,6 +27,7 @@ import { Request } from "@nestjs/common"; import { CohortMembersDto } from "./dto/cohortMembers.dto"; import { CohortMembersAdapter } from "./cohortMembersadapter"; import { CohortMembersService } from "./cohortMember.service"; +import { Response } from "@nestjs/common"; @ApiTags("Cohort Members") @Controller("cohortmembers") @@ -34,7 +35,7 @@ export class CohortMembersController { constructor( private cohortMembersAdapter: CohortMembersAdapter, private readonly cohortMembersService: CohortMembersService - ) {} + ) {} //create cohort members @Post() @@ -51,7 +52,8 @@ export class CohortMembersController { public async createCohortMembers( @Headers() headers, @Req() request: Request, - @Body() cohortMembersDto: CohortMembersDto + @Body() cohortMembersDto: CohortMembersDto, + @Res() response: Response ) { let tenantid = headers["tenantid"]; const payload = { @@ -59,9 +61,11 @@ export class CohortMembersController { }; Object.assign(cohortMembersDto, payload); - return this.cohortMembersAdapter - .buildCohortMembersAdapter() - .createCohortMembers(request, cohortMembersDto); + return this.cohortMembersService.createCohortMembers( + request, + cohortMembersDto, + response + ); } //get cohort members @@ -79,12 +83,16 @@ export class CohortMembersController { public async getCohortMembers( @Headers() headers, @Param("id") cohortMembersId: string, - @Req() request: Request + @Req() request: Request, + @Res() response: Response ) { let tenantid = headers["tenantid"]; - return this.cohortMembersAdapter - .buildCohortMembersAdapter() - .getCohortMembers(tenantid, cohortMembersId, request); + return this.cohortMembersService.getCohortMembers( + tenantid, + cohortMembersId, + response, + request + ); } //search @@ -103,11 +111,16 @@ export class CohortMembersController { public async searchCohortMembers( @Headers() headers, @Req() request: Request, - @Res() res: Response, + @Res() response: Response, @Body() cohortMembersSearchDto: CohortMembersSearchDto ) { let tenantid = headers["tenantid"]; - return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto,res); + return this.cohortMembersService.searchCohortMembers( + tenantid, + request, + cohortMembersSearchDto, + response + ); } //update @@ -124,10 +137,8 @@ export class CohortMembersController { @Req() request: Request, @Body() cohortMembersipDto: CohortMembersDto ) { - return this.cohortMembersAdapter.buildCohortMembersAdapter().updateCohortMembers( - cohortMembersId, - request, - cohortMembersipDto - ); + return this.cohortMembersAdapter + .buildCohortMembersAdapter() + .updateCohortMembers(cohortMembersId, request, cohortMembersipDto); } } diff --git a/src/cohortMembers/entities/cohort-member.entity.ts b/src/cohortMembers/entities/cohort-member.entity.ts index 211e986b..80117c19 100644 --- a/src/cohortMembers/entities/cohort-member.entity.ts +++ b/src/cohortMembers/entities/cohort-member.entity.ts @@ -1,57 +1,51 @@ import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, - ManyToMany, - JoinTable, -} from 'typeorm'; + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToMany, + JoinTable, +} from "typeorm"; import { Cohort } from "../../cohort/entities/cohort.entity"; -@Entity({ name: 'CohortMembers' }) +@Entity({ name: "CohortMembers" }) export class CohortMembers { - @PrimaryGeneratedColumn('uuid') - cohortMembershipId: string; - - @Column({ type: 'varchar', length: 255 }) - role: string; - - @Column({ type: 'uuid' }) - tenantId: string; - - @Column({ type: 'uuid', nullable: true }) - cohortId: string | null; - - @Column({ type: 'uuid', nullable: true }) - userId: string | null; - - @CreateDateColumn({ - type: "timestamp with time zone", - default: () => "CURRENT_TIMESTAMP", - }) - createdAt: Date; - - @UpdateDateColumn({ - type: "timestamp with time zone", - default: () => "CURRENT_TIMESTAMP", - }) - updatedAt: Date; - - @CreateDateColumn({ - type: "timestamp with time zone", - default: () => "CURRENT_TIMESTAMP", - }) - createdBy: Date; - - @UpdateDateColumn({ - type: "timestamp with time zone", - default: () => "CURRENT_TIMESTAMP", - }) - updatedBy: Date; - - @ManyToMany(() => Cohort, cohort => cohort.cohortMembers) - @JoinTable({ name: 'cohort_members_cohort' }) // Specify the join table name here - cohorts: Cohort[]; + @PrimaryGeneratedColumn("uuid") + cohortMembershipId: string; + + @Column({ type: "varchar", length: 255 }) + role: string; + + @Column({ type: "uuid" }) + tenantId: string; + + @Column({ type: "uuid", nullable: true }) + cohortId: string | null; + + @Column({ type: "uuid" }) + userId: string; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + + @Column({}) + createdBy: string; + + @Column({}) + updatedBy: string; + + @ManyToMany(() => Cohort, (cohort) => cohort.cohortMembers) + @JoinTable({ name: "cohort_members_cohort" }) // Specify the join table name here + cohorts: Cohort[]; } From f2353ca7d9f5a638b06035702f313735f4562157 Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 26 Mar 2024 14:52:29 +0530 Subject: [PATCH 115/408] Task #216298:Update Profile wth Custom field Support --- package-lock.json | 13 ++++ package.json | 1 + src/cohort/cohort.service.ts | 6 +- src/user/dto/user-update.dto.ts | 79 +++++++++++++++++++++++ src/user/entities/field-value-entities.ts | 4 +- src/user/user.controller.ts | 15 +++-- src/user/user.module.ts | 4 +- src/user/user.service.ts | 74 ++++++++++++++++++--- 8 files changed, 173 insertions(+), 23 deletions(-) create mode 100644 src/user/dto/user-update.dto.ts diff --git a/package-lock.json b/package-lock.json index f438591c..02681d8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "@types/jest": "27.4.1", "@types/node": "^16.0.0", "@types/supertest": "^2.0.11", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", "eslint": "^8.0.1", @@ -2205,6 +2206,12 @@ "@types/superagent": "*" } }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", @@ -11331,6 +11338,12 @@ "@types/superagent": "*" } }, + "@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", diff --git a/package.json b/package.json index a470ee4c..9db5a5d6 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@types/jest": "27.4.1", "@types/node": "^16.0.0", "@types/supertest": "^2.0.11", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", "eslint": "^8.0.1", diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 036b407e..56e92a1f 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -15,7 +15,7 @@ import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { FieldsService } from "src/adapters/hasura/services/fields.service"; -import { FieldValues } from "src/fields/entities/field-values.entity"; +// import { FieldValues } from "src/fields/entities/field-values.entity"; import { response } from "express"; import APIResponse from "src/utils/response"; @@ -25,9 +25,9 @@ export class CohortService { constructor( @InjectRepository(Cohort) - @InjectRepository(FieldValues) + // @InjectRepository(FieldValues) private cohortRepository: Repository, - private readonly fieldsService: FieldsService + // private readonly fieldsService: FieldsService ) {} public async getCohort( diff --git a/src/user/dto/user-update.dto.ts b/src/user/dto/user-update.dto.ts new file mode 100644 index 00000000..f7b58ea8 --- /dev/null +++ b/src/user/dto/user-update.dto.ts @@ -0,0 +1,79 @@ +import { IsString, IsOptional, IsArray, ValidateNested } from 'class-validator'; +import { Type } from 'class-transformer'; + +class UserDataDTO { + + @IsString() + username: string; + + @IsString() + name: string; + + @IsString() + role: string; + + @IsOptional() + dob: string | null; + + @IsOptional() + @IsString() + email: string | null; + + @IsOptional() + @IsString() + district: string | null; + + @IsOptional() + @IsString() + state: string | null; + + @IsOptional() + @IsString() + address: string | null; + + @IsOptional() + @IsString() + pincode: string | null; + + @IsString() + createdAt: string; + + @IsString() + updatedAt: string; + + @IsString() + createdBy: string; + + @IsString() + updatedBy: string; + + @IsString() + tenantId: string; + + @IsString() + status: string; +} + +class CustomFieldDTO { + @IsString() + fieldId: string; + + @IsString() + value: string; +} + +export class UserUpdateDTO { + + @IsString() + userId: string; + + + @ValidateNested() + @Type(() => UserDataDTO) + userData: UserDataDTO; + + @IsArray() + @ValidateNested({ each: true }) + @Type(() => CustomFieldDTO) + customFields: CustomFieldDTO[]; +} diff --git a/src/user/entities/field-value-entities.ts b/src/user/entities/field-value-entities.ts index 0a3d6f40..ff8ff7eb 100644 --- a/src/user/entities/field-value-entities.ts +++ b/src/user/entities/field-value-entities.ts @@ -2,14 +2,14 @@ import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateCol // import { Field } from './Field'; // Assuming you have a Field entity defined @Entity({ name: 'FieldValues' }) -export class FieldValue { +export class FieldValues { @PrimaryGeneratedColumn('uuid', { name: 'fieldValuesId' }) fieldValuesId: string; @Column({ type: 'text', nullable: false }) value: string; - @Column({ type: 'uuid', nullable: false, default: () => 'gen_random_uuid()' }) + @Column({ type: 'uuid', nullable: false}) itemId: string; @Column({ type: 'uuid', nullable: false, name: 'fieldId' }) diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index ae3d78b8..3ccaba1b 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -14,6 +14,7 @@ import { Query, Headers, Res, + Patch, } from "@nestjs/common"; import { SunbirdUserToken, @@ -36,6 +37,7 @@ import { UserSearchDto } from "./dto/user-search.dto"; import { UserAdapter } from "./useradapter"; import { UserCreateDto } from "./dto/user-create.dto"; import { UserService } from "./user.service"; +import { UserUpdateDTO } from "./dto/user-update.dto"; @ApiTags("User") @Controller("user") export class UserController { @@ -117,7 +119,8 @@ export class UserController { return this.userService.createUser(request, userCreateDto,response); } - @Put("/:userid") + + @Patch("/:userid") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User has been updated successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -129,12 +132,12 @@ export class UserController { @Headers() headers, @Param("userid") userId: string, @Req() request: Request, - @Body() userDto: UserCreateDto + @Body() userUpdateDto:UserUpdateDTO, + @Res() response: Response ) { - userDto.tenantId = headers["tenantid"]; - return await this.userAdapter - .buildUserAdapter() - .updateUser(userId, request, userDto); + // userDto.tenantId = headers["tenantid"]; + userUpdateDto.userId=userId; + return await this.userService.updateUser(userUpdateDto,response) } @Post("/search") diff --git a/src/user/user.module.ts b/src/user/user.module.ts index e113ad28..d6c4cec6 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -7,14 +7,14 @@ import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { TypeOrmModule } from "@nestjs/typeorm"; import { User } from "./entities/user-entity"; import { UserService } from "./user.service"; -import { FieldValue } from "./entities/field-value-entities"; +import { FieldValues } from "./entities/field-value-entities"; import { Field } from "./entities/field-entity"; const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([ User, - FieldValue, + FieldValues, Field ]), HttpModule, diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 1069bd89..e1639952 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -1,6 +1,6 @@ import { HttpStatus, Injectable } from '@nestjs/common'; import { User } from './entities/user-entity' -import { FieldValue } from './entities/field-value-entities'; +import { FieldValues } from './entities/field-value-entities'; import ApiResponse from '../utils/response' import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; @@ -16,6 +16,8 @@ import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; import { Field } from './entities/field-entity'; import APIResponse from '../utils/response'; +import { v5 as uuidv5 } from 'uuid'; +import { UUID } from 'typeorm/driver/mongodb/bson.typings'; @Injectable() @@ -24,8 +26,8 @@ export class UserService { constructor( @InjectRepository(User) private usersRepository: Repository, - @InjectRepository(FieldValue) - private fieldsValueRepository: Repository, + @InjectRepository(FieldValues) + private fieldsValueRepository: Repository, @InjectRepository(Field) private fieldsRepository : Repository ) {} @@ -37,8 +39,6 @@ export class UserService { customFields: [] }; - // const customFields = await this.findCustomFields(userData); - // const filledValues = await this.findFilledValues(userData?.userId); const [customFields, filledValues,userDetails] = await Promise.all([ this.findCustomFields(userData), this.findFilledValues(userData.userId), @@ -99,7 +99,61 @@ export class UserService { return result; } - public async createUser(request: any, userCreateDto: UserCreateDto,response) { + async updateUser(userDto,response){ + const apiId = 'api.users.UpdateUserDetails' + try { + let updatedData = {}; + if(userDto.userData || Object.keys(userDto.userData).length > 0){ + await this.updateBasicUserDetails(userDto.userId,userDto.userData); + updatedData['basicDetails'] = userDto.userData; + } + if(userDto.customFields.length > 0){ + for (let data of userDto.customFields) { + const result = await this.updateCustomFields(userDto.userId, data); + if (result) { + if (!updatedData['customFields']) + updatedData['customFields']= []; + updatedData['customFields'].push(result); + } + } + } + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, updatedData, 'OK')); + } catch (e) { + response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + 'Something went wrong In finding UserDetails', + e, + 'INTERNAL_SERVER_ERROR', + ), + ); + } + } + + async updateBasicUserDetails(userId,userData: Partial): Promise { + const user = await this.usersRepository.findOne({ where: { userId: userId } }); + if (!user) { + return null; + } + Object.assign(user, userData); + + return this.usersRepository.save(user); + } + + async updateCustomFields(itemId,data){ + const result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); + + if (result.affected === 0) { + return null; + } + return result; + } + + async createUser(request: any, userCreateDto: UserCreateDto,response) { // It is considered that if user is not present in keycloak it is not present in database as well let apiId='api.user.creatUser' try { @@ -144,7 +198,7 @@ export class UserService { } // Can be Implemeneted after we know what are the unique entties -async checkUserinKeyCloakandDb(userDto){ + async checkUserinKeyCloakandDb(userDto){ const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( @@ -154,9 +208,9 @@ async checkUserinKeyCloakandDb(userDto){ if(usernameExistsInKeycloak){ return usernameExistsInKeycloak; } -} + } -async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { + async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { let userData = { username:userCreateDto?.username, name:userCreateDto?.name, @@ -174,7 +228,7 @@ async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { message: "Ok.", data: result, });} -} + } From f925b74c741efe9b26295e26e8c33742c11b088c Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 26 Mar 2024 15:22:44 +0530 Subject: [PATCH 116/408] Task #216298: Updated View Profile with Updated response --- package-lock.json | 7249 +------------------------------------- src/user/user.service.ts | 4 +- 2 files changed, 11 insertions(+), 7242 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57dcf0eb..a576ce7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4981,6 +4981,15 @@ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, + "node_modules/graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/graphql-tag": { "version": "2.12.6", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", @@ -9610,7245 +9619,5 @@ "node": ">=6" } } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.0" - } - }, - "@angular-devkit/core": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.6.tgz", - "integrity": "sha512-8h2mWdBTN/dYwZuzKMg2IODlOWMdbJcpQG4XVrkk9ejCPP+3aX5Aa3glCe/voN6eBNiRfs8YDM0jxmpN2aWVtg==", - "dev": true, - "requires": { - "ajv": "8.9.0", - "ajv-formats": "2.1.1", - "fast-json-stable-stringify": "2.1.0", - "magic-string": "0.25.7", - "rxjs": "6.6.7", - "source-map": "0.7.3" - }, - "dependencies": { - "ajv": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", - "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - } - } - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/schematics": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.6.tgz", - "integrity": "sha512-mPgSqdnZRuPSMeUA+T+mwVCrq2yhXpcYm1/Rjbhy09CyHs4wSrFv21WHCrE6shlvXpcmwr0n+I0DIeagAPmjUA==", - "dev": true, - "requires": { - "@angular-devkit/core": "13.2.6", - "jsonc-parser": "3.0.0", - "magic-string": "0.25.7", - "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/schematics-cli": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-13.2.6.tgz", - "integrity": "sha512-VdMLn4DoTswjk+1RL+pod8EwLkzh8pMT2OBJ9dhsITru1sr0/2nhsqRwZzZylAXjrFwdfPj1E/vfcAfSkmMGvw==", - "dev": true, - "requires": { - "@angular-devkit/core": "13.2.6", - "@angular-devkit/schematics": "13.2.6", - "ansi-colors": "4.1.1", - "inquirer": "8.2.0", - "minimist": "1.2.5", - "symbol-observable": "4.0.0" - }, - "dependencies": { - "inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - } - } - } - }, - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", - "dev": true - }, - "@babel/core": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.7.tgz", - "integrity": "sha512-djHlEfFHnSnTAcPb7dATbiM5HxGOP98+3JLBZtjRb5I7RXrw7kFRoG2dXM8cm3H+o11A8IFH/uprmJpwFynRNQ==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.7", - "@babel/parser": "^7.17.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true - }, - "@babel/helpers": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.7.tgz", - "integrity": "sha512-TKsj9NkjJfTBxM7Phfy7kv6yYc4ZcOo+AaWGqQOKTPDOmcGkIFb5xNA746eKisQkm4yavUYh4InYM9S+VnO01w==", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - } - }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.7.tgz", - "integrity": "sha512-bm3AQf45vR4gKggRfvJdYJ0gFLoCbsPxiFLSH6hTVYABptNHY6l9NrhnucVjQ/X+SPtLANT9lc0fFhikj+VBRA==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", - "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "devOptional": true - }, - "@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "devOptional": true, - "requires": { - "@cspotcode/source-map-consumer": "0.8.0" - } - }, - "@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "peer": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "peer": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "peer": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "peer": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "peer": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "peer": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "peer": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dev": true, - "requires": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", - "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" - } - }, - "@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - } - }, - "@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@nestjs/axios": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.0.7.tgz", - "integrity": "sha512-at8nj+1Nb8UleHcIN5QqZYeWX54m4m9s9gxzVE1qWy00neX2rg0+h2TfbWsnDi2tc23zIxqexanxMOJZbzO0CA==", - "requires": { - "axios": "0.26.0" - }, - "dependencies": { - "axios": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", - "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", - "requires": { - "follow-redirects": "^1.14.8" - } - } - } - }, - "@nestjs/cli": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-8.2.3.tgz", - "integrity": "sha512-p//DACefn40VClXroxzS+2pkSdaXYvKKcr4bFOUBMTdJqT9he+U9ifcJUkg/h1bFU/Y8SS2cUsTyl0ZBHHHRcw==", - "dev": true, - "requires": { - "@angular-devkit/core": "13.2.6", - "@angular-devkit/schematics": "13.2.6", - "@angular-devkit/schematics-cli": "13.2.6", - "@nestjs/schematics": "^8.0.3", - "chalk": "3.0.0", - "chokidar": "3.5.3", - "cli-table3": "0.6.1", - "commander": "4.1.1", - "fork-ts-checker-webpack-plugin": "7.2.1", - "inquirer": "7.3.3", - "node-emoji": "1.11.0", - "ora": "5.4.1", - "os-name": "4.0.1", - "rimraf": "3.0.2", - "shelljs": "0.8.5", - "source-map-support": "0.5.21", - "tree-kill": "1.2.2", - "tsconfig-paths": "3.14.0", - "tsconfig-paths-webpack-plugin": "3.5.2", - "typescript": "4.6.2", - "webpack": "5.70.0", - "webpack-node-externals": "3.0.0" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } - } - }, - "@nestjs/common": { - "version": "8.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-8.4.3.tgz", - "integrity": "sha512-QIhWykB7IPOwHQB/K9wMwmQKibQ5dhg9dt8ySOoD36uFFwN3RJQelzMFF9Rtu7hrMPk6pSyismEUKQ8BZMUD9w==", - "requires": { - "axios": "0.26.1", - "iterare": "1.2.1", - "tslib": "2.3.1", - "uuid": "8.3.2" - } - }, - "@nestjs/config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.0.0.tgz", - "integrity": "sha512-Hi1k/1S5ogsS5c0OtNm72thiLSngijOaLDFaGI5ZPxNGpF23lctPg6ox3pYIOhXVRX/u+eiUIp71gswH2k8YNw==", - "requires": { - "dotenv": "16.0.0", - "dotenv-expand": "8.0.2", - "lodash": "4.17.21", - "uuid": "8.3.2" - } - }, - "@nestjs/core": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-8.4.1.tgz", - "integrity": "sha512-JUV2cy/5z8MS2SRwszLmyOCclMMlyumxIbC1YFFlnSInhu7ODhrHLIMztyGmyAIuaehbOnyXPtHkjl01rHxc5w==", - "requires": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "object-hash": "3.0.0", - "path-to-regexp": "3.2.0", - "tslib": "2.3.1", - "uuid": "8.3.2" - } - }, - "@nestjs/jwt": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-8.0.0.tgz", - "integrity": "sha512-fz2LQgYY2zmuD8S+8UE215anwKyXlnB/1FwJQLVR47clNfMeFMK8WCxmn6xdPhF5JKuV1crO6FVabb1qWzDxqQ==", - "requires": { - "@types/jsonwebtoken": "8.5.4", - "jsonwebtoken": "8.5.1" - } - }, - "@nestjs/mapped-types": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz", - "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==", - "requires": {} - }, - "@nestjs/platform-express": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-8.4.1.tgz", - "integrity": "sha512-c18zuhoegJsS1vZueGaNyvU8mLyFtS+6FJ2WAzDOXNpchpq0okrEPdKBifIisWuxgffQYKIufoK73vEfXSfDLg==", - "requires": { - "body-parser": "1.19.2", - "cors": "2.8.5", - "express": "4.17.3", - "multer": "1.4.4", - "tslib": "2.3.1" - } - }, - "@nestjs/schedule": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-1.1.0.tgz", - "integrity": "sha512-0QpbwClUildXqlyoaygG+aIQZNNMv31XDyQxX+Ob1zw/3I8+AVrDlBwZHQ+tlhIcJFR8aG+VTH8xwIjXwtS1UA==", - "requires": { - "cron": "1.8.2", - "uuid": "8.3.2" - } - }, - "@nestjs/schematics": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-8.0.8.tgz", - "integrity": "sha512-xIIb5YnMQN/OJQ68+MCapy2bXvTxSWgINoqQbyZWkLL/yTIuROvZCdtV850NPGyr7f7l93VBP0ZPitbFIexy3Q==", - "dev": true, - "requires": { - "@angular-devkit/core": "13.2.5", - "@angular-devkit/schematics": "13.2.5", - "fs-extra": "10.0.1", - "jsonc-parser": "3.0.0", - "pluralize": "8.0.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "13.2.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.5.tgz", - "integrity": "sha512-WuWp/1R0FtCHPBcJLF13lTLHETtDGFUX0ULfGPRaYB5OVCSQcovVp5UbZTTy/Ss3ub3EOEmJlU8kMJfBrWuq+A==", - "dev": true, - "requires": { - "ajv": "8.9.0", - "ajv-formats": "2.1.1", - "fast-json-stable-stringify": "2.1.0", - "magic-string": "0.25.7", - "rxjs": "6.6.7", - "source-map": "0.7.3" - } - }, - "@angular-devkit/schematics": { - "version": "13.2.5", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.5.tgz", - "integrity": "sha512-kAye6VYiF9JQAoeO+BYhy8eT2QOmhB+WLziRjXoFCBxh5+yXTygTVfs9fD5jmIpHmeu4hd2ErSh69yT5xWcD9g==", - "dev": true, - "requires": { - "@angular-devkit/core": "13.2.5", - "jsonc-parser": "3.0.0", - "magic-string": "0.25.7", - "ora": "5.4.1", - "rxjs": "6.6.7" - } - }, - "ajv": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", - "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - } - } - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@nestjs/swagger": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-5.2.1.tgz", - "integrity": "sha512-7dNa08WCnTsW/oAk3Ujde+z64JMfNm19DhpXasFR8oJp/9pggYAbYU927HpA+GJsSFJX6adjIRZsCKUqaGWznw==", - "requires": { - "@nestjs/mapped-types": "1.0.1", - "lodash": "4.17.21", - "path-to-regexp": "3.2.0" - } - }, - "@nestjs/testing": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-8.4.1.tgz", - "integrity": "sha512-LOvsLuNh2eRwAtyeoIZWmUZ08wt7QrPrKQujWuRyv+vBYtC+FLHjqreWLpwG2yulNEoQs9Qlr2ubPvFGT1953g==", - "dev": true, - "requires": { - "optional": "0.1.4", - "tslib": "2.3.1" - } - }, - "@nestjs/typeorm": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", - "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", - "requires": { - "uuid": "9.0.1" - }, - "dependencies": { - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "requires": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "peer": true - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sqltools/formatter": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", - "peer": true - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "devOptional": true - }, - "@tsconfig/node12": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "devOptional": true - }, - "@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "devOptional": true - }, - "@tsconfig/node16": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "devOptional": true - }, - "@types/babel__core": { - "version": "7.1.18", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.18.tgz", - "integrity": "sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@types/cache-manager": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-3.4.3.tgz", - "integrity": "sha512-71aBXoFYXZW4TnDHHH8gExw2lS28BZaWeKefgsiJI7QYZeJfUEbMKw6CQtzGjlYQcGIWwB76hcCrkVA3YHSvsw==", - "dev": true - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "requires": { - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", - "dev": true - }, - "@types/cron": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@types/cron/-/cron-1.7.3.tgz", - "integrity": "sha512-iPmUXyIJG1Js+ldPYhOQcYU3kCAQ2FWrSkm1FJPoii2eYSn6wEW6onPukNTT0bfiflexNSRPl6KWmAIqS+36YA==", - "dev": true, - "requires": { - "@types/node": "*", - "moment": ">=2.14.0" - } - }, - "@types/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "requires": { - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", - "dev": true, - "requires": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" - } - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/jsonwebtoken": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", - "integrity": "sha512-4L8msWK31oXwdtC81RmRBAULd0ShnAHjBuKT9MRQpjP0piNrZdXyTRcKY9/UIfhGeKIT4PvF5amOOUbbT/9Wpg==", - "requires": { - "@types/node": "*" - } - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "@types/node": { - "version": "16.11.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", - "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==" - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/prettier": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", - "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", - "dev": true, - "requires": { - "@types/cookiejar": "*", - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "@types/supertest": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.11.tgz", - "integrity": "sha512-uci4Esokrw9qGb9bvhhSVEjd6rkny/dk5PK/Qz4yxKiyppEI+dOPlNrZBahE3i+PoKFYyDxChVXZ/ysS/nrm1Q==", - "dev": true, - "requires": { - "@types/superagent": "*" - } - }, - "@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true - }, - "@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", - "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/type-utils": "5.15.0", - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", - "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", - "debug": "^4.3.2" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", - "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", - "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", - "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", - "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", - "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", - "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.15.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "devOptional": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - } - } - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "devOptional": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "dependencies": { - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "peer": true - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "app-root-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", - "peer": true - }, - "append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - }, - "babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dev": true, - "requires": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - } - } - }, - "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "browserslist": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.0.tgz", - "integrity": "sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001313", - "electron-to-chromium": "^1.4.76", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "requires": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "cache-manager": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-3.6.1.tgz", - "integrity": "sha512-jxJvGYhN5dUgpriAdsDnnYbKse4dEXI5i3XpwTfPq5utPtXH1uYXWyGLHGlbSlh9Vq4ytrgAUVwY+IodNeKigA==", - "requires": { - "async": "3.2.3", - "lodash": "^4.17.21", - "lru-cache": "6.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001317", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz", - "integrity": "sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "ci-info": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", - "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "class-transformer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" - }, - "class-validator": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz", - "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==", - "requires": { - "libphonenumber-js": "^1.9.43", - "validator": "^13.7.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "peer": true, - "requires": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "dependencies": { - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "peer": true - } - } - }, - "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true - }, - "cli-table3": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", - "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", - "dev": true, - "requires": { - "colors": "1.4.0", - "string-width": "^4.2.0" - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "optional": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true - }, - "cron": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz", - "integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==", - "requires": { - "moment-timezone": "^0.5.x" - } - }, - "cron-parser": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", - "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", - "requires": { - "is-nan": "^1.3.2", - "luxon": "^1.26.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", - "peer": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "requires": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true - }, - "diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, - "dotenv": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", - "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" - }, - "dotenv-expand": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.2.tgz", - "integrity": "sha512-vKKAk+VOzAWOV/dPIeSYqhgC/TQY+6L6Ibkzfsr8xd1stdBsTuGu9asCOXgbYbBeS+f2Y6lqqEuw7riOA+xEUQ==" - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "peer": true - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "electron-to-chromium": { - "version": "1.4.84", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.84.tgz", - "integrity": "sha512-b+DdcyOiZtLXHdgEG8lncYJdxbdJWJvclPNMg0eLUDcSOSO876WA/pYjdSblUTd7eJdIs4YdIxHWGazx7UPSJw==", - "dev": true - }, - "emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - } - } - }, - "eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - } - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" - } - }, - "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - } - } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "peer": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "peer": true - } - } - }, - "fork-ts-checker-webpack-plugin": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.1.tgz", - "integrity": "sha512-uOfQdg/iQ8iokQ64qcbu8iZb114rOmaKLQFu7hU14/eJaKgsP91cQ7ts7v2iiDld6TzDe84Meksha8/MkWiCyw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "schema-utils": "4.0.0", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz", - "integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==", - "dev": true, - "requires": { - "dezalgo": "1.0.3", - "hexoid": "1.0.0", - "once": "1.4.0", - "qs": "6.9.3" - }, - "dependencies": { - "qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==", - "dev": true - } - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "graphql": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz", - "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==", - "peer": true - }, - "graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "requires": { - "tslib": "^2.1.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "peer": true - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "iterare": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==" - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "peer": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "import-local": "^3.0.2", - "jest-cli": "^27.5.1" - } - }, - "jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" - } - }, - "jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - } - }, - "jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dev": true, - "requires": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true - }, - "jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", - "dev": true, - "requires": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "dev": true - }, - "jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - } - }, - "jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - } - } - }, - "jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dev": true, - "requires": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dev": true, - "requires": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - } - }, - "jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" - } - }, - "jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - } - } - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "dependencies": { - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - } - } - }, - "libphonenumber-js": { - "version": "1.9.50", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.50.tgz", - "integrity": "sha512-cCzQPChw2XbordcO2LKiw5Htx5leHVfFk/EXkxNHqJfFo7Fndcb1kF5wPJpc316vCJhhikedYnVysMh3Sc7Ocw==" - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "long-timeout": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", - "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "luxon": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", - "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==" - }, - "macos-release": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", - "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", - "dev": true - }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", - "dev": true, - "requires": { - "fs-monkey": "1.0.3" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "peer": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" - }, - "moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "multer": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", - "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "requires": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "dependencies": { - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "peer": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node-cron": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.1.tgz", - "integrity": "sha512-RAWZTNn2M5KDIUV/389UX0EXsqvdFAwc9QwHQceh0Ga56dygqSRthqIjwpgZsoDspHGt2rkHdk9Z4RgfPMdALw==" - }, - "node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "requires": { - "lodash": "^4.17.21" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - }, - "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true - }, - "node-schedule": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.0.tgz", - "integrity": "sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==", - "requires": { - "cron-parser": "^3.5.0", - "long-timeout": "0.1.1", - "sorted-array-functions": "^1.3.0" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" - }, - "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-resolve-path": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-resolve-path/-/object-resolve-path-1.1.1.tgz", - "integrity": "sha1-p/j5Poogr4DkQhe6fbVDFtnRIjI=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optional": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/optional/-/optional-0.1.4.tgz", - "integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==", - "dev": true - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "dependencies": { - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - } - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "os-name": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", - "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", - "dev": true, - "requires": { - "macos-release": "^2.5.0", - "windows-release": "^4.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "peer": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "peer": true, - "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "peer": true - } - } - }, - "path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "requires": { - "split2": "^4.1.0" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" - }, - "postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", - "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "peer": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "peer": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "peer": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "superagent": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz", - "integrity": "sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ==", - "dev": true, - "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.3", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "^2.5.0", - "qs": "^6.10.1", - "readable-stream": "^3.6.0", - "semver": "^7.3.5" - }, - "dependencies": { - "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - } - } - }, - "supertest": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz", - "integrity": "sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^7.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "swagger-ui-dist": { - "version": "4.10.3", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.10.3.tgz", - "integrity": "sha512-eR4vsd7sYo0Sx7ZKRP5Z04yij7JkNmIlUQfrDQgC+xO5ABYx+waabzN+nDsQTLAJ4Z04bjkRd8xqkJtbxr3G7w==" - }, - "swagger-ui-express": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.3.0.tgz", - "integrity": "sha512-jN46SEEe9EoXa3ZgZoKgnSF6z0w3tnM1yqhO4Y+Q4iZVc8JOQB960EZpIAz6rNROrDApVDwcMHR0mhlnc/5Omw==", - "requires": { - "swagger-ui-dist": ">=4.1.3" - } - }, - "symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "templates.js": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/templates.js/-/templates.js-0.3.11.tgz", - "integrity": "sha1-qAtXgaoySmHpK+GmlHDVATQd6QQ=" - }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, - "terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", - "dev": true, - "requires": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", - "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", - "dev": true, - "requires": { - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "peer": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "peer": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "dependencies": { - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "ts-jest": { - "version": "27.1.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.3.tgz", - "integrity": "sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" - } - }, - "ts-loader": { - "version": "9.2.8", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", - "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - } - }, - "ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", - "devOptional": true, - "requires": { - "@cspotcode/source-map-support": "0.7.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", - "yn": "3.1.1" - } - }, - "tsconfig-paths": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.0.tgz", - "integrity": "sha512-cg/1jAZoL57R39+wiw4u/SCC6Ic9Q5NqjBOb+9xISedOYurfog9ZNmKJSxAnb2m/5Bq4lE9lhUcau33Ml8DM0g==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "tsconfig-paths-webpack-plugin": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz", - "integrity": "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tsconfig-paths": "^3.9.0" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typeorm": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", - "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", - "peer": true, - "requires": { - "@sqltools/formatter": "^1.2.5", - "app-root-path": "^3.1.0", - "buffer": "^6.0.3", - "chalk": "^4.1.2", - "cli-highlight": "^2.1.11", - "dayjs": "^1.11.9", - "debug": "^4.3.4", - "dotenv": "^16.0.3", - "glob": "^10.3.10", - "mkdirp": "^2.1.3", - "reflect-metadata": "^0.2.1", - "sha.js": "^2.4.11", - "tslib": "^2.5.0", - "uuid": "^9.0.0", - "yargs": "^17.6.2" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "peer": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "peer": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "peer": true - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "peer": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "peer": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", - "peer": true - }, - "reflect-metadata": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", - "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", - "peer": true - }, - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "peer": true - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "peer": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "peer": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "peer": true - } - } - }, - "typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", - "devOptional": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8-compile-cache-lib": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", - "devOptional": true - }, - "v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", - "webpack-sources": "^3.2.3" - } - }, - "webpack-node-externals": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", - "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", - "dev": true - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "windows-release": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", - "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", - "dev": true, - "requires": { - "execa": "^4.0.2" - }, - "dependencies": { - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "peer": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true - } } } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index e1639952..53096c0c 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -45,13 +45,13 @@ export class UserService { this.findUserDetails(userData.userId) ]); const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); - for (const data of customFields) { + for (let data of customFields) { const fieldValue = filledValuesMap.get(data.fieldId); const customField = { fieldId: data.fieldId, label: data.label, value: fieldValue || '', - options: data.fieldParams || {}, + options: data?.fieldParams?.['options'] || {}, type: data.type || '' }; result.customFields.push(customField); From 74a172cfeb15fe5c31333e24632b3abda42ef16a Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Tue, 26 Mar 2024 15:54:23 +0530 Subject: [PATCH 117/408] Fix[request body change for bulk attendance] --- src/attendance/attendance.controller.ts | 8 ++-- src/attendance/attendance.service.ts | 36 +++++---------- src/attendance/dto/attendance.dto.ts | 58 +++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index d26dfa97..c0aa15ad 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -29,7 +29,7 @@ import { UsePipes, ValidationPipe, } from "@nestjs/common"; -import { AttendanceDto } from "./dto/attendance.dto"; +import { AttendanceDto, BulkAttendanceDTO } from "./dto/attendance.dto"; import { FileInterceptor } from "@nestjs/platform-express"; import { diskStorage } from "multer"; import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; @@ -74,7 +74,6 @@ export class AttendanceController { @Post() - @UsePipes(new ValidationPipe()) @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ @@ -95,6 +94,7 @@ export class AttendanceController { @ApiHeader({ name: "tenantid", }) + @UsePipes(ValidationPipe) public async createAttendace( @Headers() headers, @Req() request: Request, @@ -182,7 +182,7 @@ export class AttendanceController { @ApiCreatedResponse({ description: "Attendance has been created successfully.", }) - @ApiBody({ type: [AttendanceDto] }) + @ApiBody({ type: BulkAttendanceDTO }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ @@ -192,7 +192,7 @@ export class AttendanceController { public async multipleAttendance( @Headers() headers, @Req() request: Request, - @Body() attendanceDtos: [AttendanceDto] + @Body() attendanceDtos: BulkAttendanceDTO ) { let tenantid = headers["tenantid"]; return this.attendaceService diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 7ab402f9..7b8baf9e 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -9,7 +9,7 @@ import { BadRequestException, HttpException, HttpStatus, Injectable } from "@nes import { ErrorResponse } from "src/error-response"; import { AttendanceSearchDto } from "./dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; -import { AttendanceDto } from './dto/attendance.dto'; +import { AttendanceDto, BulkAttendanceDTO } from './dto/attendance.dto'; import { AttendanceDateDto } from './dto/attendance-date.dto'; import { Between } from 'typeorm'; import { AttendanceStatsDto } from './dto/attendance-stats.dto'; @@ -167,7 +167,6 @@ GROUP BY try { - if (!isAfter(new Date(attendanceDto.attendanceDate), new Date()) && attendanceDto.attendanceDate) { const decoded: any = jwt_decode(request?.headers?.authorization); const userId = @@ -210,13 +209,6 @@ GROUP BY return await this.createAttendance(request, attendanceDto); } - } - else { - return new ErrorResponse({ - errorCode: '500', - errorMessage: "Date cannot be from future", - }); - } } catch (e) { return e; } @@ -367,20 +359,23 @@ GROUP BY public async multipleAttendance( tenantId: string, request: any, - attendanceData: [AttendanceDto] + attendanceData: BulkAttendanceDTO ) { const responses = []; const errors = []; try { let count = 1; - for (const attendance of attendanceData) { - if (attendance.userId && !isAfter(new Date(attendance.attendanceDate), new Date()) && attendance.attendanceDate && attendance.attendance &&(attendance.attendance === "present" || attendance.attendance === "absent" ) && attendance.contextId) { - - attendance.tenantId = tenantId; + for (let attendance of attendanceData.userAttendance) { + const userNewAttendance = new AttendanceDto({ + attendanceDate: attendanceData.attendanceDate, + contextId: attendanceData.contextId, + attendance: attendance.attendance, + userId: attendance.userId + }) const attendanceRes: any = await this.updateAttendanceRecord( request, - attendance + userNewAttendance ); if (attendanceRes?.statusCode === 200) { responses.push(attendanceRes.data); @@ -391,15 +386,6 @@ GROUP BY }); } count++; - } - - else { - errors.push({ - message: `userId should not be empty null or undefined for record or attendance date should not be of future for ${count} or attendance should be valid enum value[present,absent,halfday] or contextId should be present` - - }); - count++; - } } } catch (e) { @@ -410,7 +396,7 @@ GROUP BY return { statusCode: 200, - totalCount: attendanceData.length, + totalCount: attendanceData.userAttendance.length, successCount: responses.length, errorCount: errors.length, responses, diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 75f68adb..36b8fd7a 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -1,10 +1,10 @@ import { ManyToOne, JoinColumn } from 'typeorm'; -import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; +import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, Validate, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; import { Exclude, Expose, Transform } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsObject } from 'class-validator'; import { User } from 'src/user/entities/user-entity'; -import { format, isAfter } from 'date-fns'; // Import isAfter function from date-fns +import { format, isAfter, isBefore, isValid } from 'date-fns'; // Import isAfter function from date-fns import { HttpException, HttpStatus } from '@nestjs/common'; //for student valid enum are[present,absent] @@ -16,6 +16,16 @@ enum Attendance{ halfDay="half-day" } +@ValidatorConstraint({ name: 'isNotAfterToday', async: false }) +export class IsNotAfterToday implements ValidatorConstraintInterface { + validate(date: Date, args: ValidationArguments) { + return isBefore(date, new Date()); + } + + defaultMessage(args: ValidationArguments) { + return 'Attendance date must not be after today'; + } +} export class AttendanceDto { @Expose() attendanceId: string; @@ -44,7 +54,10 @@ export class AttendanceDto { default: new Date() }) @IsNotEmpty() - @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @Validate(IsNotAfterToday, { + message: 'Attendance date must not be after today', + }) @Expose() attendanceDate: Date; @@ -141,3 +154,42 @@ export class AttendanceDto { Object.assign(this, obj); } } + + +export class UserAttendanceDTO { + @IsUUID() + @IsNotEmpty() + userId: string; + + @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) + @IsNotEmpty() + // Assuming these are the possible values for attendance + attendance: string; +} + +export class BulkAttendanceDTO { + @ApiProperty({ + type: String, + description: "The date of the attendance in format yyyy-mm-dd", + default: new Date() + }) + @IsNotEmpty() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @Validate(IsNotAfterToday, { + message: 'Attendance date must not be after today', + }) + @Expose() + attendanceDate: Date; + + @IsUUID() + @Expose() + + contextId: string; + + // Adjust the max size according to your requirements + userAttendance: UserAttendanceDTO[]; + + constructor(obj: any) { + Object.assign(this, obj); + } +} From d37d2f3b6c1cbb45acd5b77a60e77c9bb772032b Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Tue, 26 Mar 2024 16:10:40 +0530 Subject: [PATCH 118/408] Fix[change in object name and removed validation from contextId for self attendance ] --- src/attendance/attendance.service.ts | 4 ++-- src/attendance/dto/attendance.dto.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 7b8baf9e..24f0f8e1 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -367,7 +367,7 @@ GROUP BY let count = 1; for (let attendance of attendanceData.userAttendance) { - const userNewAttendance = new AttendanceDto({ + const userAttendance = new AttendanceDto({ attendanceDate: attendanceData.attendanceDate, contextId: attendanceData.contextId, attendance: attendance.attendance, @@ -375,7 +375,7 @@ GROUP BY }) const attendanceRes: any = await this.updateAttendanceRecord( request, - userNewAttendance + userAttendance ); if (attendanceRes?.statusCode === 200) { responses.push(attendanceRes.data); diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 36b8fd7a..9c24f471 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -133,8 +133,8 @@ export class AttendanceDto { description: "The contextId of the attendance", default: "", }) - @IsNotEmpty() - @IsUUID() + + @Expose() contextId: string; @@ -183,6 +183,7 @@ export class BulkAttendanceDTO { @IsUUID() @Expose() + @IsNotEmpty() contextId: string; From fbe28b1f82db810f1433de6f2fdbe05ede994fe1 Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 26 Mar 2024 16:18:51 +0530 Subject: [PATCH 119/408] Task #216180 : Added GetUserDetails API --- src/auth/auth-service.ts | 33 +++++++++++++++++++++++++++++---- src/auth/auth.controller.ts | 18 ++++++++++++++++++ src/auth/auth.module.ts | 12 +++++++++++- src/user/user.service.ts | 12 ++++++++---- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/auth/auth-service.ts b/src/auth/auth-service.ts index 65a4d8f8..a810447b 100644 --- a/src/auth/auth-service.ts +++ b/src/auth/auth-service.ts @@ -1,6 +1,9 @@ -import { Injectable } from '@nestjs/common'; +import { HttpStatus, Injectable } from '@nestjs/common'; +import { UserService } from '../user/user.service'; import axios from 'axios'; import qs from 'qs' +import jwt_decode from "jwt-decode"; +import APIResponse from 'src/utils/response'; @@ -8,9 +11,8 @@ import qs from 'qs' @Injectable() export class AuthService { private axiosInstance; - constructor(){ - this.axiosInstance = axios.create(); - } + constructor(private readonly userService: UserService){ + this.axiosInstance = axios.create();} async login(authDto,response){ try{ @@ -39,4 +41,27 @@ export class AuthService { return response.status(500).send({ message: 'An error occurred during login.' }); } } + + public async getUserByAuth(request: any,response) { + let apiId = 'api.auth.getUserDetails'; + try { + const decoded: any = jwt_decode(request.headers.authorization); + const username = decoded.preferred_username; + let data = await this.userService.findUserDetails(null,username) + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, data, 'OK')); + }catch(e){ + response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + 'Something went wrong In finding UserDetails', + e, + 'INTERNAL_SERVER_ERROR', + ), + ); + } +} } \ No newline at end of file diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 117b9609..f99c1358 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -3,6 +3,8 @@ import { ApiBody, ApiForbiddenResponse, ApiHeader, + ApiBasicAuth, + ApiOkResponse, } from "@nestjs/swagger"; import { Controller, @@ -45,4 +47,20 @@ export class AuthController { console.log(request) return this.authService.login(authDto,response); } + + @Get('/getUserDetails') + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "User detail." }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async getUserByAuth(@Req() request: Request,@Res() response:Response){ + // const tenantId = headers["tenantid"]; + return this.authService.getUserByAuth(request,response); + } + } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 2a884be6..a4590764 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -2,16 +2,26 @@ import { CacheModule, Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { AuthController } from "./auth.controller"; import { AuthService } from "./auth-service"; +import { UserService } from "src/user/user.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import {User} from '../user/entities/user-entity'; +import { FieldValues } from '../user/entities/field-value-entities' +import { Field } from "src/user/entities/field-entity"; const ttl = process.env.TTL as never; @Module({ imports: [ + TypeOrmModule.forFeature([ + User, + FieldValues, + Field + ]), HttpModule, CacheModule.register({ ttl: ttl, }), ], controllers: [AuthController], - providers: [AuthService], + providers: [AuthService,UserService], }) export class AuthModule {} diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 53096c0c..4f2e438d 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -18,6 +18,7 @@ import { Field } from './entities/field-entity'; import APIResponse from '../utils/response'; import { v5 as uuidv5 } from 'uuid'; import { UUID } from 'typeorm/driver/mongodb/bson.typings'; +import { AnyARecord } from 'dns'; @Injectable() @@ -74,11 +75,14 @@ export class UserService { } } - async findUserDetails(userId){ + async findUserDetails(userId,username?:any){ + let whereClause:any = { userId: userId }; + if(username && userId === null){ + delete whereClause.userId; + whereClause.username = username; + } let userDetails = await this.usersRepository.findOne({ - where:{ - userId:userId - } + where:whereClause }) return userDetails; } From a6eaa09d3cf20f0f40b1f24d19576480477f4ab6 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Tue, 26 Mar 2024 17:37:31 +0530 Subject: [PATCH 120/408] Update cohort member --- src/cohortMembers/cohortMember.service.ts | 48 ++++++++++++- src/cohortMembers/cohortMembers.controller.ts | 15 +++-- .../dto/cohortMember-update.dto.ts | 67 +++++++++++++++++++ 3 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 src/cohortMembers/dto/cohortMember-update.dto.ts diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index bf90e99a..1ebce52b 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -13,6 +13,7 @@ import APIResponse from "src/utils/response"; import { HttpStatus } from "@nestjs/common"; import response from "src/utils/response"; import { User } from "src/user/entities/user-entity"; +import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; @Injectable() export class CohortMembersService { @@ -143,7 +144,7 @@ export class CohortMembersService { cohortMembers: CohortMembersDto, response: any ) { - const apiId = "api.cohortMember.getCohortMembers"; + const apiId = "api.cohortMember.createCohortMembers"; try { // Create a new CohortMembers entity and populate it with cohortMembers data @@ -173,4 +174,49 @@ export class CohortMembersService { ); } } + + public async updateCohortMembers( + cohortMembershipId: string, + request: any, + cohortMembersUpdateDto: CohortMembersUpdateDto, + response: any + ) { + const apiId = "api.cohortMember.updateCohortMembers"; + + try { + const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ + where: { cohortMembershipId: cohortMembershipId }, + }); + + if (!cohortMemberToUpdate) { + throw new Error("Cohort member not found"); + } + Object.assign(cohortMemberToUpdate, cohortMembersUpdateDto); + + const updatedCohortMember = await this.cohortMembersRepository.save( + cohortMemberToUpdate + ); + + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + updatedCohortMember, + "Cohort Member updated Successfully" + ) + ); + } catch (error) { + return response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong", + `Failure updating Cohort Member. Error is: ${error}`, + "INTERNAL_SERVER_ERROR" + ) + ); + } + } } diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index d5f83889..d59dc4eb 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -28,6 +28,7 @@ import { CohortMembersDto } from "./dto/cohortMembers.dto"; import { CohortMembersAdapter } from "./cohortMembersadapter"; import { CohortMembersService } from "./cohortMember.service"; import { Response } from "@nestjs/common"; +import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; @ApiTags("Cohort Members") @Controller("cohortmembers") @@ -129,16 +130,20 @@ export class CohortMembersController { @ApiCreatedResponse({ description: "Cohort Members has been updated successfully.", }) - @ApiBody({ type: CohortMembersDto }) + @ApiBody({ type: CohortMembersUpdateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateCohortMembers( @Param("id") cohortMembersId: string, @Req() request: Request, - @Body() cohortMembersipDto: CohortMembersDto + @Body() cohortMemberUpdateDto: CohortMembersUpdateDto, + @Res() response: Response ) { - return this.cohortMembersAdapter - .buildCohortMembersAdapter() - .updateCohortMembers(cohortMembersId, request, cohortMembersipDto); + return this.cohortMembersService.updateCohortMembers( + cohortMembersId, + request, + cohortMemberUpdateDto, + response + ); } } diff --git a/src/cohortMembers/dto/cohortMember-update.dto.ts b/src/cohortMembers/dto/cohortMember-update.dto.ts new file mode 100644 index 00000000..522057e3 --- /dev/null +++ b/src/cohortMembers/dto/cohortMember-update.dto.ts @@ -0,0 +1,67 @@ +import { Exclude, Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; +import { IsOptional } from "class-validator"; + +export class CohortMembersUpdateDto { + @Expose() + tenantId: string; + + @Expose() + cohortMembershipId: string; + + @Expose() + @IsOptional() + createdAt: string; + + @Expose() + @IsOptional() + updatedAt: string; + + @ApiProperty({ + type: String, + description: "The cohortId of the cohort members", + default: "", + }) + @Expose() + @IsOptional() // Marking as optional + cohortId?: string; // Making it optional by adding '?' after the type + + @ApiProperty({ + type: String, + description: "The userId of the cohort members", + default: "", + }) + @Expose() + @IsOptional() + userId?: string; + + @ApiProperty({ + type: String, + description: "The role of the cohort members", + default: "", + }) + @Expose() + role: string; + + @ApiProperty({ + type: String, + description: "The createdBy of the cohort members", + default: "", + }) + @Expose() + @IsOptional() + createdBy?: string; + + @ApiProperty({ + type: String, + description: "The updatedBy of the cohort members", + default: "", + }) + @Expose() + @IsOptional() + updatedBy?: string; + + constructor(obj: any) { + Object.assign(this, obj); + } +} From d6b89a4352cb900140be6942c3999e3083f80812 Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 26 Mar 2024 19:00:39 +0530 Subject: [PATCH 121/408] Task #216181 : Updated Response of View Profile --- src/user/user.service.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 4f2e438d..bc71b542 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -37,14 +37,16 @@ export class UserService { let apiId='api.users.getUsersDetails' try { const result = { - customFields: [] - }; - + userData:{ + } + }; + let customFieldsArray =[]; const [customFields, filledValues,userDetails] = await Promise.all([ this.findCustomFields(userData), this.findFilledValues(userData.userId), this.findUserDetails(userData.userId) ]); + result.userData=userDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { const fieldValue = filledValuesMap.get(data.fieldId); @@ -55,9 +57,9 @@ export class UserService { options: data?.fieldParams?.['options'] || {}, type: data.type || '' }; - result.customFields.push(customField); + customFieldsArray.push(customField); } - result['userData']=userDetails; + result.userData['customFields'] = customFieldsArray; return response .status(HttpStatus.OK) .send(APIResponse.success(apiId, result, 'OK')); From bb7180edfb7216f7f8a014f3279758363736e2f1 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 26 Mar 2024 20:45:17 +0530 Subject: [PATCH 122/408] GET Cohot: Show field name and field values --- src/cohort/cohort.service.ts | 34 ++++++---- src/fields/fields.service.ts | 127 ++++++++++++++++++----------------- src/utils/response.ts | 22 ++++++ 3 files changed, 111 insertions(+), 72 deletions(-) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 1bdef3b7..b52d22e2 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -11,6 +11,7 @@ import { UserDto } from "src/user/dto/user.dto"; import { StudentDto } from "src/student/dto/student.dto"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { InjectRepository } from "@nestjs/typeorm"; @@ -27,12 +28,9 @@ export class CohortService { constructor( @InjectRepository(Cohort) - + private cohortRepository: Repository, - private fieldsService: FieldsService - // @InjectRepository(FieldValues) - // private fieldsValuesRepository: Repository, - // private readonly fieldsService: FieldsService, + private fieldsService: FieldsService, ) { } public async getCohort( @@ -45,8 +43,14 @@ export class CohortService { try { const cohort = await this.cohortRepository.findOne({ - where: { tenantId: tenantId, cohortId: cohortId }, + where: { cohortId: cohortId }, + select: ["cohortId","parentId","name","type","status","image","programId","attendanceCaptureImage"], }); + + // let searchField = { itemId: cohortId } + + const fieldValue = await this.fieldsService.getFieldsAndFieldsValues(cohortId) + if (!cohort) { return response .status(HttpStatus.NOT_FOUND) @@ -59,11 +63,16 @@ export class CohortService { ) ); } + + cohort["customFields"] = fieldValue; + const result = { + cohort: cohort, + }; return response.status(HttpStatus.OK).send( APIResponse.success( apiId, - cohort, + result, "Cohort Retrieved Successfully" ) ); @@ -230,15 +239,16 @@ export class CohortService { const [results, totalCount] = await this.cohortRepository.findAndCount({ where: whereClause, skip: offset, + take: parseInt(limit), }); const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ - statusCode: 200, - message: 'Ok.', - totalCount, - data: mappedResponse, + statusCode: 200, + message: 'Ok.', + totalCount, + data: mappedResponse, }); } catch (e) { @@ -271,6 +281,6 @@ export class CohortService { return new CohortDto(cohortMapping); }) return cohortValueResponse; - + } } diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index d9259122..b5fe29d7 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -10,6 +10,9 @@ import { FieldValues } from "./entities/fields-values.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { SuccessResponse } from "src/success-response"; +import { off } from "process"; +import APIResponse from "src/utils/response"; +import { log } from "util"; @Injectable() export class FieldsService { @@ -57,42 +60,19 @@ export class FieldsService { async searchFields(tenantId: string, request: any, fieldsSearchDto: FieldsSearchDto) { try { - let { limit, page, filters } = fieldsSearchDto; - - let offset = 0; - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - - if (limit.trim() === '') { - limit = '0'; - } - - const whereClause = {}; - if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } - else { - whereClause['tenantId'] = tenantId; - } - - const [results, totalCount] = await this.fieldsRepository.findAndCount({ - where: whereClause, - skip: offset, - }); - - // console.log(results); + const getConditionalData = APIResponse.search(fieldsSearchDto) + const offset = getConditionalData.offset ; + const limit = getConditionalData.limit ; + const whereClause = getConditionalData.whereClause ; - - const mappedResponse = await this.mappedResponseField(results); + const getFieldValue = await this.searchFieldData(offset, limit, whereClause) + return new SuccessResponse({ statusCode: 200, message: 'Ok.', - totalCount, - data: mappedResponse, + totalCount : getFieldValue.totalCount, + data: getFieldValue.mappedResponse, }); } catch (e) { @@ -104,6 +84,26 @@ export class FieldsService { } } + async searchFieldData(offset: number, limit: string, searchData:any){ + let queryOptions: any = { + where: searchData, + }; + + if (offset !== undefined) { + queryOptions.skip = offset; + } + + if (limit !== undefined) { + queryOptions.take = parseInt(limit); + } + + + const [results, totalCount] = await this.fieldsRepository.findAndCount(queryOptions); + + const mappedResponse = await this.mappedResponseField(results); + return {mappedResponse, totalCount}; + } + async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { try { @@ -136,40 +136,18 @@ export class FieldsService { async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { try { + const getConditionalData = APIResponse.search(fieldValuesSearchDto) + const offset = getConditionalData.offset ; + const limit = getConditionalData.limit ; + const whereClause = getConditionalData.whereClause ; - let { limit, page, filters } = fieldValuesSearchDto; - - let offset = 0; - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - - if (limit.trim() === '') { - limit = '0'; - } - - const whereClause = {}; - if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } - - console.log(whereClause); - - const [results, totalCount] = await this.fieldsValuesRepository.findAndCount({ - where: whereClause, - take: parseInt(limit), - skip: offset, - }); - - const mappedResponse = await this.mappedResponse(results); + const getFieldValue = await this.getSearchFieldValueData(offset, limit, whereClause) return new SuccessResponse({ statusCode: 200, message: 'Ok.', - totalCount, - data: mappedResponse, + totalCount: getFieldValue.totalCount, + data: getFieldValue.mappedResponse, }); } catch (e) { @@ -181,6 +159,26 @@ export class FieldsService { } } + async getSearchFieldValueData(offset: number, limit: string, searchData:any){ + let queryOptions: any = { + where: searchData, + }; + + if (offset !== undefined) { + queryOptions.skip = offset; + } + + if (limit !== undefined) { + queryOptions.take = parseInt(limit); + } + + const [results, totalCount] = await this.fieldsValuesRepository.findAndCount(queryOptions); + const mappedResponse = await this.mappedResponse(results); + + return {mappedResponse, totalCount}; + + } + async searchFieldValueId(cohortId: string, fieldId: string){ const response = await this.fieldsValuesRepository.findOne({ where: { itemId: cohortId, fieldId: fieldId }, @@ -213,6 +211,14 @@ export class FieldsService { } } + public async getFieldsAndFieldsValues(cohortId:string){ + let query = `SELECT FV."value",FV."itemId", FV."fieldId", F."name", F."label", F."context",F."type", F."state", F."contextType", F."fieldParams" FROM public."FieldValues" FV + LEFT JOIN public."Fields" F + ON FV."fieldId" = F."fieldId" where FV."itemId" =$1`; + const results = await this.fieldsValuesRepository.query(query, [cohortId]); + return results; + } + public async mappedResponse(result: any) { const fieldValueResponse = result.map((item: any) => { @@ -269,4 +275,5 @@ export class FieldsService { return fieldResponse; } + } diff --git a/src/utils/response.ts b/src/utils/response.ts index 1f9f406d..e8d9ce65 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -57,6 +57,28 @@ export default class APIResponse { } } + public static search(dtoFileName){ + let { limit, page, filters } = dtoFileName; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + console.log(offset); + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + return {offset,limit,whereClause}; + } + // public static handleBadRequests( // response: Response, // apiId: string, From 4850c4dcf059f36ce48f5958d5d6cdc451e22d2d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 26 Mar 2024 20:47:12 +0530 Subject: [PATCH 123/408] GET Cohot: Show field name and field values --- src/utils/response.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/response.ts b/src/utils/response.ts index e8d9ce65..7aa5abc1 100644 --- a/src/utils/response.ts +++ b/src/utils/response.ts @@ -64,7 +64,6 @@ export default class APIResponse { if (page > 1) { offset = parseInt(limit) * (page - 1); } - console.log(offset); if (limit.trim() === '') { limit = '0'; From de250fd3d87e246c39628e4f50b328a8cc8c9d71 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 27 Mar 2024 10:29:30 +0530 Subject: [PATCH 124/408] Fix[attendance report and attendance list API] --- src/attendance/attendance.controller.ts | 4 +- src/attendance/attendance.service.ts | 220 +++++++++++++-------- src/attendance/dto/attendance-stats.dto.ts | 46 ++++- 3 files changed, 184 insertions(+), 86 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index c0aa15ad..f80a265f 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -209,8 +209,6 @@ export class AttendanceController { strategy: "excludeAll", }) @UsePipes(ValidationPipe) - - public async report( @Headers() headers, @Req() request: Request, @@ -218,7 +216,7 @@ export class AttendanceController { ) { let tenantid = headers["tenantid"]; return this.attendaceService - .attendanceReport(attendanceStatsDto.contextId); + .attendanceReport(attendanceStatsDto); } /** No longer required in Shiksha 2.0 */ diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 24f0f8e1..ef4cf7d3 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -1,3 +1,4 @@ +import { User } from './../user/entities/user-entity'; import { isAfter } from 'date-fns'; import { ConfigService } from '@nestjs/config'; import { Client } from 'pg'; @@ -13,15 +14,15 @@ import { AttendanceDto, BulkAttendanceDTO } from './dto/attendance.dto'; import { AttendanceDateDto } from './dto/attendance-date.dto'; import { Between } from 'typeorm'; import { AttendanceStatsDto } from './dto/attendance-stats.dto'; -import { User } from 'src/user/entities/user-entity'; - - +import { format } from 'date-fns' +const moment = require('moment'); @Injectable() export class AttendanceService { constructor(private configService: ConfigService, @InjectRepository(AttendanceEntity) - private readonly attendanceRepository: Repository,) { } + private readonly attendanceRepository: Repository, + ) { } @@ -73,44 +74,81 @@ export class AttendanceService { } } - async attendanceReport(contextId:string) { - try{ - const query = ` - SELECT - u."name", - COUNT(CASE WHEN aa."attendance" = 'Present' THEN 1 END) * 100.0 / COUNT(aa."attendance") AS attendance_percentage -FROM - public."Attendance" AS aa -INNER JOIN - public."Users" AS u ON aa."userId" = u."userId" -WHERE - aa."attendance" IN ('Present', 'Absent') - AND u."role" = 'student' - AND aa."contextId" = $1 -GROUP BY - u."name", - u."role"; - `; - - const result = await this.attendanceRepository.query(query,[contextId]); - const report= await this.mapResponseforReport(result); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: report, - }); + async attendanceReport(attendanceStatsDto: AttendanceStatsDto) { + + const { contextId, attendanceDate, report, limit, offset } = attendanceStatsDto + try { + if (report === true) { + const query = ` + SELECT u."userId",u."name", + CASE + WHEN COUNT(*) = 0 THEN NULL + ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*),2) + END AS attendance_percentage + FROM public."CohortMembers" AS cm + INNER JOIN public."Users" AS u ON cm."userId" = u."userId" + LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" + WHERE cm."cohortId" = $1 AND cm."role" = 'student' + GROUP BY u."userId" + LIMIT $2 + OFFSET $3; + ;`; + + + const result = await this.attendanceRepository.query(query, [contextId, limit, offset]); + const report = await this.mapResponseforReport(result); + + + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: report, + }); + } + else if (report === false) { + if (attendanceDate) { + const query = ` + SELECT * + FROM public."Users" AS u + INNER JOIN public."CohortMembers" AS cm ON cm."userId" = u."userId" AND cm."role"='student' + LEFT JOIN public."Attendance" AS aa ON aa."userId" = cm."userId" AND (aa."attendanceDate" =$1 OR aa."attendanceDate" IS NULL) + where cm."cohortId" = $2 + LIMIT $3 + OFFSET $4 + `; + + + + const result = await this.attendanceRepository.query(query, [attendanceDate, contextId, limit, offset]); + const report = await this.mapAttendanceRecord(result); + + + return new SuccessResponse({ + statusCode: 200, + message: "Ok.", + data: report, + }); + } + + else { + + return new ErrorResponse({ + errorCode: "400", + errorMessage: "Please provide valid attendance date", + }); + + } + } } - catch(error){ + catch (error) { return new ErrorResponse({ errorCode: "500", - errorMessage: error, + errorMessage: "Internal server error", }); - - } + } } public async mappedResponse(result: any) { @@ -146,6 +184,7 @@ GROUP BY const attendanceReport = result.map((item: any) => { const attendanceReportMapping = { name: item?.name ? `${item.name}` : "", + userId: item?.userId ? `${item.userId}` : "", attendance_percentage: item?.attendance_percentage ? `${item.attendance_percentage}` : "", }; @@ -154,6 +193,25 @@ GROUP BY return attendanceReport; } + + public async mapAttendanceRecord(result: any) { + const attendanceRecords = result.map((item: any) => { + const dateObject = new Date(item.attendanceDate); + const formattedDate = moment(dateObject).format('YYYY-MM-DD'); + + let attendance = { + name: item?.name ? `${item.name}` : "", + userId: item?.userId ? `${item.userId}` : "", + attendance: item?.attendance ? `${item.attendance}` : "", + attendanceDate: item.attendanceDate ? formattedDate : null + + }; + console.log(attendance) + return new AttendanceStatsDto(attendance); + }); + + return attendanceRecords; + } /* Method to create,update or add attendance for valid user in attendance table @body an object of details consisting of attendance details of user (attendance dto) @@ -167,48 +225,48 @@ GROUP BY try { - const decoded: any = jwt_decode(request?.headers?.authorization); + const decoded: any = jwt_decode(request?.headers?.authorization); - const userId = - decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - const attendanceToSearch = new AttendanceSearchDto({}); + const userId = + decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + const attendanceToSearch = new AttendanceSearchDto({}); - attendanceToSearch.filters = { - attendanceDate: attendanceDto.attendanceDate, - userId: attendanceDto.userId, - }; + attendanceToSearch.filters = { + attendanceDate: attendanceDto.attendanceDate, + userId: attendanceDto.userId, + }; - const attendanceFound: any = await this.searchAttendance( - attendanceDto.tenantId, - request, - attendanceToSearch - ); + const attendanceFound: any = await this.searchAttendance( + attendanceDto.tenantId, + request, + attendanceToSearch + ); - if (attendanceFound?.errorCode) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: attendanceFound?.errorMessage, - }); - } + if (attendanceFound?.errorCode) { + return new ErrorResponse({ + errorCode: "500", + errorMessage: attendanceFound?.errorMessage, + }); + } - if ( - attendanceFound.data.length > 0 && - attendanceFound.statusCode === 200 - ) { + if ( + attendanceFound.data.length > 0 && + attendanceFound.statusCode === 200 + ) { - return await this.updateAttendance( - attendanceFound.data[0].attendanceId, - request, - attendanceDto - ); - } else { + return await this.updateAttendance( + attendanceFound.data[0].attendanceId, + request, + attendanceDto + ); + } else { - return await this.createAttendance(request, attendanceDto); - } + return await this.createAttendance(request, attendanceDto); + } } catch (e) { return e; } @@ -267,7 +325,7 @@ GROUP BY public async createAttendance(request: any, attendanceDto: AttendanceDto) { try { - const attendance = this.attendanceRepository.create(attendanceDto); + const attendance = this.attendanceRepository.create(attendanceDto); const result = await this.attendanceRepository.save(attendance); return new SuccessResponse({ @@ -303,7 +361,7 @@ GROUP BY ) { try { - + let { limit, page } = attendanceSearchDto; if (!limit) { limit = '0'; @@ -373,19 +431,19 @@ GROUP BY attendance: attendance.attendance, userId: attendance.userId }) - const attendanceRes: any = await this.updateAttendanceRecord( - request, - userAttendance - ); - if (attendanceRes?.statusCode === 200) { - responses.push(attendanceRes.data); - } else { - errors.push({ - userId: attendance.userId, - attendanceRes, - }); - } - count++; + const attendanceRes: any = await this.updateAttendanceRecord( + request, + userAttendance + ); + if (attendanceRes?.statusCode === 200) { + responses.push(attendanceRes.data); + } else { + errors.push({ + userId: attendance.userId, + attendanceRes, + }); + } + count++; } } catch (e) { diff --git a/src/attendance/dto/attendance-stats.dto.ts b/src/attendance/dto/attendance-stats.dto.ts index a07adb4a..e53e5931 100644 --- a/src/attendance/dto/attendance-stats.dto.ts +++ b/src/attendance/dto/attendance-stats.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from "@nestjs/swagger"; -import { Expose } from "class-transformer"; +import { Expose, Transform } from "class-transformer"; import { IsNotEmpty, IsNumberString, IsString, IsUUID } from 'class-validator'; export class AttendanceStatsDto { @@ -26,7 +26,49 @@ export class AttendanceStatsDto { @Expose() attendance_percentage: string; + @ApiProperty({ + type: String, + description: "userId of student", + }) + @Expose() + userId: string; + + @ApiProperty({ + description: "attendance date", + }) + @Expose() + attendanceDate: Date; + + @ApiProperty({ + description: "attendance", + }) + @Expose() + attendance: string; + + @ApiProperty({ + type: String, + description: "flag", + }) + @Expose() + report: boolean; + + @ApiProperty({ + type: String, + description: "The name of the person", + }) + @IsNotEmpty() + @Expose() + limit: number; + + @ApiProperty({ + type: String, + description: "The name of the person", + }) + @Expose() + @IsNotEmpty() + offset: number; + constructor(obj: Partial) { Object.assign(this, obj); - } + } } From 6fa2fa940826bcf0923f6a35ca2627831f5a2bcd Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 27 Mar 2024 11:05:40 +0530 Subject: [PATCH 125/408] Fix[applying validation for search attendance by date] --- src/attendance/attendance.controller.ts | 1 + src/attendance/dto/attendance-date.dto.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index f80a265f..aa51b4b0 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -168,6 +168,7 @@ export class AttendanceController { @ApiHeader({ name: "tenantid", }) + @UsePipes(ValidationPipe) public async attendanceFilter( @Headers() headers, @Req() request: Request, diff --git a/src/attendance/dto/attendance-date.dto.ts b/src/attendance/dto/attendance-date.dto.ts index 8f2ebdb1..3b00e50d 100644 --- a/src/attendance/dto/attendance-date.dto.ts +++ b/src/attendance/dto/attendance-date.dto.ts @@ -1,16 +1,21 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { IsNotEmpty, Matches } from "class-validator"; export class AttendanceDateDto { @ApiProperty({ type: Date, description: "From Date", }) + @IsNotEmpty() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) fromDate: string; @ApiProperty({ type: Date, description: "To Date", }) + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @IsNotEmpty() toDate: string; @ApiProperty({ From 5b1a4ff95181c3b81ce63d78e4ea20f8e3531ffa Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 27 Mar 2024 11:25:47 +0530 Subject: [PATCH 126/408] Fix[added dependency] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4026374b..307ecfb2 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "form-data": "^4.0.0", "graphql-tag": "^2.12.6", "jwt-decode": "^3.1.2", - "moment": "^2.29.3", + "moment": "^2.30.1", "multer": "^1.4.4", "node-cron": "^3.0.1", "node-schedule": "^2.1.0", From 970e81f33d23b598f7288b118872f1c1e174c535 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 27 Mar 2024 12:32:42 +0530 Subject: [PATCH 127/408] Task #216339: chore - Keycloak issue fixes --- src/adapters/hasura/user.adapter.ts | 2 +- src/common/keycloak.ts | 162 ------------------ .../utils}/keycloak.adapter.util.ts | 2 +- src/user/user.service.ts | 2 +- 4 files changed, 3 insertions(+), 165 deletions(-) delete mode 100644 src/common/keycloak.ts rename src/{adapters/hasura => common/utils}/keycloak.adapter.util.ts (98%) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 873ecfcf..8905e363 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -13,7 +13,7 @@ import { getKeycloakAdminToken, createUserInKeyCloak, checkIfUsernameExistsInKeycloak, -} from "./keycloak.adapter.util"; +} from "../../common/utils/keycloak.adapter.util"; import { UserCreateDto } from "src/user/dto/user-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; diff --git a/src/common/keycloak.ts b/src/common/keycloak.ts deleted file mode 100644 index 8904e1be..00000000 --- a/src/common/keycloak.ts +++ /dev/null @@ -1,162 +0,0 @@ -function getUserRole(userRoles: string[]) { - if (userRoles.includes("systemAdmin")) { - return "systemAdmin"; - } else if (userRoles.includes("facilitator")) { - return "facilitator"; - } else if (userRoles.includes("beneficiary")) { - return "beneficiary"; - } else return "user"; - } - - function getUserGroup(role: string) { - switch (role) { - case "systemAdmin": - return "systemAdmin"; - case "facilitator": - return "facilitator"; - default: - return "beneficiary"; - } - } - - async function getKeycloakAdminToken() { - const axios = require("axios"); - const qs = require("qs"); - const data = qs.stringify({ - username: process.env.KEYCLOAK_USERNAME, - password: process.env.KEYCLOAK_PASSWORD, - grant_type: "password", - client_id: "admin-cli", - }); - - const config = { - method: "post", - url: process.env.KEYCLOAK + process.env.KEYCLOAK_ADMIN_TOKEN, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - data: data, - }; - - let res; - try { - res = await axios(config); - } catch (error) { - console.log(error, "err"); - } - - return res; - } - - async function createUserInKeyCloak(query, token) { - const axios = require("axios"); - const name = query.name; - const nameParts = name.split(" "); - let lname = ""; - - if (nameParts[2]) { - lname = nameParts[2]; - } else if (nameParts[1]) { - lname = nameParts[1]; - } - if (!query.password) { - return "User cannot be created, Password missing"; - } - - const data = JSON.stringify({ - firstName: nameParts[0], - lastName: lname, - enabled: "true", - username: query.username, - groups: [getUserGroup(query.role)], - credentials: [ - { - temporary: "false", - type: "password", - value: query.password, - }, - ], - }); - - const config = { - method: "post", - url: process.env.KEYCLOAK + process.env.KEYCLOAK_ADMIN, - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }, - data: data, - }; - - let userResponse; - try { - userResponse = await axios(config); - } catch (e) { - console.log(e.response, "Keycloak Creation error"); - return e; - } - - const userString = userResponse.headers.location; - const index = userString.lastIndexOf("/"); - const userId = userString.substring(index + 1); - - return userId; - } - - async function checkIfEmailExistsInKeycloak(email, token) { - const axios = require("axios"); - const config = { - method: "get", - url: process.env.KEYCLOAK + process.env.KEYCLOAK_ADMIN + `?email=${email}`, - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }, - }; - - let userResponse; - try { - userResponse = await axios(config); - } catch (e) { - console.log(e, "Keycloak error - email"); - return e; - } - - return userResponse; - } - - async function checkIfUsernameExistsInKeycloak(username, token) { - // console.log(username); - const axios = require("axios"); - const config = { - method: "get", - url: - process.env.KEYCLOAK + - process.env.KEYCLOAK_ADMIN + - `?username=${username}`, - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }, - }; - - let userResponse; - try { - userResponse = await axios(config); - } catch (e) { - console.log(e, "Keycloak error - username"); - return e; - } - - return userResponse; - } - - export { - getUserGroup, - getUserRole, - getKeycloakAdminToken, - createUserInKeyCloak, - checkIfEmailExistsInKeycloak, - checkIfUsernameExistsInKeycloak, - }; - \ No newline at end of file diff --git a/src/adapters/hasura/keycloak.adapter.util.ts b/src/common/utils/keycloak.adapter.util.ts similarity index 98% rename from src/adapters/hasura/keycloak.adapter.util.ts rename to src/common/utils/keycloak.adapter.util.ts index f2e3d18b..030e2804 100644 --- a/src/adapters/hasura/keycloak.adapter.util.ts +++ b/src/common/utils/keycloak.adapter.util.ts @@ -133,7 +133,7 @@ async function checkIfUsernameExistsInKeycloak(username, token) { url: process.env.KEYCLOAK + process.env.KEYCLOAK_ADMIN + - `?username=${username}`, + `?username=${username}&exact=true`, headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 1069bd89..baffafda 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -11,7 +11,7 @@ import { getKeycloakAdminToken, createUserInKeyCloak, checkIfUsernameExistsInKeycloak, - } from "../common/keycloak"; +} from "../common/utils/keycloak.adapter.util" import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; import { Field } from './entities/field-entity'; From ceed2765653e54f3e5c20dd32cc9558ec306c3da Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 27 Mar 2024 16:37:58 +0530 Subject: [PATCH 128/408] COHORT: Delete Cohort data (update status) --- src/cohort/cohort.controller.ts | 38 ++++++++++++++++++++++++++-- src/cohort/cohort.service.ts | 39 +++++++++++++++++++++++++++-- src/cohort/dto/cohort-create.dto.ts | 6 ++--- src/cohort/dto/cohort.dto.ts | 7 +++--- src/fields/fields.service.ts | 2 +- 5 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index c777df99..a0df2fd2 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -24,6 +24,7 @@ import { UploadedFile, Res, Headers, + Delete, } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -43,7 +44,7 @@ export class CohortController { constructor( private cohortAdapter: CohortAdapter, private readonly cohortService: CohortService - ) {} + ) { } //create cohort @Post() @ApiConsumes("multipart/form-data") @@ -101,7 +102,7 @@ export class CohortController { let tenantid = headers["tenantid"]; return this.cohortService.getCohort(tenantid, cohortId, request, response); } - + // search @Post("/search") @ApiBasicAuth("access-token") @@ -155,4 +156,37 @@ export class CohortController { return this.cohortService.updateCohort(cohortId, request, cohortCreateDto); } + + //delete cohort + @Delete("/:id") + @ApiConsumes("multipart/form-data") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Cohort has been deleted successfully." }) + @UseInterceptors( + FileInterceptor("image", { + storage: diskStorage({ + destination: process.env.IMAGEPATH, + filename: editFileName, + }), + fileFilter: imageFileFilter, + }) + ) + @ApiBody({ type: CohortCreateDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + public async updateCohortStatus( + @Param("id") cohortId: string, + @Req() request: Request, + @Body() cohortCreateDto: CohortCreateDto, + @UploadedFile() image + ) { + const response = { + image: image?.filename, + }; + Object.assign(cohortCreateDto, response); + + return this.cohortService.updateCohortStatus(cohortId, request, cohortCreateDto); + + } + } diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index b52d22e2..d8fcdf74 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -43,7 +43,7 @@ export class CohortService { try { const cohort = await this.cohortRepository.findOne({ - where: { cohortId: cohortId }, + where: { cohortId: cohortId, status: "true" }, select: ["cohortId","parentId","name","type","status","image","programId","attendanceCaptureImage"], }); @@ -164,7 +164,6 @@ export class CohortService { }); const response = await this.cohortRepository.update(cohortId, cohortUpdateData); - console.log(response); let field_value_array = cohortUpdateDto.fieldValues.split("|"); @@ -283,4 +282,40 @@ export class CohortService { return cohortValueResponse; } + + public async updateCohortStatus( + cohortId: string, + request: any, + cohortUpdateDto: CohortCreateDto + ) { + try { + const cohortUpdateData: any = {}; + + Object.keys(cohortUpdateDto).forEach((e) => { + if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" + ) { + if (Array.isArray(cohortUpdateDto[e])) { + cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + } else { + cohortUpdateData[e] = cohortUpdateDto[e]; + } + } + }); + let query =`UPDATE public."Cohort" + SET "status" = false + WHERE "cohortId" = $1`; + const results = await this.cohortRepository.query(query, [cohortId]); + + return new SuccessResponse({ + statusCode: 200, + message: "Cohort Deleted Successfully.", + }); + } catch (e) { + console.error(e); + return new ErrorResponse({ + errorCode: "401", + errorMessage: e, + }); + } + } } diff --git a/src/cohort/dto/cohort-create.dto.ts b/src/cohort/dto/cohort-create.dto.ts index 5f7446e8..a0ed1ffa 100644 --- a/src/cohort/dto/cohort-create.dto.ts +++ b/src/cohort/dto/cohort-create.dto.ts @@ -67,12 +67,12 @@ export class CohortCreateDto { //status @ApiPropertyOptional({ - type: String, + type: Boolean, description: "The status of the cohort", - default: "publish", + default: true, }) @Expose() - status: string; + status: boolean; //attendanceCaptureImage @ApiProperty({ diff --git a/src/cohort/dto/cohort.dto.ts b/src/cohort/dto/cohort.dto.ts index 40221c78..87cc65e0 100644 --- a/src/cohort/dto/cohort.dto.ts +++ b/src/cohort/dto/cohort.dto.ts @@ -64,14 +64,15 @@ export class CohortDto { @Expose() type: string; + //status @ApiPropertyOptional({ - type: String, + type: Boolean, description: "The status of the cohort", - default: "publish", + default: true, }) @Expose() - status: string; + status: boolean; //image @Expose() diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index b5fe29d7..65a687ea 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -212,7 +212,7 @@ export class FieldsService { } public async getFieldsAndFieldsValues(cohortId:string){ - let query = `SELECT FV."value",FV."itemId", FV."fieldId", F."name", F."label", F."context",F."type", F."state", F."contextType", F."fieldParams" FROM public."FieldValues" FV + let query = `SELECT FV."value",FV."itemId", FV."fieldId", F."name" AS fieldname, F."label", F."context",F."type", F."state", F."contextType", F."fieldParams" FROM public."FieldValues" FV LEFT JOIN public."Fields" F ON FV."fieldId" = F."fieldId" where FV."itemId" =$1`; const results = await this.fieldsValuesRepository.query(query, [cohortId]); From e51836ba1f76b4d8632e44ac9995fc5d91bc801d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 27 Mar 2024 16:54:52 +0530 Subject: [PATCH 129/408] COHORT: Delete Cohort data (update status) --- src/cohort/cohort.controller.ts | 11 +---------- src/cohort/cohort.service.ts | 18 ++---------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index a0df2fd2..cb96ec58 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -162,15 +162,6 @@ export class CohortController { @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort has been deleted successfully." }) - @UseInterceptors( - FileInterceptor("image", { - storage: diskStorage({ - destination: process.env.IMAGEPATH, - filename: editFileName, - }), - fileFilter: imageFileFilter, - }) - ) @ApiBody({ type: CohortCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @@ -185,7 +176,7 @@ export class CohortController { }; Object.assign(cohortCreateDto, response); - return this.cohortService.updateCohortStatus(cohortId, request, cohortCreateDto); + return this.cohortService.updateCohortStatus(cohortId); } diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index d8fcdf74..ca54dff1 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -284,28 +284,14 @@ export class CohortService { } public async updateCohortStatus( - cohortId: string, - request: any, - cohortUpdateDto: CohortCreateDto + cohortId: string ) { try { - const cohortUpdateData: any = {}; - - Object.keys(cohortUpdateDto).forEach((e) => { - if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" - ) { - if (Array.isArray(cohortUpdateDto[e])) { - cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); - } else { - cohortUpdateData[e] = cohortUpdateDto[e]; - } - } - }); let query =`UPDATE public."Cohort" SET "status" = false WHERE "cohortId" = $1`; const results = await this.cohortRepository.query(query, [cohortId]); - + return new SuccessResponse({ statusCode: 200, message: "Cohort Deleted Successfully.", From a4284c7493df331df58c499ebaf1e2e22442dc5b Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Wed, 27 Mar 2024 17:26:48 +0530 Subject: [PATCH 130/408] Added delete cohort member API --- src/cohortMembers/cohortMember.service.ts | 86 ++++++++++++++----- src/cohortMembers/cohortMembers.controller.ts | 29 +++++++ 2 files changed, 94 insertions(+), 21 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 1ebce52b..2d994301 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -81,36 +81,32 @@ export class CohortMembersService { const apiId = "api.cohortMember.searchCohortMembers"; try { - let offset = 0; - if (cohortMembersSearchDto.page > 1) { - offset = - parseInt(cohortMembersSearchDto.limit) * - (cohortMembersSearchDto.page - 1); + let { limit, page, filters } = cohortMembersSearchDto; + if (!limit) { + limit = "0"; } - let filters: any = { tenantId: tenantId || "" }; - const tempFilters = { ...cohortMembersSearchDto.filters }; + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } - // Convert filter keys to match TypeORM column names - Object.keys(tempFilters).forEach((item) => { - Object.keys(tempFilters[item]).forEach((e) => { - if (!e.startsWith("_")) { - tempFilters[item][`_${e}`] = tempFilters[item][e]; - delete tempFilters[item][e]; - } + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; }); - }); - - filters = { ...filters, ...tempFilters }; - - const takeLimit = parseInt(cohortMembersSearchDto.limit); // Parse limit value here + } else { + whereClause["tenantId"] = tenantId; + } const [cohortMembers, count] = await this.cohortMembersRepository.findAndCount({ - where: filters, - take: takeLimit, // Use parsed limit value here + where: whereClause, + take: parseInt(limit), skip: offset, }); + const responseData = { totalCount: count, cohortMembers: cohortMembers, @@ -219,4 +215,52 @@ export class CohortMembersService { ); } } + + public async deleteCohortMemberById( + tenantId: string, + cohortMembershipId: any, + response: any, + request: any + ) { + const apiId = "api.cohortMember.deleteCohortMemberById"; + + try { + const cohortMember = await this.cohortMembersRepository.find({ + where: { + tenantId: tenantId, + cohortMembershipId: cohortMembershipId, + }, + }); + + if (!cohortMember || cohortMember.length === 0) { + return response.status(HttpStatus.NOT_FOUND).send({ + error: "Cohort member not found", + }); + } + + const result = await this.cohortMembersRepository.delete( + cohortMembershipId + ); + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + result, + "Cohort Member deleted Successfully" + ) + ); + } catch (error) { + return response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong", + `Failure Retrieving Cohort Member. Error is: ${error}`, + "INTERNAL_SERVER_ERROR" + ) + ); + } + } } diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index d59dc4eb..19a15c90 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -13,6 +13,7 @@ import { Post, Body, Put, + Delete, Param, UseInterceptors, ClassSerializerInterceptor, @@ -146,4 +147,32 @@ export class CohortMembersController { response ); } + + //delete + @Delete("/:id") + @UseInterceptors(ClassSerializerInterceptor) + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Cohort member deleted successfully" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async deleteCohortMember( + @Headers() headers, + @Param("id") cohortMembershipId: string, + @Req() request: Request, + @Res() response: Response + ) { + let tenantid = headers["tenantid"]; + + return this.cohortMembersService.deleteCohortMemberById( + tenantid, + cohortMembershipId, + response, + request + ); + } } From 44d911d6f80f52413188521cf9658ca68263346a Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 27 Mar 2024 18:09:14 +0530 Subject: [PATCH 131/408] Fix[search and sort functionality for report] --- src/attendance/attendance.controller.ts | 2 +- src/attendance/attendance.service.ts | 36 +++++++++----- src/attendance/dto/attendance-stats.dto.ts | 48 +++++++++++++++---- src/cohortMembers/cohortMembers.controller.ts | 42 ++++++++-------- 4 files changed, 87 insertions(+), 41 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index aa51b4b0..7c0a36e7 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -203,7 +203,7 @@ export class AttendanceController { @Post("/report") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Attendance list." }) - @ApiBody({ type: AttendanceSearchDto }) + @ApiBody({ type: AttendanceStatsDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index ef4cf7d3..db057af0 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -22,7 +22,7 @@ export class AttendanceService { constructor(private configService: ConfigService, @InjectRepository(AttendanceEntity) private readonly attendanceRepository: Repository, - ) { } + ) { } @@ -76,10 +76,16 @@ export class AttendanceService { async attendanceReport(attendanceStatsDto: AttendanceStatsDto) { - const { contextId, attendanceDate, report, limit, offset } = attendanceStatsDto + let { contextId, attendanceDate, report, limit, offset, filters } = attendanceStatsDto try { + + if (report === true) { - const query = ` + let nameFilter = ''; + if (filters && filters.search) { + nameFilter = `AND u."name" LIKE '%${filters.search.trim()}%'`; + } + let query = ` SELECT u."userId",u."name", CASE WHEN COUNT(*) = 0 THEN NULL @@ -89,12 +95,25 @@ export class AttendanceService { INNER JOIN public."Users" AS u ON cm."userId" = u."userId" LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" WHERE cm."cohortId" = $1 AND cm."role" = 'student' + ${nameFilter} GROUP BY u."userId" - LIMIT $2 - OFFSET $3; - ;`; + `; + + + if (filters) { + if (filters.nameOrder && filters.nameOrder==="asc" || filters.nameOrder==="desc") { + query += ` ORDER BY "name" ${filters.nameOrder}` + + } + else if (filters.percentageOrder && filters.percentageOrder==="asc" || filters.percentageOrder==="desc") { + query += ` ORDER BY attendance_percentage ${filters.percentageOrder}` + } + } + query += ` + LIMIT $2 + OFFSET $3` const result = await this.attendanceRepository.query(query, [contextId, limit, offset]); const report = await this.mapResponseforReport(result); @@ -206,7 +225,6 @@ export class AttendanceService { attendanceDate: item.attendanceDate ? formattedDate : null }; - console.log(attendance) return new AttendanceStatsDto(attendance); }); @@ -308,7 +326,6 @@ export class AttendanceService { }); } catch (error) { if (error instanceof BadRequestException) { - console.error("Error updating attendance:", error); return new ErrorResponse({ errorCode: "500", errorMessage: "Internal Server Error", @@ -341,7 +358,6 @@ export class AttendanceService { errorMessage: "Please provide valid userID", }); } else { - console.error('Error creating attendance:', error); return new ErrorResponse({ errorCode: "500", errorMessage: 'Internal Server Error', @@ -402,7 +418,6 @@ export class AttendanceService { data: mappedResponse, }); } catch (e) { - console.error(e); return new ErrorResponse({ errorCode: "500", errorMessage: e, @@ -447,7 +462,6 @@ export class AttendanceService { } } catch (e) { - console.error(e); return e; } diff --git a/src/attendance/dto/attendance-stats.dto.ts b/src/attendance/dto/attendance-stats.dto.ts index e53e5931..01369724 100644 --- a/src/attendance/dto/attendance-stats.dto.ts +++ b/src/attendance/dto/attendance-stats.dto.ts @@ -1,6 +1,27 @@ -import { ApiProperty } from "@nestjs/swagger"; -import { Expose, Transform } from "class-transformer"; -import { IsNotEmpty, IsNumberString, IsString, IsUUID } from 'class-validator'; +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { Expose, Transform, Type } from "class-transformer"; +import { IsEnum, IsNotEmpty, IsNumberString, IsOptional, IsString, IsUUID, ValidateNested } from 'class-validator'; + +enum Order { + ASC = 'asc', + DESC = 'desc', +} + + +class FiltersDto { + @IsEnum(Order,{ message: "nameOrder must be a valid enum value asc or desc" }) + @IsOptional() + nameOrder: Order; + + @IsEnum(Order,{ message: "nameOrder must be a valid enum value asc or desc" }) + @IsOptional() + percentageOrder: Order; + + @IsString() + @IsOptional() + search: string; + +} export class AttendanceStatsDto { @ApiProperty({ @@ -53,22 +74,33 @@ export class AttendanceStatsDto { report: boolean; @ApiProperty({ - type: String, - description: "The name of the person", + type: Number, + description: "limit", }) @IsNotEmpty() @Expose() limit: number; @ApiProperty({ - type: String, - description: "The name of the person", + type: Number, + description: "offset", }) @Expose() - @IsNotEmpty() offset: number; + @ApiProperty({ + type: Object, + description: "Filters", + }) + @ApiPropertyOptional() + @ValidateNested({ each: true }) + @Type(() => FiltersDto) + + filters: FiltersDto + constructor(obj: Partial) { Object.assign(this, obj); } } + + diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 0c1bb75d..4d1ee9a4 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -88,27 +88,27 @@ export class CohortMembersController { } //search - @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort Members list." }) - @ApiBody({ type: CohortMembersSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async searchCohortMembers( - @Headers() headers, - @Req() request: Request, - @Res() res: Response, - @Body() cohortMembersSearchDto: CohortMembersSearchDto - ) { - let tenantid = headers["tenantid"]; - return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto,res); - } + // @Post("/search") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Cohort Members list." }) + // @ApiBody({ type: CohortMembersSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async searchCohortMembers( + // @Headers() headers, + // @Req() request: Request, + // @Res() res: Response, + // @Body() cohortMembersSearchDto: CohortMembersSearchDto + // ) { + // let tenantid = headers["tenantid"]; + // return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto,res); + // } //update @Put("/:id") From 4d3a5537a4a1cf98a09f20d097c8cae2fdbe88b6 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 27 Mar 2024 18:19:32 +0530 Subject: [PATCH 132/408] Fix[resolve conflict] --- src/cohortMembers/cohortMembers.controller.ts | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 4d1ee9a4..054caf8a 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -87,28 +87,28 @@ export class CohortMembersController { .getCohortMembers(tenantid, cohortMembersId, request); } - //search - // @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Cohort Members list." }) - // @ApiBody({ type: CohortMembersSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - // @SerializeOptions({ - // strategy: "excludeAll", - // }) - // @ApiHeader({ - // name: "tenantid", - // }) - // public async searchCohortMembers( - // @Headers() headers, - // @Req() request: Request, - // @Res() res: Response, - // @Body() cohortMembersSearchDto: CohortMembersSearchDto - // ) { - // let tenantid = headers["tenantid"]; - // return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto,res); - // } + search + @Post("/search") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Cohort Members list." }) + @ApiBody({ type: CohortMembersSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async searchCohortMembers( + @Headers() headers, + @Req() request: Request, + @Res() res: Response, + @Body() cohortMembersSearchDto: CohortMembersSearchDto + ) { + let tenantid = headers["tenantid"]; + return this.cohortMembersService.searchCohortMembers(tenantid, request, cohortMembersSearchDto,res); + } //update @Put("/:id") From e5045ba2632e896c6ffff54ed2c749c54da8b4b6 Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 27 Mar 2024 19:26:34 +0530 Subject: [PATCH 133/408] Task #216365 : Added Update Profiele and Create user API with Custom field Support --- src/auth/auth.module.ts | 4 +- src/user/dto/user-create.dto.ts | 7 ++ src/user/entities/user-entity.ts | 4 +- src/user/user.module.ts | 4 +- src/user/user.service.ts | 137 +++++++++++++++++++++++-------- 5 files changed, 117 insertions(+), 39 deletions(-) diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index a4590764..a4e0f198 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -7,6 +7,7 @@ import { TypeOrmModule } from "@nestjs/typeorm"; import {User} from '../user/entities/user-entity'; import { FieldValues } from '../user/entities/field-value-entities' import { Field } from "src/user/entities/field-entity"; +import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; const ttl = process.env.TTL as never; @Module({ @@ -14,7 +15,8 @@ const ttl = process.env.TTL as never; TypeOrmModule.forFeature([ User, FieldValues, - Field + Field, + CohortMembers ]), HttpModule, CacheModule.register({ diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 225de48a..1f5aa24f 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -105,6 +105,13 @@ export class UserCreateDto { @Expose() updatedBy: string; + @ApiPropertyOptional({ + type: String, + description: "The cohort id of the user", + }) + @Expose() + cohortId: string; + //fieldValues @ApiProperty({ type: String, diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts index 863a5a1b..dc401c2f 100644 --- a/src/user/entities/user-entity.ts +++ b/src/user/entities/user-entity.ts @@ -38,8 +38,8 @@ export class User { @UpdateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) updatedAt: Date; -// @Column({ type: "numberic", nullable: true }) -// mobile: number; + @Column() + mobile: number; @Column({ nullable: true }) createdBy: string; diff --git a/src/user/user.module.ts b/src/user/user.module.ts index d6c4cec6..a5fa88ca 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -9,13 +9,15 @@ import { User } from "./entities/user-entity"; import { UserService } from "./user.service"; import { FieldValues } from "./entities/field-value-entities"; import { Field } from "./entities/field-entity"; +import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([ User, FieldValues, - Field + Field, + CohortMembers ]), HttpModule, SunbirdModule, diff --git a/src/user/user.service.ts b/src/user/user.service.ts index bc71b542..91604469 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Injectable } from '@nestjs/common'; +import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; import { User } from './entities/user-entity' import { FieldValues } from './entities/field-value-entities'; import ApiResponse from '../utils/response' @@ -12,13 +12,16 @@ import { createUserInKeyCloak, checkIfUsernameExistsInKeycloak, } from "../common/keycloak"; +import { FieldValuesCreateDto } from 'src/fields/dto/field-values-create.dto'; import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; import { Field } from './entities/field-entity'; import APIResponse from '../utils/response'; +import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; import { v5 as uuidv5 } from 'uuid'; import { UUID } from 'typeorm/driver/mongodb/bson.typings'; import { AnyARecord } from 'dns'; +import { CohortSearchDto } from 'src/cohort/dto/cohort-search.dto'; @Injectable() @@ -30,7 +33,9 @@ export class UserService { @InjectRepository(FieldValues) private fieldsValueRepository: Repository, @InjectRepository(Field) - private fieldsRepository : Repository + private fieldsRepository : Repository, + @InjectRepository (CohortMembers) + private cohortMemberRepository: Repository ) {} async getUsersDetailsById(userData:Record,response){ @@ -115,6 +120,7 @@ export class UserService { } if(userDto.customFields.length > 0){ for (let data of userDto.customFields) { + console.log(data); const result = await this.updateCustomFields(userDto.userId, data); if (result) { if (!updatedData['customFields']) @@ -151,11 +157,16 @@ export class UserService { } async updateCustomFields(itemId,data){ - const result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); - + let result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); + let newResult; if (result.affected === 0) { - return null; - } + newResult = await this.fieldsValueRepository.save({ + itemId, + fieldId: data.fieldId, + value: data.value + }); + } + Object.assign(result, newResult); return result; } @@ -165,6 +176,8 @@ export class UserService { try { const decoded: any = jwt_decode(request.headers.authorization); const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + let cohortId = userCreateDto.cohortId; + delete userCreateDto.cohortId; userCreateDto.createdBy = userId userCreateDto.updatedBy = userId; @@ -177,18 +190,53 @@ export class UserService { const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - - resKeycloak = await createUserInKeyCloak(userSchema, token).catch( - (error) => { - errKeycloak = error.response?.data.errorMessage; - - return new ErrorResponse({ - errorCode: "500", - errorMessage: "Someting went wrong", - }); + let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) + if(checkUserinKeyCloakandDb){ + return response + .status(HttpStatus.BAD_REQUEST) + .json( + APIResponse.error( + apiId, + 'User Already Exist', + 'User already exists', + 'BAD_REQUEST', + ), + ); + } + resKeycloak = await createUserInKeyCloak(userSchema, token); + userCreateDto.userId = resKeycloak; + let result = await this.createUserInDatabase(request, userCreateDto,cohortId); + console.log(result); + let field_value_array = userCreateDto.fieldValues?.split("|"); + let fieldData = {}; + if(result && field_value_array?.length > 0) { + let userId = result.userId; + for (let i = 0; i < field_value_array?.length; i++) { + let fieldValues = field_value_array[i].split(":"); + fieldData={ + fieldId:fieldValues[0], + value:fieldValues[1] + } + console.log(fieldData); + let result = await this.updateCustomFields(userId,fieldData); + console.log(result); + if(!result) { + response + .status(HttpStatus.BAD_REQUEST) + .send( + ApiResponse.error( + apiId, + `Something went wrong ${result}`, + `Failure in UpdateCustomField`, + 'INTERNAL_SERVER_ERROR', + ), + ); } - ); userCreateDto.userId = resKeycloak; - return await this.createUserInDatabase(request, userCreateDto); + } + } + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, result, 'OK')); } catch (e) { response .status(HttpStatus.INTERNAL_SERVER_ERROR) @@ -211,30 +259,49 @@ export class UserService { userDto.username, token ); - if(usernameExistsInKeycloak){ + if(usernameExistsInKeycloak.data.length > 0) { return usernameExistsInKeycloak; } + return false; } - async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { - let userData = { - username:userCreateDto?.username, - name:userCreateDto?.name, - role:userCreateDto.role, - password:userCreateDto.password, - mobile:userCreateDto.mobile, - tenantId:userCreateDto.tenantId, - createdBy:userCreateDto.createdBy, - updatedby:userCreateDto.updatedBy, - userId:userCreateDto.userId, + async createUserInDatabase(request: any, userCreateDto: UserCreateDto,cohortId) { + const user = new User() + user.username=userCreateDto?.username + user.name=userCreateDto?.name + user.role=userCreateDto?.role + // user.mobile= Number(userCreateDto?.mobile), + user.tenantId=userCreateDto?.tenantId + user.createdBy=userCreateDto?.createdBy + user.updatedBy=userCreateDto?.updatedBy + user.userId=userCreateDto?.userId + let result = await this.usersRepository.save(user); + console.log(result.userId); + if(result) { + let cohortData = { + userId:result?.userId, + role:result?.role, + // createdBy:result?.userId, + // updatedBy:result?.userId, + tenantId:result?.tenantId, + cohortId:cohortId } - let result = await this.usersRepository.create(userData); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - });} + await this.addCohortMember(cohortData); + } + return result; } + + async addCohortMember(cohortData){ + try { + console.log(cohortData); + let result = await this.cohortMemberRepository.insert(cohortData); + return result;; + } catch (error) { + console.log(error); + throw new Error(error) + } + } +} From cddd8d948659a7934af9c4ab42508361bf661b5b Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 27 Mar 2024 19:36:37 +0530 Subject: [PATCH 134/408] chore : test for Keycloak --- src/app.controller.ts | 6 ++++-- src/app.service.ts | 4 ++-- src/auth/auth.module.ts | 3 ++- src/common/guards/keycloak.guard.ts | 16 ++++++++++++++++ src/common/guards/keycloak.strategy.ts | 23 +++++++++++++++++++++++ 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/common/guards/keycloak.guard.ts create mode 100644 src/common/guards/keycloak.strategy.ts diff --git a/src/app.controller.ts b/src/app.controller.ts index 42e665b1..18f351d5 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,12 +1,14 @@ -import { Controller, Get, Param, Res } from "@nestjs/common"; +import { Controller, Get, Param, Res, UseGuards } from "@nestjs/common"; import { AppService } from "./app.service"; +import { KeycloakAuthGuard } from "./common/guards/keycloak.guard"; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() - getHello(): string { + @UseGuards(KeycloakAuthGuard) + getHello(): object { return this.appService.getHello(); } diff --git a/src/app.service.ts b/src/app.service.ts index 92f4b485..3743f6df 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -3,7 +3,7 @@ require("dotenv").config(); @Injectable() export class AppService { - getHello(): string { - return process.env.ADAPTERSOURCE; + getHello(): object { + return { msg: "Welcome to Shiksha Backend" }; } } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 2a884be6..4cdcfce6 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -2,6 +2,7 @@ import { CacheModule, Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { AuthController } from "./auth.controller"; import { AuthService } from "./auth-service"; +import { KeycloakStrategy } from "src/common/guards/keycloak.strategy"; const ttl = process.env.TTL as never; @Module({ @@ -12,6 +13,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [AuthController], - providers: [AuthService], + providers: [AuthService, KeycloakStrategy], }) export class AuthModule {} diff --git a/src/common/guards/keycloak.guard.ts b/src/common/guards/keycloak.guard.ts new file mode 100644 index 00000000..9d11b080 --- /dev/null +++ b/src/common/guards/keycloak.guard.ts @@ -0,0 +1,16 @@ +import { Injectable, ExecutionContext, UnauthorizedException } from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; + +@Injectable() +export class KeycloakAuthGuard extends AuthGuard("keycloak") { + canActivate(context: ExecutionContext) { + return super.canActivate(context); + } + + handleRequest(err, user, info) { + if (err || !user) { + throw err || new UnauthorizedException(); + } + return user; + } +} diff --git a/src/common/guards/keycloak.strategy.ts b/src/common/guards/keycloak.strategy.ts new file mode 100644 index 00000000..dba8b864 --- /dev/null +++ b/src/common/guards/keycloak.strategy.ts @@ -0,0 +1,23 @@ +import { Injectable } from "@nestjs/common"; +import { PassportStrategy } from "@nestjs/passport"; +import { Strategy } from "passport-keycloak-oauth2-oidc"; +import { ConfigService } from "@nestjs/config"; + +@Injectable() +export class KeycloakStrategy extends PassportStrategy(Strategy, "keycloak") { + constructor(private readonly configService: ConfigService) { + super({ + host: configService.get("KEYCLOAK"), + realm: configService.get("KEYCLOAK_REALM"), + clientID: configService.get("KEYCLOAK_CLIENT_ID"), + clientSecret: configService.get("KEYCLOAK_HASURA_CLIENT_SECRET"), + authServerURL: configService.get("KEYCLOAK_AUTH_SERVER"), + callbackURL: configService.get("KEYCLOAK_AUTH_SERVER"), + }); + } + + async validate(accessToken: string, refreshToken: string, profile: any) { + // You can perform additional validation or data manipulation here + return { accessToken, refreshToken, profile }; + } +} From 4a3bb1f21177884198e71a78fa5203ea84949dfa Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 27 Mar 2024 19:37:11 +0530 Subject: [PATCH 135/408] chore : test for Keycloak --- package-lock.json | 757 +++++++++++++++++++++++++++++++++++++++++----- package.json | 3 + 2 files changed, 691 insertions(+), 69 deletions(-) diff --git a/package-lock.json b/package-lock.json index 95a563a0..a366f035 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@nestjs/config": "^2.0.0", "@nestjs/core": "^8.0.0", "@nestjs/jwt": "^8.0.0", + "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^8.0.0", "@nestjs/schedule": "^1.1.0", "@nestjs/swagger": "^5.2.0", @@ -28,11 +29,13 @@ "form-data": "^4.0.0", "graphql-tag": "^2.12.6", "jwt-decode": "^3.1.2", + "keycloak-connect": "^24.0.2", "moment": "^2.29.3", "multer": "^1.4.4", "node-cron": "^3.0.1", "node-schedule": "^2.1.0", "object-resolve-path": "^1.1.1", + "passport-keycloak-oauth2-oidc": "^1.0.5", "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", @@ -1530,6 +1533,15 @@ } } }, + "node_modules/@nestjs/passport": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz", + "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0" + } + }, "node_modules/@nestjs/platform-express": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-8.4.1.tgz", @@ -1865,6 +1877,12 @@ "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" }, + "node_modules/@testim/chrome-version": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", + "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==", + "optional": true + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1874,6 +1892,12 @@ "node": ">= 6" } }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "optional": true + }, "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", @@ -2213,6 +2237,15 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", @@ -2808,6 +2841,29 @@ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", "dev": true }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "optional": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/async": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", @@ -2942,6 +2998,23 @@ } ] }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2985,6 +3058,11 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", @@ -3039,6 +3117,11 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -3113,6 +3196,15 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "optional": true, + "engines": { + "node": "*" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3270,6 +3362,39 @@ "node": ">=6.0" } }, + "node_modules/chromedriver": { + "version": "123.0.0", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-123.0.0.tgz", + "integrity": "sha512-OE9mpxXwbFy5LncAisqXm1aEzuLPtEMORIxyYIn9uT7N8rquJWyoip6w9Rytub3o2gnynW9+PFOTPVTldaYrtw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@testim/chrome-version": "^1.1.4", + "axios": "^1.6.7", + "compare-versions": "^6.1.0", + "extract-zip": "^2.0.1", + "proxy-agent": "^6.4.0", + "proxy-from-env": "^1.1.0", + "tcp-port-used": "^1.0.2" + }, + "bin": { + "chromedriver": "bin/chromedriver" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chromedriver/node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "optional": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -3450,6 +3575,12 @@ "node": ">= 6" } }, + "node_modules/compare-versions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", + "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", + "optional": true + }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -3661,6 +3792,15 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "optional": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -3721,7 +3861,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "devOptional": true }, "node_modules/deepmerge": { "version": "4.2.2", @@ -3756,6 +3896,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "optional": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3912,6 +4066,20 @@ "integrity": "sha512-b+DdcyOiZtLXHdgEG8lncYJdxbdJWJvclPNMg0eLUDcSOSO876WA/pYjdSblUTd7eJdIs4YdIxHWGazx7UPSJw==", "dev": true }, + "node_modules/elliptic": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", + "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -3941,7 +4109,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, + "devOptional": true, "dependencies": { "once": "^1.4.0" } @@ -3997,15 +4165,14 @@ } }, "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "devOptional": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" + "esutils": "^2.0.2" }, "bin": { "escodegen": "bin/escodegen.js", @@ -4018,36 +4185,6 @@ "source-map": "~0.6.1" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", @@ -4246,7 +4383,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, + "devOptional": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4283,7 +4420,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=4.0" } @@ -4292,7 +4429,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -4433,6 +4570,41 @@ "node": ">=4" } }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "optional": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4496,6 +4668,15 @@ "bser": "2.1.1" } }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "optional": true, + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -4598,9 +4779,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -4896,6 +5077,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-uri": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "optional": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4", + "fs-extra": "^11.2.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "optional": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -4972,7 +5182,16 @@ "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true + "devOptional": true + }, + "node_modules/graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } }, "node_modules/graphql-tag": { "version": "2.12.6", @@ -5029,6 +5248,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -5046,6 +5274,16 @@ "node": "*" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -5272,6 +5510,34 @@ "node": ">= 0.10" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "optional": true + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5417,6 +5683,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "optional": true + }, + "node_modules/is2": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", + "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", + "optional": true, + "dependencies": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + }, + "engines": { + "node": ">=v0.10.0" + } + }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -6221,6 +6507,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "optional": true + }, "node_modules/jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", @@ -6342,7 +6634,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, + "devOptional": true, "dependencies": { "universalify": "^2.0.0" }, @@ -6389,6 +6681,16 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/jwk-to-pem": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.5.tgz", + "integrity": "sha512-L90jwellhO8jRKYwbssU9ifaMVqajzj3fpRjDKcsDzrslU9syRbFqfkXtT4B89HYAap+xsxNcxgBSB09ig+a7A==", + "dependencies": { + "asn1.js": "^5.3.0", + "elliptic": "^6.5.4", + "safe-buffer": "^5.0.1" + } + }, "node_modules/jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -6403,6 +6705,20 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, + "node_modules/keycloak-connect": { + "version": "24.0.2", + "resolved": "https://registry.npmjs.org/keycloak-connect/-/keycloak-connect-24.0.2.tgz", + "integrity": "sha512-o4hrHAI5SxIVqyD1yY0uIhDM6y9hZyyb3pJc1yYakhfhn2WPqmOGeq8zELPS1XJpj+k/paS+65LW45en1HgebA==", + "dependencies": { + "jwk-to-pem": "^2.0.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "chromedriver": "latest" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -6740,6 +7056,16 @@ "node": ">=6" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6865,6 +7191,15 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "optional": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/node-cron": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.1.tgz", @@ -6972,6 +7307,11 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, + "node_modules/oauth": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", + "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7172,6 +7512,76 @@ "node": ">=6" } }, + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "optional": true, + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "optional": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "optional": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "optional": true, + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -7228,6 +7638,60 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "peer": true, + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-keycloak-oauth2-oidc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/passport-keycloak-oauth2-oidc/-/passport-keycloak-oauth2-oidc-1.0.5.tgz", + "integrity": "sha512-uvZGTFu7MozqOIocDdSlEImEQTaPd8g5Lwbt83SbFqOVvCS3PelKjMQOYoJ7ERL7ELOY6puV0BY+Pw8ExM4EYw==", + "dependencies": { + "lodash": "^4.17.20", + "passport-oauth2": "^1.5.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.10.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -7296,6 +7760,18 @@ "node": ">=8" } }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", + "peer": true + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "optional": true + }, "node_modules/pg": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", @@ -7462,15 +7938,6 @@ "node": ">=0.10.0" } }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/prettier": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", @@ -7551,6 +8018,78 @@ "node": ">= 0.10" } }, + "node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "optional": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "optional": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "optional": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "optional": true + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -7561,7 +8100,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, + "devOptional": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -8069,6 +8608,56 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", + "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "optional": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "optional": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/sorted-array-functions": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", @@ -8395,6 +8984,33 @@ "node": ">=6" } }, + "node_modules/tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "optional": true, + "dependencies": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, + "node_modules/tcp-port-used/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/templates.js": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/templates.js/-/templates.js-0.3.11.tgz", @@ -8795,18 +9411,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -9123,11 +9727,16 @@ "node": ">=4.2.0" } }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 10.0.0" } @@ -9594,6 +10203,16 @@ "node": ">=10" } }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "optional": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 4026374b..3a1b2523 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@nestjs/config": "^2.0.0", "@nestjs/core": "^8.0.0", "@nestjs/jwt": "^8.0.0", + "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^8.0.0", "@nestjs/schedule": "^1.1.0", "@nestjs/swagger": "^5.2.0", @@ -40,11 +41,13 @@ "form-data": "^4.0.0", "graphql-tag": "^2.12.6", "jwt-decode": "^3.1.2", + "keycloak-connect": "^24.0.2", "moment": "^2.29.3", "multer": "^1.4.4", "node-cron": "^3.0.1", "node-schedule": "^2.1.0", "object-resolve-path": "^1.1.1", + "passport-keycloak-oauth2-oidc": "^1.0.5", "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", From 81d759b484c059bf2d39209f845a5aa3631cedae Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 28 Mar 2024 12:21:25 +0530 Subject: [PATCH 136/408] Task #216365: Create users API Updated with more fields Support --- src/user/user.service.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 91604469..32dfcd59 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -177,7 +177,7 @@ export class UserService { const decoded: any = jwt_decode(request.headers.authorization); const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; let cohortId = userCreateDto.cohortId; - delete userCreateDto.cohortId; + delete userCreateDto?.cohortId; userCreateDto.createdBy = userId userCreateDto.updatedBy = userId; @@ -206,7 +206,6 @@ export class UserService { resKeycloak = await createUserInKeyCloak(userSchema, token); userCreateDto.userId = resKeycloak; let result = await this.createUserInDatabase(request, userCreateDto,cohortId); - console.log(result); let field_value_array = userCreateDto.fieldValues?.split("|"); let fieldData = {}; if(result && field_value_array?.length > 0) { @@ -217,9 +216,7 @@ export class UserService { fieldId:fieldValues[0], value:fieldValues[1] } - console.log(fieldData); let result = await this.updateCustomFields(userId,fieldData); - console.log(result); if(!result) { response .status(HttpStatus.BAD_REQUEST) @@ -270,13 +267,21 @@ export class UserService { user.username=userCreateDto?.username user.name=userCreateDto?.name user.role=userCreateDto?.role - // user.mobile= Number(userCreateDto?.mobile), + user.mobile= Number(userCreateDto?.mobile), user.tenantId=userCreateDto?.tenantId user.createdBy=userCreateDto?.createdBy user.updatedBy=userCreateDto?.updatedBy - user.userId=userCreateDto?.userId + user.userId=userCreateDto?.userId, + user.state=userCreateDto?.state, + user.district=userCreateDto?.district, + user.address=userCreateDto?.address, + user.pincode=userCreateDto?.pincode + + if (userCreateDto?.dob) { + user.dob = new Date(userCreateDto.dob); + } + let result = await this.usersRepository.save(user); - console.log(result.userId); if(result) { let cohortData = { userId:result?.userId, @@ -293,7 +298,6 @@ export class UserService { async addCohortMember(cohortData){ try { - console.log(cohortData); let result = await this.cohortMemberRepository.insert(cohortData); return result;; } catch (error) { From 3d8dfb8e54544db75a6db68f5309e59105273633 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 28 Mar 2024 15:56:51 +0530 Subject: [PATCH 137/408] Task #216365: Removed Express Response to overcome node issue --- src/user/dto/user-create.dto.ts | 9 ++--- src/user/user.controller.ts | 3 +- src/user/user.service.ts | 64 +++++++++++++++------------------ 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 1f5aa24f..992efe77 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -22,10 +22,11 @@ export class UserCreateDto { @Expose() username: string; - @ApiProperty({ - type: String, - description: "The name of the user", - }) + // @ApiProperty({ + // type: String, + // description: "The name of the user", + // }) + @ApiProperty({ type: () => String }) @Expose() name: string; diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 3ccaba1b..76a5d250 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -112,11 +112,10 @@ export class UserController { async createUser( @Headers() headers, @Req() request: Request, - @Res() response:Response, @Body() userCreateDto: UserCreateDto ) { userCreateDto.tenantId = headers["tenantid"]; - return this.userService.createUser(request, userCreateDto,response); + return this.userService.createUser(request, userCreateDto); } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 32dfcd59..330a0a46 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -170,12 +170,13 @@ export class UserService { return result; } - async createUser(request: any, userCreateDto: UserCreateDto,response) { + async createUser(request: any, userCreateDto: UserCreateDto) { // It is considered that if user is not present in keycloak it is not present in database as well let apiId='api.user.creatUser' try { const decoded: any = jwt_decode(request.headers.authorization); const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + console.log(userId); let cohortId = userCreateDto.cohortId; delete userCreateDto?.cohortId; userCreateDto.createdBy = userId @@ -192,18 +193,21 @@ export class UserService { const token = keycloakResponse.data.access_token; let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) if(checkUserinKeyCloakandDb){ - return response - .status(HttpStatus.BAD_REQUEST) - .json( - APIResponse.error( - apiId, - 'User Already Exist', - 'User already exists', - 'BAD_REQUEST', - ), - ); + return new ErrorResponse({ + errorCode: "400", + errorMessage: "User Already Exists", + }); } - resKeycloak = await createUserInKeyCloak(userSchema, token); + resKeycloak = await createUserInKeyCloak(userSchema, token).catch( + (error) => { + errKeycloak = error.response?.data.errorMessage; + + return new ErrorResponse({ + errorCode: "500", + errorMessage: "Someting went wrong", + }); + } + ); userCreateDto.userId = resKeycloak; let result = await this.createUserInDatabase(request, userCreateDto,cohortId); let field_value_array = userCreateDto.fieldValues?.split("|"); @@ -218,33 +222,23 @@ export class UserService { } let result = await this.updateCustomFields(userId,fieldData); if(!result) { - response - .status(HttpStatus.BAD_REQUEST) - .send( - ApiResponse.error( - apiId, - `Something went wrong ${result}`, - `Failure in UpdateCustomField`, - 'INTERNAL_SERVER_ERROR', - ), - ); + return new ErrorResponse({ + errorCode: "500", + errorMessage: `Error is ${result}`, + }); } } } - return response - .status(HttpStatus.OK) - .send(APIResponse.success(apiId, result, 'OK')); + return new SuccessResponse({ + statusCode: 200, + message: "ok", + data: result, + }); } catch (e) { - response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - ApiResponse.error( - apiId, - 'Something went wrong', - `Failure Posting Data. Error is: ${e}`, - 'INTERNAL_SERVER_ERROR', - ), - ); + return new ErrorResponse({ + errorCode: "500", + errorMessage: `Error is ${e}`, + }); } } From cfe6eb64e6180a39d48ba560c41e81a5882b3803 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 28 Mar 2024 19:07:20 +0530 Subject: [PATCH 138/408] Fix[response code matching with postman for attendance API's] --- src/attendance/attendance.controller.ts | 48 +++++++---- src/attendance/attendance.service.ts | 103 ++++++++++++++---------- src/attendance/dto/attendance.dto.ts | 8 +- src/error-response-typeorm.ts | 13 +++ 4 files changed, 109 insertions(+), 63 deletions(-) create mode 100644 src/error-response-typeorm.ts diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 7c0a36e7..c23af646 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -28,6 +28,7 @@ import { Headers, UsePipes, ValidationPipe, + Res, } from "@nestjs/common"; import { AttendanceDto, BulkAttendanceDTO } from "./dto/attendance.dto"; import { FileInterceptor } from "@nestjs/platform-express"; @@ -39,6 +40,7 @@ import { AttendaceAdapter } from "./attendanceadapter"; import { AttendanceDateDto } from "./dto/attendance-date.dto"; import { AttendanceService } from './attendance.service'; import { AttendanceStatsDto } from "./dto/attendance-stats.dto"; +import { Response } from "express"; @ApiTags("Attendance") @Controller("attendance") @@ -90,7 +92,7 @@ export class AttendanceController { ) @ApiBody({ type: AttendanceDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -99,11 +101,13 @@ export class AttendanceController { @Headers() headers, @Req() request: Request, @Body() attendanceDto: AttendanceDto, + @Res() response:Response, @UploadedFile() image ) { attendanceDto.tenantId = headers["tenantid"]; attendanceDto.image = image?.filename; - return this.attendaceService.updateAttendanceRecord(request, attendanceDto); + const result = await this.attendaceService.updateAttendanceRecord(request, attendanceDto); + return response.status(result.statusCode).json(result); } @Put("/:id") @@ -128,21 +132,24 @@ export class AttendanceController { @Param("id") attendanceId: string, @Req() request: Request, @Body() attendanceDto: AttendanceDto, + @Res() response:Response, @UploadedFile() image ) { - const response = { + const res = { image: image?.filename, }; Object.assign(attendanceDto, response); - return this.attendaceService - .updateAttendance(attendanceId, request, attendanceDto); + const result = await this.attendaceService + .updateAttendance(attendanceId, request, attendanceDto); + return response.status(result.statusCode).json(result); + } @Post("/search") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Attendance list." }) @ApiBody({ type: AttendanceSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", @@ -153,15 +160,17 @@ export class AttendanceController { public async searchAttendanceNew( @Headers() headers, @Req() request: Request, - @Body() studentSearchDto: AttendanceSearchDto + @Body() studentSearchDto: AttendanceSearchDto, + @Res() response:Response ) { let tenantid = headers["tenantid"]; - return this.attendaceService + + const result = await this.attendaceService .searchAttendance(tenantid, request, studentSearchDto); + return response.status(result.statusCode).json(result); } @Post("/bydate") - @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: " Ok." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -172,10 +181,12 @@ export class AttendanceController { public async attendanceFilter( @Headers() headers, @Req() request: Request, + @Res() response:Response, @Body() attendanceDateDto: AttendanceDateDto ) { const tenantId = headers["tenantid"]; - return this.attendaceService.attendanceByDate(tenantId, request, attendanceDateDto); + const result = await this.attendaceService.attendanceByDate(tenantId, request, attendanceDateDto); + return response.status(result.statusCode).json(result); } @Post("bulkAttendance") @@ -185,7 +196,6 @@ export class AttendanceController { }) @ApiBody({ type: BulkAttendanceDTO }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -193,11 +203,13 @@ export class AttendanceController { public async multipleAttendance( @Headers() headers, @Req() request: Request, + @Res() response:Response, @Body() attendanceDtos: BulkAttendanceDTO ) { - let tenantid = headers["tenantid"]; - return this.attendaceService - .multipleAttendance(tenantid, request, attendanceDtos); + let tenantId = headers["tenantid"]; + const result = await this.attendaceService + .multipleAttendance(tenantId, request, attendanceDtos); + return response.status(result.statusCode).json(result); } @Post("/report") @@ -205,7 +217,6 @@ export class AttendanceController { @ApiCreatedResponse({ description: "Attendance list." }) @ApiBody({ type: AttendanceStatsDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) @@ -213,11 +224,14 @@ export class AttendanceController { public async report( @Headers() headers, @Req() request: Request, + @Res() response:Response, @Body() attendanceStatsDto: AttendanceStatsDto ) { let tenantid = headers["tenantid"]; - return this.attendaceService - .attendanceReport(attendanceStatsDto); + + const result = await this.attendaceService + .attendanceReport(attendanceStatsDto); + return response.status(result.statusCode).json(result); } /** No longer required in Shiksha 2.0 */ diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index db057af0..3580bbad 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -7,7 +7,6 @@ import { InjectRepository } from "@nestjs/typeorm"; import { AttendanceEntity } from "./entities/attendance.entity"; import { Repository } from "typeorm"; import { BadRequestException, HttpException, HttpStatus, Injectable } from "@nestjs/common"; -import { ErrorResponse } from "src/error-response"; import { AttendanceSearchDto } from "./dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; import { AttendanceDto, BulkAttendanceDTO } from './dto/attendance.dto'; @@ -15,6 +14,7 @@ import { AttendanceDateDto } from './dto/attendance-date.dto'; import { Between } from 'typeorm'; import { AttendanceStatsDto } from './dto/attendance-stats.dto'; import { format } from 'date-fns' +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; const moment = require('moment'); @Injectable() @@ -35,6 +35,7 @@ export class AttendanceService { async searchAttendance(tenantId: string, request: any, attendanceSearchDto: AttendanceSearchDto) { try { + let { limit, page, filters } = attendanceSearchDto; if (!limit) { limit = '0'; @@ -61,14 +62,14 @@ export class AttendanceService { const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: 'Ok.', totalCount, data: mappedResponse, }); } catch (error) { - return new ErrorResponse({ - errorCode: '500', + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: error, }); } @@ -78,12 +79,10 @@ export class AttendanceService { let { contextId, attendanceDate, report, limit, offset, filters } = attendanceStatsDto try { - - if (report === true) { let nameFilter = ''; if (filters && filters.search) { - nameFilter = `AND u."name" LIKE '%${filters.search.trim()}%'`; + nameFilter = `AND u."name" ILIKE '%${filters.search.trim()}%'`; } let query = ` SELECT u."userId",u."name", @@ -119,7 +118,7 @@ export class AttendanceService { return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: "Ok.", data: report, }); @@ -151,8 +150,8 @@ export class AttendanceService { else { - return new ErrorResponse({ - errorCode: "400", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, errorMessage: "Please provide valid attendance date", }); @@ -161,9 +160,9 @@ export class AttendanceService { } catch (error) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: "Internal server error", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, }); @@ -264,19 +263,19 @@ export class AttendanceService { ); - if (attendanceFound?.errorCode) { - return new ErrorResponse({ - errorCode: "500", + if (attendanceFound instanceof ErrorResponseTypeOrm) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: attendanceFound?.errorMessage, }); } if ( attendanceFound.data.length > 0 && - attendanceFound.statusCode === 200 + attendanceFound.statusCode === 200 && attendanceFound instanceof SuccessResponse ) { - return await this.updateAttendance( + return await this.updateAttendance( attendanceFound.data[0].attendanceId, request, attendanceDto @@ -286,7 +285,10 @@ export class AttendanceService { return await this.createAttendance(request, attendanceDto); } } catch (e) { - return e; + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } } @@ -300,13 +302,14 @@ export class AttendanceService { attendanceDto: AttendanceDto ) { try { + const attendanceRecord = await this.attendanceRepository.findOne({ where: { attendanceId }, }); if (!attendanceRecord) { - return new ErrorResponse({ - errorCode: "404", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, errorMessage: "Attendance record not found", }); } @@ -320,18 +323,18 @@ export class AttendanceService { ); return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: "Attendance record updated successfully", data: updatedAttendanceRecord, }); } catch (error) { - if (error instanceof BadRequestException) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: "Internal Server Error", + + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, }); - } + } } @@ -341,25 +344,27 @@ export class AttendanceService { */ public async createAttendance(request: any, attendanceDto: AttendanceDto) { + + try { const attendance = this.attendanceRepository.create(attendanceDto); const result = await this.attendanceRepository.save(attendance); return new SuccessResponse({ - statusCode: 200, - message: "Ok.", + statusCode: HttpStatus.CREATED, + message: "Attendance created successfully.", data: result, }); } catch (error) { - if (error.code === '23503' && error.constraint === 'Attendance_userId_fkey') { - // Handle foreign key constraint violation - return new ErrorResponse({ - errorCode: "23503", + + if (error.code == '23503') { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, errorMessage: "Please provide valid userID", }); } else { - return new ErrorResponse({ - errorCode: "500", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: 'Internal Server Error', }); } @@ -412,14 +417,14 @@ export class AttendanceService { const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: "Ok", totalCount: totalCount, data: mappedResponse, }); } catch (e) { - return new ErrorResponse({ - errorCode: "500", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -434,40 +439,50 @@ export class AttendanceService { request: any, attendanceData: BulkAttendanceDTO ) { + const responses = []; const errors = []; try { let count = 1; for (let attendance of attendanceData.userAttendance) { + + const userAttendance = new AttendanceDto({ attendanceDate: attendanceData.attendanceDate, contextId: attendanceData.contextId, attendance: attendance.attendance, - userId: attendance.userId + userId: attendance.userId, + tenantId:tenantId }) const attendanceRes: any = await this.updateAttendanceRecord( request, userAttendance ); - if (attendanceRes?.statusCode === 200) { + + if (attendanceRes?.statusCode === 200||attendanceRes?.statusCode === 201) { responses.push(attendanceRes.data); - } else { + } + else { errors.push({ userId: attendance.userId, attendanceRes, }); } count++; - + + } } catch (e) { - return e; + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } return { - statusCode: 200, + statusCode: HttpStatus.OK, totalCount: attendanceData.userAttendance.length, successCount: responses.length, errorCount: errors.length, diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 9c24f471..c98fe01a 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -1,6 +1,6 @@ import { ManyToOne, JoinColumn } from 'typeorm'; -import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, Validate, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; -import { Exclude, Expose, Transform } from "class-transformer"; +import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, Validate, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; +import { Exclude, Expose, Transform, Type } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsObject } from 'class-validator'; import { User } from 'src/user/entities/user-entity'; @@ -187,6 +187,10 @@ export class BulkAttendanceDTO { contextId: string; + + @ApiPropertyOptional() + @ValidateNested({ each: true }) + @Type(() => UserAttendanceDTO) // Adjust the max size according to your requirements userAttendance: UserAttendanceDTO[]; diff --git a/src/error-response-typeorm.ts b/src/error-response-typeorm.ts new file mode 100644 index 00000000..2655aed0 --- /dev/null +++ b/src/error-response-typeorm.ts @@ -0,0 +1,13 @@ +import { Expose } from "class-transformer"; + +export class ErrorResponseTypeOrm { + @Expose() + statusCode: number; + + @Expose() + errorMessage: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } +} From 65fb45b8066ef5e923e8a79b83d2684407a2bd5f Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 28 Mar 2024 19:09:59 +0530 Subject: [PATCH 139/408] Task #216371 : Auth Guard for Keycloak --- package.json | 6 +- src/app.controller.ts | 4 +- src/auth/auth-service.ts | 67 ----------------- src/auth/auth.controller.ts | 19 +++-- src/auth/auth.module.ts | 18 ++--- src/auth/auth.service.ts | 68 +++++++++++++++++ src/common/guards/keycloak.guard.ts | 17 +---- src/common/guards/keycloak.strategy.ts | 26 +++---- src/common/utils/keycloak.service.ts | 100 +++++++++++++++++++++++++ 9 files changed, 205 insertions(+), 120 deletions(-) delete mode 100644 src/auth/auth-service.ts create mode 100644 src/auth/auth.service.ts create mode 100644 src/common/utils/keycloak.service.ts diff --git a/package.json b/package.json index 17c55f02..0ba47a92 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "dependencies": { "@nestjs/axios": "^0.0.7", "@nestjs/common": "^8.4.2", - "@nestjs/config": "^2.0.0", + "@nestjs/config": "^2.3.4", "@nestjs/core": "^8.0.0", "@nestjs/jwt": "^8.0.0", "@nestjs/passport": "^10.0.3", @@ -41,13 +41,13 @@ "form-data": "^4.0.0", "graphql-tag": "^2.12.6", "jwt-decode": "^3.1.2", - "keycloak-connect": "^24.0.2", "moment": "^2.30.1", "multer": "^1.4.4", "node-cron": "^3.0.1", "node-schedule": "^2.1.0", "object-resolve-path": "^1.1.1", - "passport-keycloak-oauth2-oidc": "^1.0.5", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", diff --git a/src/app.controller.ts b/src/app.controller.ts index 18f351d5..b92a83d0 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,13 +1,13 @@ import { Controller, Get, Param, Res, UseGuards } from "@nestjs/common"; import { AppService } from "./app.service"; -import { KeycloakAuthGuard } from "./common/guards/keycloak.guard"; +import { JwtAuthGuard } from "./common/guards/keycloak.guard"; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() - @UseGuards(KeycloakAuthGuard) + @UseGuards(JwtAuthGuard) getHello(): object { return this.appService.getHello(); } diff --git a/src/auth/auth-service.ts b/src/auth/auth-service.ts deleted file mode 100644 index a810447b..00000000 --- a/src/auth/auth-service.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { HttpStatus, Injectable } from '@nestjs/common'; -import { UserService } from '../user/user.service'; -import axios from 'axios'; -import qs from 'qs' -import jwt_decode from "jwt-decode"; -import APIResponse from 'src/utils/response'; - - - -@Injectable() -@Injectable() -export class AuthService { - private axiosInstance; - constructor(private readonly userService: UserService){ - this.axiosInstance = axios.create();} - - async login(authDto,response){ - try{ - const { KEYCLOAK, KEYCLOAK_USER_TOKEN, KEYCLOAK_HASURA_CLIENT_SECRET } = process.env; - const data = qs.stringify({ - username: authDto.username, - password: authDto.password, - grant_type: "password", - client_id: "hasura", - client_secret: KEYCLOAK_HASURA_CLIENT_SECRET, - }); - - const axiosConfig = { - method: "post", - url: `${KEYCLOAK}${KEYCLOAK_USER_TOKEN}`, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - data: data, - }; - - const res = await this.axiosInstance(axiosConfig); - return response.status(200).send(res.data); - } catch (error) { - console.error(error); - return response.status(500).send({ message: 'An error occurred during login.' }); - } - } - - public async getUserByAuth(request: any,response) { - let apiId = 'api.auth.getUserDetails'; - try { - const decoded: any = jwt_decode(request.headers.authorization); - const username = decoded.preferred_username; - let data = await this.userService.findUserDetails(null,username) - return response - .status(HttpStatus.OK) - .send(APIResponse.success(apiId, data, 'OK')); - }catch(e){ - response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - 'Something went wrong In finding UserDetails', - e, - 'INTERNAL_SERVER_ERROR', - ), - ); - } -} -} \ No newline at end of file diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index f99c1358..5504fcff 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -23,14 +23,12 @@ import { Headers, } from "@nestjs/common"; import { AuthDto } from "./dto/auth-dto"; -import { AuthService } from "./auth-service"; +import { AuthService } from "./auth.service"; @ApiTags("Auth") @Controller("auth") export class AuthController { - constructor( - private authService:AuthService - ) {} + constructor(private authService: AuthService) {} @Post("/login") @ApiBody({ type: AuthDto }) @@ -44,11 +42,10 @@ export class AuthController { @Res() response: Response, @Body() authDto: AuthDto ) { - console.log(request) - return this.authService.login(authDto,response); + return this.authService.login(authDto, response); } - @Get('/getUserDetails') + @Get("/getUserDetails") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -58,9 +55,11 @@ export class AuthController { @ApiHeader({ name: "tenantid", }) - public async getUserByAuth(@Req() request: Request,@Res() response:Response){ + public async getUserByAuth( + @Req() request: Request, + @Res() response: Response + ) { // const tenantId = headers["tenantid"]; - return this.authService.getUserByAuth(request,response); + return this.authService.getUserByAuth(request, response); } - } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 1fa0e63f..36417ada 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,30 +1,26 @@ import { CacheModule, Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { AuthController } from "./auth.controller"; -import { AuthService } from "./auth-service"; -import { KeycloakStrategy } from "src/common/guards/keycloak.strategy"; +import { AuthService } from "./auth.service"; +import { JwtStrategy } from "src/common/guards/keycloak.strategy"; import { UserService } from "src/user/user.service"; import { TypeOrmModule } from "@nestjs/typeorm"; -import {User} from '../user/entities/user-entity'; -import { FieldValues } from '../user/entities/field-value-entities' +import { User } from "../user/entities/user-entity"; +import { FieldValues } from "../user/entities/field-value-entities"; import { Field } from "src/user/entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; +import { KeycloakService } from "src/common/utils/keycloak.service"; const ttl = process.env.TTL as never; @Module({ imports: [ - TypeOrmModule.forFeature([ - User, - FieldValues, - Field, - CohortMembers - ]), + TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers]), HttpModule, CacheModule.register({ ttl: ttl, }), ], controllers: [AuthController], - providers: [AuthService, KeycloakStrategy,UserService], + providers: [AuthService, JwtStrategy, KeycloakService, UserService], }) export class AuthModule {} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts new file mode 100644 index 00000000..1e2b4a00 --- /dev/null +++ b/src/auth/auth.service.ts @@ -0,0 +1,68 @@ +import { HttpStatus, Injectable } from "@nestjs/common"; +import { UserService } from "../user/user.service"; +import axios from "axios"; +import qs from "qs"; +import jwt_decode from "jwt-decode"; +import APIResponse from "src/utils/response"; + +@Injectable() +export class AuthService { + private axiosInstance; + constructor(private readonly userService: UserService) { + this.axiosInstance = axios.create(); + } + + async login(authDto, response) { + try { + const { KEYCLOAK, KEYCLOAK_USER_TOKEN, KEYCLOAK_HASURA_CLIENT_SECRET } = + process.env; + const data = qs.stringify({ + username: authDto.username, + password: authDto.password, + grant_type: "password", + client_id: "hasura", + client_secret: KEYCLOAK_HASURA_CLIENT_SECRET, + }); + + const axiosConfig = { + method: "post", + url: `${KEYCLOAK}${KEYCLOAK_USER_TOKEN}`, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + data: data, + }; + + const res = await this.axiosInstance(axiosConfig); + return response.status(200).send(res.data); + } catch (error) { + console.error(error); + return response + .status(500) + .send({ message: "An error occurred during login." }); + } + } + + public async getUserByAuth(request: any, response) { + let apiId = "api.auth.getUserDetails"; + try { + const decoded: any = jwt_decode(request.headers.authorization); + const username = decoded.preferred_username; + let data = await this.userService.findUserDetails(null, username); + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, data, "OK")); + } catch (e) { + response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong In finding UserDetails", + e, + "INTERNAL_SERVER_ERROR" + ) + ); + } + } +} diff --git a/src/common/guards/keycloak.guard.ts b/src/common/guards/keycloak.guard.ts index 9d11b080..768afc54 100644 --- a/src/common/guards/keycloak.guard.ts +++ b/src/common/guards/keycloak.guard.ts @@ -1,16 +1,5 @@ -import { Injectable, ExecutionContext, UnauthorizedException } from "@nestjs/common"; -import { AuthGuard } from "@nestjs/passport"; +import { Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; @Injectable() -export class KeycloakAuthGuard extends AuthGuard("keycloak") { - canActivate(context: ExecutionContext) { - return super.canActivate(context); - } - - handleRequest(err, user, info) { - if (err || !user) { - throw err || new UnauthorizedException(); - } - return user; - } -} +export class JwtAuthGuard extends AuthGuard('jwt-keycloak') {} diff --git a/src/common/guards/keycloak.strategy.ts b/src/common/guards/keycloak.strategy.ts index dba8b864..73d78aab 100644 --- a/src/common/guards/keycloak.strategy.ts +++ b/src/common/guards/keycloak.strategy.ts @@ -1,23 +1,23 @@ -import { Injectable } from "@nestjs/common"; +import { ExtractJwt, Strategy } from "passport-jwt"; import { PassportStrategy } from "@nestjs/passport"; -import { Strategy } from "passport-keycloak-oauth2-oidc"; +import { Injectable } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; @Injectable() -export class KeycloakStrategy extends PassportStrategy(Strategy, "keycloak") { - constructor(private readonly configService: ConfigService) { +export class JwtStrategy extends PassportStrategy(Strategy, "jwt-keycloak") { + constructor(configService: ConfigService) { super({ - host: configService.get("KEYCLOAK"), - realm: configService.get("KEYCLOAK_REALM"), - clientID: configService.get("KEYCLOAK_CLIENT_ID"), - clientSecret: configService.get("KEYCLOAK_HASURA_CLIENT_SECRET"), - authServerURL: configService.get("KEYCLOAK_AUTH_SERVER"), - callbackURL: configService.get("KEYCLOAK_AUTH_SERVER"), + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + ignoreExpiration: false, + secretOrKey: configService.get("KEYCLOAK_REALM_RSA_PUBLIC_KEY"), }); } - async validate(accessToken: string, refreshToken: string, profile: any) { - // You can perform additional validation or data manipulation here - return { accessToken, refreshToken, profile }; + async validate(payload: any) { + /** + * This can be obtained via req.user in the Controllers + * This is where we validate that the user is valid and delimit the payload returned to req.user + */ + return { userId: payload.sub }; } } diff --git a/src/common/utils/keycloak.service.ts b/src/common/utils/keycloak.service.ts new file mode 100644 index 00000000..0911897f --- /dev/null +++ b/src/common/utils/keycloak.service.ts @@ -0,0 +1,100 @@ +import { HttpService } from '@nestjs/axios'; +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { firstValueFrom } from 'rxjs'; + +type LoginResponse = { + access_token: string; + scope: string; + refresh_token: string; + token_type: string; + session_state: string; + 'not-before-policy': number; + refresh_expires_in: number; + expires_in: number; +}; + +type UserInfoResponse = { + sub: string; + email_verified: boolean; + preferred_username: string; +}; + +@Injectable() +export class KeycloakService { + private baseURL: string; + private realm: string; + private clientId: string; + private clientSecret: string; + + constructor( + private readonly configService: ConfigService, + private readonly httpService: HttpService, + ) { + this.baseURL = this.configService.get('KEYCLOAK_BASE_URL'); + this.realm = this.configService.get('KEYCLOAK_REALM'); + this.clientId = this.configService.get('KEYCLOAK_CLIENT_ID'); + this.clientSecret = this.configService.get('KEYCLOAK_CLIENT_SECRET'); + } + + async login(username: string, password: string): Promise { + const { data } = await firstValueFrom( + this.httpService.post( + `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/token`, + new URLSearchParams({ + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: 'password', + username, + password, + }), + ), + ); + + return data; + } + + async getUserInfo(accessToken: string): Promise { + const { data } = await firstValueFrom( + this.httpService.get( + `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/userinfo`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }, + ), + ); + + return data; + } + + async refreshToken(refreshToken: string): Promise { + const { data } = await firstValueFrom( + this.httpService.post( + `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/token`, + new URLSearchParams({ + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: 'refresh_token', + refresh_token: refreshToken, + }), + ), + ); + + return data; + } + + async logout(refreshToken: string) { + await firstValueFrom( + this.httpService.post( + `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/logout`, + new URLSearchParams({ + client_id: this.clientId, + client_secret: this.clientSecret, + refresh_token: refreshToken, + }), + ), + ); + } +} \ No newline at end of file From 14258c936751b14bda77cb0c0e53af224f90444b Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 28 Mar 2024 19:19:16 +0530 Subject: [PATCH 140/408] Fix[change in variable name] --- src/attendance/attendance.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index c23af646..482f96a0 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -135,7 +135,7 @@ export class AttendanceController { @Res() response:Response, @UploadedFile() image ) { - const res = { + const Imageresponse = { image: image?.filename, }; Object.assign(attendanceDto, response); From 96bf07fed254b2f91b6aa14b19a44a9195e96255 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 28 Mar 2024 21:18:23 +0530 Subject: [PATCH 141/408] COHORT: Get cohort data using userId --- src/cohortMembers/cohortMember.service.ts | 78 +++++++++++++++++++---- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 2d994301..c5614f68 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -19,8 +19,8 @@ import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; export class CohortMembersService { constructor( @InjectRepository(CohortMembers) - private cohortMembersRepository: Repository - ) {} + private cohortMembersRepository: Repository, + ) { } public async getCohortMembers( tenantId: string, @@ -96,28 +96,55 @@ export class CohortMembersService { Object.entries(filters).forEach(([key, value]) => { whereClause[key] = value; }); - } else { - whereClause["tenantId"] = tenantId; } - - const [cohortMembers, count] = - await this.cohortMembersRepository.findAndCount({ - where: whereClause, + let findCohortId = await this.findCohortName(whereClause['userId']); + console.log(findCohortId); + let result = { + cohortData: [] + }; + for (let data of findCohortId) { + result.cohortData.push(data) + let filterDetails = { + where: data.cohortId, take: parseInt(limit), skip: offset, - }); + } + const getDetails = await this.getUserDetails(filterDetails); + result.cohortData.push(getDetails); + // console.log(getDetails); + // result.push(getDetails); + + } + + console.log(result); + + + + + - const responseData = { - totalCount: count, - cohortMembers: cohortMembers, - }; + + + // console.log(getDetails); + + // const [cohortMembers, count] = + // await this.cohortMembersRepository.findAndCount({ + // where: whereClause, + // take: parseInt(limit), + // skip: offset, + // }); + + // const responseData = { + // totalCount: count, + // cohortMembers: cohortMembers, + // }; return response .status(HttpStatus.OK) .send( APIResponse.success( apiId, - responseData, + result, "Cohort Member Retrieved Successfully" ) ); @@ -135,6 +162,29 @@ export class CohortMembersService { } } + public async findCohortName(userId: any) { + let query = `SELECT c."name",c."cohortId" + FROM public."CohortMembers" AS cm + LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" + WHERE cm."userId"=$1` + let result = await this.cohortMembersRepository.query(query, [userId]) + return result; + } + + + public async getUserDetails(filter) { + let query = `SELECT f."label", fv."value",f."type",f."fieldParams" + FROM public."CohortMembers" cm + LEFT JOIN public."FieldValues" fv ON fv."itemId" = cm."cohortId" + LEFT JOIN public."Fields" f ON fv."fieldId" = f."fieldId" + WHERE cm."cohortId"= $1` + // console.log(filter.where); + + // console.log(query); + + let result = await this.cohortMembersRepository.query(query, [filter.where]) + return result; + } public async createCohortMembers( request: any, cohortMembers: CohortMembersDto, From 23171037bd9bd49f8c87dd30f24c986e7ceeb2d2 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 28 Mar 2024 23:56:22 +0530 Subject: [PATCH 142/408] Task #216220: Updated Response of Seacrh memner API --- src/cohortMembers/cohortMember.service.ts | 85 +++++++++++------------ 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index c5614f68..5eacc009 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -19,8 +19,8 @@ import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; export class CohortMembersService { constructor( @InjectRepository(CohortMembers) - private cohortMembersRepository: Repository, - ) { } + private cohortMembersRepository: Repository + ) {} public async getCohortMembers( tenantId: string, @@ -97,48 +97,33 @@ export class CohortMembersService { whereClause[key] = value; }); } - let findCohortId = await this.findCohortName(whereClause['userId']); - console.log(findCohortId); + + let findCohortId = await this.findCohortName(whereClause["userId"]); + let result = { - cohortData: [] + cohortData: [], }; + for (let data of findCohortId) { - result.cohortData.push(data) + let cohortData = { + cohortId: data.cohortId, + name:data.name, + customField: [], + }; + let filterDetails = { where: data.cohortId, take: parseInt(limit), skip: offset, - } + }; + const getDetails = await this.getUserDetails(filterDetails); - result.cohortData.push(getDetails); - // console.log(getDetails); - // result.push(getDetails); + console.log(getDetails); + cohortData.customField.push(getDetails); + result.cohortData.push(cohortData); } - console.log(result); - - - - - - - - - // console.log(getDetails); - - // const [cohortMembers, count] = - // await this.cohortMembersRepository.findAndCount({ - // where: whereClause, - // take: parseInt(limit), - // skip: offset, - // }); - - // const responseData = { - // totalCount: count, - // cohortMembers: cohortMembers, - // }; - return response .status(HttpStatus.OK) .send( @@ -161,28 +146,36 @@ export class CohortMembersService { ); } } - + async getDetailsForCohort(cohort) { + const filterDetails = { + where: cohort.cohortId, + take: parseInt(cohort.limit), + skip: cohort.offset, + }; + const getDetails = await this.getUserDetails(filterDetails); + return { ...cohort, customField: getDetails }; + } public async findCohortName(userId: any) { let query = `SELECT c."name",c."cohortId" FROM public."CohortMembers" AS cm LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" - WHERE cm."userId"=$1` - let result = await this.cohortMembersRepository.query(query, [userId]) + WHERE cm."userId"=$1`; + let result = await this.cohortMembersRepository.query(query, [userId]); return result; } - public async getUserDetails(filter) { - let query = `SELECT f."label", fv."value",f."type",f."fieldParams" + let query = `SELECT DISTINCT f."label", fv."value", f."type", f."fieldParams" FROM public."CohortMembers" cm - LEFT JOIN public."FieldValues" fv ON fv."itemId" = cm."cohortId" - LEFT JOIN public."Fields" f ON fv."fieldId" = f."fieldId" - WHERE cm."cohortId"= $1` - // console.log(filter.where); - - // console.log(query); - - let result = await this.cohortMembersRepository.query(query, [filter.where]) + LEFT JOIN ( + SELECT DISTINCT ON (fv."fieldId", fv."itemId") fv.* + FROM public."FieldValues" fv + ) fv ON fv."itemId" = cm."cohortId" + INNER JOIN public."Fields" f ON fv."fieldId" = f."fieldId" + WHERE cm."cohortId" = $1;`; + let result = await this.cohortMembersRepository.query(query, [ + filter.where, + ]); return result; } public async createCohortMembers( From 4140046606beaf2fa09551c6542423433d0dd597 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 28 Mar 2024 23:58:10 +0530 Subject: [PATCH 143/408] Task #216220: Updated Response of Search member API --- src/cohortMembers/cohortMember.service.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 5eacc009..9682b2bd 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -146,15 +146,6 @@ export class CohortMembersService { ); } } - async getDetailsForCohort(cohort) { - const filterDetails = { - where: cohort.cohortId, - take: parseInt(cohort.limit), - skip: cohort.offset, - }; - const getDetails = await this.getUserDetails(filterDetails); - return { ...cohort, customField: getDetails }; - } public async findCohortName(userId: any) { let query = `SELECT c."name",c."cohortId" FROM public."CohortMembers" AS cm From ac7c573adcf3eaa6113916cf8139cca389d326c1 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 29 Mar 2024 11:10:59 +0530 Subject: [PATCH 144/408] Removed Interceptor Class from View Profile API --- src/user/user.controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 76a5d250..7b636edc 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -58,7 +58,7 @@ export class UserController { * @since 1.6 */ @Get("/:userid") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -85,7 +85,7 @@ export class UserController { } @Get() - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) From 3293dcdf03632fbc21d2f0d44968438c3be93a48 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 29 Mar 2024 14:28:05 +0530 Subject: [PATCH 145/408] Fix[applie JWT token requirement for API at controller level] --- src/attendance/attendance.controller.ts | 5 ++++- src/cohort/cohort.controller.ts | 4 +++- src/cohortMembers/cohortMembers.controller.ts | 3 +++ src/fields/fields.controller.ts | 4 ++++ src/user/user.controller.ts | 3 +++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 482f96a0..4c9a87fe 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -29,6 +29,7 @@ import { UsePipes, ValidationPipe, Res, + UseGuards, } from "@nestjs/common"; import { AttendanceDto, BulkAttendanceDTO } from "./dto/attendance.dto"; import { FileInterceptor } from "@nestjs/platform-express"; @@ -41,9 +42,12 @@ import { AttendanceDateDto } from "./dto/attendance-date.dto"; import { AttendanceService } from './attendance.service'; import { AttendanceStatsDto } from "./dto/attendance-stats.dto"; import { Response } from "express"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; + @ApiTags("Attendance") @Controller("attendance") +@UseGuards(JwtAuthGuard) export class AttendanceController { constructor( private service: AttendanceHasuraService, @@ -75,7 +79,6 @@ export class AttendanceController { @Post() - @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index cb96ec58..68b295d7 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -25,6 +25,7 @@ import { Res, Headers, Delete, + UseGuards, } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -33,13 +34,14 @@ import { FileInterceptor } from "@nestjs/platform-express"; import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; import { diskStorage } from "multer"; import { Response, response } from "express"; - import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortService } from "./cohort.service"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; // import { FieldsService } from "../fields/fields.service"; @ApiTags("Cohort") @Controller("cohort") +@UseGuards(JwtAuthGuard) export class CohortController { constructor( private cohortAdapter: CohortAdapter, diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 8af7830d..0dd5cad2 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -22,6 +22,7 @@ import { CacheInterceptor, Headers, Res, + UseGuards, } from "@nestjs/common"; import { CohortMembersSearchDto } from "./dto/cohortMembers-search.dto"; import { Request } from "@nestjs/common"; @@ -30,9 +31,11 @@ import { CohortMembersAdapter } from "./cohortMembersadapter"; import { CohortMembersService } from "./cohortMember.service"; import { Response } from "@nestjs/common"; import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("Cohort Members") @Controller("cohortmembers") +@UseGuards(JwtAuthGuard) export class CohortMembersController { constructor( private cohortMembersAdapter: CohortMembersAdapter, diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 1c289ebd..f06e54dc 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -23,6 +23,7 @@ import { CacheInterceptor, UploadedFile, Headers, + UseGuards, } from "@nestjs/common"; import { FieldsSearchDto } from "./dto/fields-search.dto"; import { Request } from "@nestjs/common"; @@ -34,9 +35,12 @@ import { FieldsAdapter } from "./fieldsadapter"; import { FieldValuesDto } from "./dto/field-values.dto"; import { FieldValuesSearchDto } from "./dto/field-values-search.dto"; import { FieldsService } from "./fields.service"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; + @ApiTags("Fields") @Controller("fields") +@UseGuards(JwtAuthGuard) export class FieldsController { constructor(private fieldsAdapter: FieldsAdapter, private readonly fieldsService: FieldsService diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 76a5d250..d132fc43 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -15,6 +15,7 @@ import { Headers, Res, Patch, + UseGuards, } from "@nestjs/common"; import { SunbirdUserToken, @@ -38,8 +39,10 @@ import { UserAdapter } from "./useradapter"; import { UserCreateDto } from "./dto/user-create.dto"; import { UserService } from "./user.service"; import { UserUpdateDTO } from "./dto/user-update.dto"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("User") @Controller("user") +@UseGuards(JwtAuthGuard) export class UserController { constructor( private readonly service: UserService, From aee2fe6041b5f06c6ec9327b5f654f33d7cd44d5 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 29 Mar 2024 15:05:36 +0530 Subject: [PATCH 146/408] COHORT: Update field value data --- src/cohort/cohort.service.ts | 55 ++++++++++++------- src/cohort/entities/cohort.entity.ts | 4 -- .../entities/cohort-member.entity.ts | 5 -- src/fields/fields.service.ts | 17 ++++-- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index ca54dff1..e50aaa3e 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -20,6 +20,7 @@ import { FieldsService } from "../fields/fields.service"; import { response } from "express"; import APIResponse from "src/utils/response"; import { FieldValues } from "../fields/entities/fields-values.entity"; +import { v4 as uuidv4 } from 'uuid'; @Injectable() export class CohortService { @@ -44,7 +45,7 @@ export class CohortService { try { const cohort = await this.cohortRepository.findOne({ where: { cohortId: cohortId, status: "true" }, - select: ["cohortId","parentId","name","type","status","image","programId","attendanceCaptureImage"], + select: ["cohortId", "parentId", "name", "type", "status", "image", "programId", "attendanceCaptureImage"], }); // let searchField = { itemId: cohortId } @@ -63,7 +64,7 @@ export class CohortService { ) ); } - + cohort["customFields"] = fieldValue; const result = { cohort: cohort, @@ -93,6 +94,7 @@ export class CohortService { public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try { const cohortData: any = {}; + cohortCreateDto.cohortId = uuidv4(); Object.keys(cohortCreateDto).forEach((e) => { if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { if (Array.isArray(cohortCreateDto[e])) { @@ -102,11 +104,12 @@ export class CohortService { } } }); - const response = await this.cohortRepository.save(cohortData); + // const response = await this.cohortRepository.insert(cohortData); let cohortId = response?.cohortId; + let field_value_array = cohortCreateDto.fieldValues.split("|"); if (field_value_array.length > 0) { @@ -174,20 +177,34 @@ export class CohortService { let fieldValues = field_value_array[i].split(":"); let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; - const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) - const rowid = fieldVauesRowId.fieldValuesId; - - let fieldValueDto: FieldValuesDto = { - fieldValuesId: rowid, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.updateFieldValues(rowid, fieldValueDto); + try { + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + const rowid = fieldVauesRowId['fieldValuesId']; + + let fieldValueDto: FieldValuesDto = { + fieldValuesId: rowid, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.updateFieldValues(rowid, fieldValueDto); + }catch{ + let fieldValueDto: FieldValuesDto = { + fieldValuesId: null, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.createFieldValues(request, fieldValueDto); + } } } @@ -287,11 +304,11 @@ export class CohortService { cohortId: string ) { try { - let query =`UPDATE public."Cohort" + let query = `UPDATE public."Cohort" SET "status" = false WHERE "cohortId" = $1`; const results = await this.cohortRepository.query(query, [cohortId]); - + return new SuccessResponse({ statusCode: 200, message: "Cohort Deleted Successfully.", diff --git a/src/cohort/entities/cohort.entity.ts b/src/cohort/entities/cohort.entity.ts index a18abd1e..505561ba 100644 --- a/src/cohort/entities/cohort.entity.ts +++ b/src/cohort/entities/cohort.entity.ts @@ -6,7 +6,6 @@ import { UpdateDateColumn, ManyToMany, } from "typeorm"; -import { CohortMembers } from "../../cohortMembers/entities/cohort-member.entity"; @Entity({ name: "Cohort" }) export class Cohort { @@ -67,7 +66,4 @@ export class Cohort { }) updatedBy: Date; - @ManyToMany(() => CohortMembers, cohortMember => cohortMember.cohorts) - cohortMembers: CohortMembers[]; - } diff --git a/src/cohortMembers/entities/cohort-member.entity.ts b/src/cohortMembers/entities/cohort-member.entity.ts index 80117c19..7e2006e9 100644 --- a/src/cohortMembers/entities/cohort-member.entity.ts +++ b/src/cohortMembers/entities/cohort-member.entity.ts @@ -8,8 +8,6 @@ import { JoinTable, } from "typeorm"; -import { Cohort } from "../../cohort/entities/cohort.entity"; - @Entity({ name: "CohortMembers" }) export class CohortMembers { @PrimaryGeneratedColumn("uuid") @@ -45,7 +43,4 @@ export class CohortMembers { @Column({}) updatedBy: string; - @ManyToMany(() => Cohort, (cohort) => cohort.cohortMembers) - @JoinTable({ name: "cohort_members_cohort" }) // Specify the join table name here - cohorts: Cohort[]; } diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 65a687ea..694ece41 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -117,7 +117,7 @@ export class FieldsService { } } }); - + let result = await this.fieldsValuesRepository.save(fieldsData); return new SuccessResponse({ statusCode: 200, @@ -179,11 +179,16 @@ export class FieldsService { } - async searchFieldValueId(cohortId: string, fieldId: string){ - const response = await this.fieldsValuesRepository.findOne({ - where: { itemId: cohortId, fieldId: fieldId }, - }); - return response; + async searchFieldValueId(cohortId: string, fieldId: string){ + try{ + const response = await this.fieldsValuesRepository.findOne({ + where: { itemId: cohortId, fieldId: fieldId }, + }); + return response; + } catch{ + return "error"; + } + } async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { From ef1c6bb7ea6d0d6bb906a365d9300e3c6d81acb5 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 29 Mar 2024 15:07:30 +0530 Subject: [PATCH 147/408] add --- src/cohort/cohort.service.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index e50aaa3e..21fefffb 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -105,11 +105,8 @@ export class CohortService { } }); const response = await this.cohortRepository.save(cohortData); - // const response = await this.cohortRepository.insert(cohortData); - let cohortId = response?.cohortId; - let field_value_array = cohortCreateDto.fieldValues.split("|"); if (field_value_array.length > 0) { From ae6470821f61a5f7c547df04a999b5314d85c2c2 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 29 Mar 2024 15:26:18 +0530 Subject: [PATCH 148/408] update changes --- src/cohort/cohort.service.ts | 2 +- src/fields/fields.service.ts | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 21fefffb..1cfb25c0 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -176,7 +176,7 @@ export class CohortService { let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; try { const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) - const rowid = fieldVauesRowId['fieldValuesId']; + const rowid = fieldVauesRowId.fieldValuesId; let fieldValueDto: FieldValuesDto = { fieldValuesId: rowid, diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 694ece41..3a0b9fc9 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -179,16 +179,11 @@ export class FieldsService { } - async searchFieldValueId(cohortId: string, fieldId: string){ - try{ - const response = await this.fieldsValuesRepository.findOne({ - where: { itemId: cohortId, fieldId: fieldId }, - }); - return response; - } catch{ - return "error"; - } - + async searchFieldValueId(cohortId: string, fieldId: string){ + const response = await this.fieldsValuesRepository.findOne({ + where: { itemId: cohortId, fieldId: fieldId }, + }); + return response; } async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { From ad25e01a75fc67d1bb677cdb5cb90b2eeb2be26b Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 29 Mar 2024 15:40:09 +0530 Subject: [PATCH 149/408] Fix[filter added to get average percentage attendance for specific userId] --- src/attendance/attendance.service.ts | 35 +++++++++++++++++++--- src/attendance/dto/attendance-stats.dto.ts | 4 +++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 3580bbad..786011fa 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -81,9 +81,15 @@ export class AttendanceService { try { if (report === true) { let nameFilter = ''; + let userFilter = ''; + if (filters && filters.search) { nameFilter = `AND u."name" ILIKE '%${filters.search.trim()}%'`; } + if (filters && filters.userId) { + userFilter = ` AND u."userId"='${filters.userId.trim()}'`; + } + let query = ` SELECT u."userId",u."name", CASE @@ -94,10 +100,10 @@ export class AttendanceService { INNER JOIN public."Users" AS u ON cm."userId" = u."userId" LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" WHERE cm."cohortId" = $1 AND cm."role" = 'student' + ${userFilter} ${nameFilter} GROUP BY u."userId" - - `; + `; if (filters) { @@ -114,6 +120,26 @@ export class AttendanceService { LIMIT $2 OFFSET $3` const result = await this.attendanceRepository.query(query, [contextId, limit, offset]); + + // let countquery = `SELECT AVG(attendance_percentage) AS average_attendance_percentage + // FROM ( + // SELECT u."userId", u."name", + // CASE + // WHEN COUNT(*) = 0 THEN NULL + // ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'Present' THEN 1 END) * 100.0 / COUNT(*),2) + // END AS attendance_percentage + // FROM public."CohortMembers" AS cm + // INNER JOIN public."Users" AS u ON cm."userId" = u."userId" + // LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" + // WHERE cm."cohortId" = $1 AND cm."role" = 'student' + // ${userFilter} + // GROUP BY u."userId" + // ) AS subquery; + // ` + // const average=await this.attendanceRepository.query(countquery,[contextId]) + // console.log(average,) + + const report = await this.mapResponseforReport(result); @@ -121,6 +147,7 @@ export class AttendanceService { statusCode: HttpStatus.OK, message: "Ok.", data: report, + }); } else if (report === false) { @@ -144,7 +171,7 @@ export class AttendanceService { return new SuccessResponse({ statusCode: 200, message: "Ok.", - data: report, + data: report }); } @@ -205,7 +232,7 @@ export class AttendanceService { userId: item?.userId ? `${item.userId}` : "", attendance_percentage: item?.attendance_percentage ? `${item.attendance_percentage}` : "", }; - + return new AttendanceStatsDto(attendanceReportMapping); }); diff --git a/src/attendance/dto/attendance-stats.dto.ts b/src/attendance/dto/attendance-stats.dto.ts index 01369724..c8b60446 100644 --- a/src/attendance/dto/attendance-stats.dto.ts +++ b/src/attendance/dto/attendance-stats.dto.ts @@ -20,6 +20,10 @@ class FiltersDto { @IsString() @IsOptional() search: string; + + @IsString() + @IsOptional() + userId: string; } From 91a319c8c7b0d4b9202a2f0dd2ce26873583e3c6 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 29 Mar 2024 15:46:38 +0530 Subject: [PATCH 150/408] Task #216220: Get Cohort Lost API Created --- src/cohort/cohort.controller.ts | 11 ++-- src/cohort/cohort.module.ts | 10 +++- src/cohort/cohort.service.ts | 97 +++++++++++++++++++-------------- 3 files changed, 68 insertions(+), 50 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index cb96ec58..274b8941 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -81,9 +81,8 @@ export class CohortController { return this.cohortService.createCohort(request, cohortCreateDto); } - //get cohort - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @Get("cohortList/:id") + @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -93,14 +92,14 @@ export class CohortController { @ApiHeader({ name: "tenantid", }) - public async getCohort( + public async getCohortList( @Headers() headers, - @Param("id") cohortId: string, + @Param("id") userId: string, @Req() request: Request, @Res() response: Response ) { let tenantid = headers["tenantid"]; - return this.cohortService.getCohort(tenantid, cohortId, request, response); + return this.cohortService.getCohortList(tenantid, userId, request, response); } // search diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 50d74d18..9e659949 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -9,12 +9,16 @@ import { Cohort } from "./entities/cohort.entity"; import { FieldsService } from "../fields/fields.service"; import { Fields } from "../fields/entities/fields.entity"; import { FieldValues } from "../fields/entities/fields-values.entity"; +import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; const ttl = process.env.TTL as never; @Module({ imports: [ - TypeOrmModule.forFeature([Cohort]), - TypeOrmModule.forFeature([Fields]), - TypeOrmModule.forFeature([FieldValues]), + TypeOrmModule.forFeature([ + Cohort, + FieldValues, + Fields, + CohortMembers + ]), HttpModule, HasuraModule, CacheModule.register({ diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index ca54dff1..173c36d6 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Injectable } from "@nestjs/common"; +import { ConsoleLogger, HttpStatus, Injectable } from "@nestjs/common"; import { CohortInterface } from "./interfaces/cohort.interface"; import { HttpService } from "@nestjs/axios"; import { SuccessResponse } from "src/success-response"; @@ -20,6 +20,7 @@ import { FieldsService } from "../fields/fields.service"; import { response } from "express"; import APIResponse from "src/utils/response"; import { FieldValues } from "../fields/entities/fields-values.entity"; +import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; @Injectable() export class CohortService { @@ -28,54 +29,47 @@ export class CohortService { constructor( @InjectRepository(Cohort) - private cohortRepository: Repository, + @InjectRepository(CohortMembers) + private cohortMembersRepository: Repository, private fieldsService: FieldsService, ) { } - public async getCohort( + public async getCohortList( tenantId: string, - cohortId: string, + userId: string, request: any, response: any ) { const apiId = "api.concept.editminiScreeningAnswer"; - try { - const cohort = await this.cohortRepository.findOne({ - where: { cohortId: cohortId, status: "true" }, - select: ["cohortId","parentId","name","type","status","image","programId","attendanceCaptureImage"], - }); + console.log(userId); + let findCohortId = await this.findCohortName(userId); + console.log(findCohortId); + let result = { + cohortData: [], + }; - // let searchField = { itemId: cohortId } - - const fieldValue = await this.fieldsService.getFieldsAndFieldsValues(cohortId) - - if (!cohort) { - return response - .status(HttpStatus.NOT_FOUND) - .send( - APIResponse.error( - apiId, - `Cohort Id is wrong`, - `Cohort not found`, - "COHORT_NOT_FOUND" - ) - ); + for (let data of findCohortId) { + let cohortData = { + cohortId: data.cohortId, + name:data.name, + customField:{} + }; + const getDetails = await this.getCohortListDetails(data.cohortId); + cohortData.customField=getDetails + result.cohortData.push(cohortData); } - - cohort["customFields"] = fieldValue; - const result = { - cohort: cohort, - }; - return response.status(HttpStatus.OK).send( - APIResponse.success( - apiId, - result, - "Cohort Retrieved Successfully" - ) - ); + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + result, + "OK" + ) + ); } catch (error) { return response .status(HttpStatus.INTERNAL_SERVER_ERROR) @@ -83,13 +77,36 @@ export class CohortService { APIResponse.error( apiId, "Something went wrong", - `Failure Retrieving Cohort. Error is: ${error}`, + `Failure Retrieving Cohort Member. Error is: ${error}`, "INTERNAL_SERVER_ERROR" ) ); } + + } + public async findCohortName(userId: any) { + let query = `SELECT c."name",c."cohortId" + FROM public."CohortMembers" AS cm + LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" + WHERE cm."userId"=$1`; + let result = await this.cohortMembersRepository.query(query, [userId]); + return result; } + public async getCohortListDetails(userId) { + let query = `SELECT DISTINCT f."label", fv."value", f."type", f."fieldParams" + FROM public."CohortMembers" cm + LEFT JOIN ( + SELECT DISTINCT ON (fv."fieldId", fv."itemId") fv.* + FROM public."FieldValues" fv + ) fv ON fv."itemId" = cm."cohortId" + INNER JOIN public."Fields" f ON fv."fieldId" = f."fieldId" + WHERE cm."cohortId" = $1;`; + let result = await this.cohortMembersRepository.query(query, [ + userId + ]); + return result; + } public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try { const cohortData: any = {}; @@ -231,10 +248,8 @@ export class CohortService { whereClause[key] = value; }); } - else { - whereClause['tenantId'] = tenantId; - } - + console.log(whereClause); + return true; const [results, totalCount] = await this.cohortRepository.findAndCount({ where: whereClause, skip: offset, From 511b4c36637acfc7cbfea4b3de031d71e3e37a3f Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 29 Mar 2024 16:34:08 +0530 Subject: [PATCH 151/408] Fix[added average attendance percentage calculation to response of report list ] --- src/attendance/attendance.service.ts | 66 +++++++++++++++++----------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index 786011fa..f68e2b5d 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -76,7 +76,6 @@ export class AttendanceService { } async attendanceReport(attendanceStatsDto: AttendanceStatsDto) { - let { contextId, attendanceDate, report, limit, offset, filters } = attendanceStatsDto try { if (report === true) { @@ -105,7 +104,6 @@ export class AttendanceService { GROUP BY u."userId" `; - if (filters) { if (filters.nameOrder && filters.nameOrder==="asc" || filters.nameOrder==="desc") { query += ` ORDER BY "name" ${filters.nameOrder}` @@ -121,34 +119,50 @@ export class AttendanceService { OFFSET $3` const result = await this.attendanceRepository.query(query, [contextId, limit, offset]); - // let countquery = `SELECT AVG(attendance_percentage) AS average_attendance_percentage - // FROM ( - // SELECT u."userId", u."name", - // CASE - // WHEN COUNT(*) = 0 THEN NULL - // ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'Present' THEN 1 END) * 100.0 / COUNT(*),2) - // END AS attendance_percentage - // FROM public."CohortMembers" AS cm - // INNER JOIN public."Users" AS u ON cm."userId" = u."userId" - // LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" - // WHERE cm."cohortId" = $1 AND cm."role" = 'student' - // ${userFilter} - // GROUP BY u."userId" - // ) AS subquery; - // ` - // const average=await this.attendanceRepository.query(countquery,[contextId]) - // console.log(average,) - - - const report = await this.mapResponseforReport(result); - - + if((!filters) || (!filters?.userId)) + { + // We dont need average for single user + let countquery = `SELECT AVG(attendance_percentage) AS average_attendance_percentage + FROM ( + SELECT u."userId", u."name", + CASE + WHEN COUNT(*) = 0 THEN NULL + ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*),2) + END AS attendance_percentage + FROM public."CohortMembers" AS cm + INNER JOIN public."Users" AS u ON cm."userId" = u."userId" + LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" + WHERE cm."cohortId" = $1 AND cm."role" = 'student' + ${userFilter} + GROUP BY u."userId" + ) AS subquery; + ` + + const average=await this.attendanceRepository.query(countquery,[contextId]) + const report = await this.mapResponseforReport(result); + const response = { + report, + average:average[0] + } return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", - data: report, + data: response, }); + } + else + { + const response = await this.mapResponseforReport(result); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: response, + + }); + } + + } else if (report === false) { if (attendanceDate) { @@ -166,6 +180,8 @@ export class AttendanceService { const result = await this.attendanceRepository.query(query, [attendanceDate, contextId, limit, offset]); const report = await this.mapAttendanceRecord(result); + + return new SuccessResponse({ From 804ae4e167c4753280445cfe6a5ccbd2696795e8 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 29 Mar 2024 17:37:41 +0530 Subject: [PATCH 152/408] Added parent id in Get Cohort List --- src/auth/auth.service.ts | 8 +++++--- src/cohort/cohort.service.ts | 5 +++-- src/user/user.service.ts | 1 - 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 1e2b4a00..603feb94 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -34,14 +34,16 @@ export class AuthService { }; const res = await this.axiosInstance(axiosConfig); + // if(dataerror(); + // ) return response.status(200).send(res.data); } catch (error) { console.error(error); return response - .status(500) - .send({ message: "An error occurred during login." }); - } + .status(error.response ? error.response.status : 500) + .send({ message: error.message }); } +} public async getUserByAuth(request: any, response) { let apiId = "api.auth.getUserDetails"; diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 173c36d6..b1f2f33e 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -54,6 +54,7 @@ export class CohortService { let cohortData = { cohortId: data.cohortId, name:data.name, + parentId:data.parentId, customField:{} }; const getDetails = await this.getCohortListDetails(data.cohortId); @@ -85,10 +86,10 @@ export class CohortService { } public async findCohortName(userId: any) { - let query = `SELECT c."name",c."cohortId" + let query = `SELECT c."name",c."cohortId",c."parentId" FROM public."CohortMembers" AS cm LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" - WHERE cm."userId"=$1`; + WHERE cm."userId"=$1 AND c.status=true`; let result = await this.cohortMembersRepository.query(query, [userId]); return result; } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 4616b929..687e625e 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -176,7 +176,6 @@ export class UserService { try { const decoded: any = jwt_decode(request.headers.authorization); const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - console.log(userId); let cohortId = userCreateDto.cohortId; delete userCreateDto?.cohortId; userCreateDto.createdBy = userId From 8b1e3f893d15f4ab5b49d26a3f0cb387f7a9e084 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 29 Mar 2024 18:17:36 +0530 Subject: [PATCH 153/408] Fix[round off values of report, added validation for contextId] --- src/attendance/attendance.service.ts | 6 +++--- src/attendance/dto/attendance.dto.ts | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/attendance/attendance.service.ts b/src/attendance/attendance.service.ts index f68e2b5d..0626af92 100644 --- a/src/attendance/attendance.service.ts +++ b/src/attendance/attendance.service.ts @@ -93,7 +93,7 @@ export class AttendanceService { SELECT u."userId",u."name", CASE WHEN COUNT(*) = 0 THEN NULL - ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*),2) + ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*),0) END AS attendance_percentage FROM public."CohortMembers" AS cm INNER JOIN public."Users" AS u ON cm."userId" = u."userId" @@ -122,12 +122,12 @@ export class AttendanceService { if((!filters) || (!filters?.userId)) { // We dont need average for single user - let countquery = `SELECT AVG(attendance_percentage) AS average_attendance_percentage + let countquery = `SELECT ROUND(AVG(attendance_percentage)) AS average_attendance_percentage FROM ( SELECT u."userId", u."name", CASE WHEN COUNT(*) = 0 THEN NULL - ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*),2) + ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*)) END AS attendance_percentage FROM public."CohortMembers" AS cm INNER JOIN public."Users" AS u ON cm."userId" = u."userId" diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index c98fe01a..32a80d1b 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -133,8 +133,7 @@ export class AttendanceDto { description: "The contextId of the attendance", default: "", }) - - + @IsNotEmpty() @Expose() contextId: string; From 4124c527d99b4f222ca12c4a8b4b6170ab8bb4b4 Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 1 Apr 2024 10:35:33 +0530 Subject: [PATCH 154/408] Task #216298: Updated Update User Controller --- src/auth/auth.service.ts | 7 ++----- src/user/user.controller.ts | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 603feb94..ab57ffac 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -34,14 +34,11 @@ export class AuthService { }; const res = await this.axiosInstance(axiosConfig); - // if(dataerror(); - // ) return response.status(200).send(res.data); } catch (error) { - console.error(error); return response - .status(error.response ? error.response.status : 500) - .send({ message: error.message }); + .status(error.response ? error.response.status : 500) + .send({ message: error.message }); } } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index c7310607..22df7465 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -126,7 +126,6 @@ export class UserController { @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User has been updated successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) From 29e8949f8a29b1538849b80732f8d3c5fb6ccd0a Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 1 Apr 2024 13:12:12 +0530 Subject: [PATCH 155/408] Task #216181 : Added Role in User View Profile --- src/cohort/cohort.controller.ts | 26 ++++++++++++++++++++++++-- src/cohort/cohort.service.ts | 33 ++++++++++++++++++++++++++++++++- src/user/user.controller.ts | 5 +++-- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 1ccdf2ed..57d229c7 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -96,12 +96,34 @@ export class CohortController { }) public async getCohortList( @Headers() headers, - @Param("id") userId: string, + @Param("id") id: string, @Req() request: Request, @Res() response: Response ) { let tenantid = headers["tenantid"]; - return this.cohortService.getCohortList(tenantid, userId, request, response); + console.log(request); + return this.cohortService.getCohortList(tenantid, id, request, response); + } + + @Get("cohortDetails/:id") + @UseInterceptors(CacheInterceptor) + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Cohort details" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async getCohortDetails( + @Headers() headers, + @Param("id") cohortId: string, + @Req() request: Request, + @Res() response: Response + ) { + let tenantid = headers["tenantid"]; + return this.cohortService.getCohortsDetails(tenantid, cohortId, request, response); } // search diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 44e2831e..0525834e 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -36,6 +36,37 @@ export class CohortService { private fieldsService: FieldsService, ) { } + public async getCohortsDetails(tenantId: string, + cohortId: string, + request: any, + response: any){ + const apiId = "api.concept.cohortDetails"; + let cohortName = await this.cohortRepository.findOne({ + where:{cohortId} + }) + // let result = { + // cohortData: [], + // }; + let cohortData = { + cohortId: cohortId, + name:cohortName.name, + parentId:cohortName.parentId, + customField:{} + }; + const getDetails = await this.getCohortListDetails(cohortId); + cohortData.customField=getDetails + // result.cohortData.push(cohortData); + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + cohortData, + "OK" + ) + ); + } + public async getCohortList( tenantId: string, userId: string, @@ -82,8 +113,8 @@ export class CohortService { ) ); } - } + public async findCohortName(userId: any) { let query = `SELECT c."name",c."cohortId",c."parentId" FROM public."CohortMembers" AS cm diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 22df7465..1326cbd8 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -60,7 +60,7 @@ export class UserController { * * @since 1.6 */ - @Get("/:userid") + @Get("/:userid/:role") @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @@ -74,6 +74,7 @@ export class UserController { public async getUser( @Headers() headers, @Param("userid") userId: string, + @Param("role") role:string, @Req() request: Request, @Res() response: Response ) { @@ -82,7 +83,7 @@ export class UserController { let userData = { userId:userId, context:"USERS", - contextType:"TEACHER" + contextType:role } return this.userService.getUsersDetailsById(userData,response); } From e3515d2af407737f7b70abd7eaf2a13fa06fdcdd Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 1 Apr 2024 13:54:18 +0530 Subject: [PATCH 156/408] Converted Role to Upper Case due to DB --- src/user/user.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 687e625e..00e8943d 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -97,7 +97,7 @@ export class UserService { let customFields = await this.fieldsRepository.find({ where:{ context:userData.context, - contextType:userData.contextType + contextType:userData.contextType.toUpperCase() } }) return customFields; From 4fa8d5ae6bb78a5c773f07405a1bc5d8b84ab9ed Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:35:06 +0530 Subject: [PATCH 157/408] Create pratham-qa.yml --- .github/workflows/pratham-qa.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/pratham-qa.yml diff --git a/.github/workflows/pratham-qa.yml b/.github/workflows/pratham-qa.yml new file mode 100644 index 00000000..b15a6e98 --- /dev/null +++ b/.github/workflows/pratham-qa.yml @@ -0,0 +1,21 @@ +name: Deploy to QA +on: + push: + branches: + - main +jobs: + deploy: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - + name: Deploy Stack + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.HOST_NAME_PRATHAM_QA }} + username: ${{ secrets.USERNAME_PRATHAM_QA }} + key: ${{ secrets.EC2_SSH_KEY_PRATHAM_QA }} + port: ${{ secrets.PORT_PRATHAM_QA }} + script: | + cd ${{ secrets.TARGET_DIR_PRATHAM_QA }} + ./deploy.sh From 7bb6adbd228b2b38b54cba69ce5014271ef20acd Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:35:38 +0530 Subject: [PATCH 158/408] Update pratham-qa.yml --- .github/workflows/pratham-qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pratham-qa.yml b/.github/workflows/pratham-qa.yml index b15a6e98..b3fb1940 100644 --- a/.github/workflows/pratham-qa.yml +++ b/.github/workflows/pratham-qa.yml @@ -2,7 +2,7 @@ name: Deploy to QA on: push: branches: - - main + - Shiksha-2.0 jobs: deploy: runs-on: ubuntu-latest From ee25f070ef12e111855c1f278d6f3ea67958be22 Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 1 Apr 2024 19:18:43 +0530 Subject: [PATCH 159/408] Fixed Swagger Issue in Dev --- src/app.module.ts | 3 ++- src/main.ts | 35 +++++++++++---------------------- src/user/dto/user-create.dto.ts | 6 ++---- src/user/dto/user-search.dto.ts | 6 ++---- 4 files changed, 18 insertions(+), 32 deletions(-) diff --git a/src/app.module.ts b/src/app.module.ts index ce3bdf25..ae137d59 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -31,6 +31,7 @@ import { CohortMembersModule } from "./cohortMembers/cohortMembers.module"; import { FieldsModule } from "./fields/fields.module"; import { AuthModule } from "./auth/auth.module"; import { DatabaseModule } from "./common/database.module"; +import { SwaggerModule } from "@nestjs/swagger"; // Below modules no longer required in Shiksha 2.0 // import { GroupModule } from "./group/group.module"; // import { GroupMembershipModule } from "./groupMembership/groupMembership.module"; @@ -42,8 +43,8 @@ import { DatabaseModule } from "./common/database.module"; MulterModule.register({ dest: "./uploads", }), - UserModule, SchoolModule, + UserModule, RoleModule, AttendanceModule, HolidayModule, diff --git a/src/main.ts b/src/main.ts index a41bc669..994a3676 100644 --- a/src/main.ts +++ b/src/main.ts @@ -45,30 +45,19 @@ async function bootstrap() { exclude: [{ path: "health", method: RequestMethod.GET }], }); + const config = new DocumentBuilder() + .setTitle("Shiksha Platform") + .setDescription("CRUD API") + .setVersion("1.0") + .addTag("V1") + .addApiKey( + { type: "apiKey", name: "Authorization", in: "header" }, + "access-token" + ) - // const config = new DocumentBuilder() - // .setTitle("Shiksha Platform") - // .setDescription("CRUD API") - // .setVersion("1.0") - // .addTag("V1") - // .addApiKey( - // { type: "apiKey", name: "Authorization", in: "header" }, - // "access-token" - // ) - - // const config = new DocumentBuilder() - // .setTitle("Shiksha Platform") - // .setDescription("CRUD API") - // .setVersion("1.0") - // .addTag("V1") - // .addApiKey( - // { type: "apiKey", name: "Authorization", in: "header" }, - // "access-token" - // ) - - // .build(); - // const document = SwaggerModule.createDocument(app, config); - // SwaggerModule.setup("api/swagger-docs", app, document); + .build(); + const document = SwaggerModule.createDocument(app, config); + SwaggerModule.setup("api/swagger-docs", app, document); app.enableCors(); await app.listen(3000); } diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 992efe77..8589b24c 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -6,6 +6,7 @@ import { IsString, IsNumber, } from "class-validator"; +import { User } from "../entities/user-entity"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class UserCreateDto { @@ -15,10 +16,7 @@ export class UserCreateDto { @Expose() userId: string; - @ApiProperty({ - type: String, - description: "The username of the user", - }) + @ApiProperty({ type: () => User }) @Expose() username: string; diff --git a/src/user/dto/user-search.dto.ts b/src/user/dto/user-search.dto.ts index b9247ea2..7193420a 100644 --- a/src/user/dto/user-search.dto.ts +++ b/src/user/dto/user-search.dto.ts @@ -7,12 +7,10 @@ import { IsNumber, } from "class-validator"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { User } from "../entities/user-entity"; export class UserSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) + @ApiProperty({ type: () => User }) limit: string; @ApiProperty({ From d36f8afa23b624abe6a84c8d73aaee5d680f5b35 Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 2 Apr 2024 15:20:57 +0530 Subject: [PATCH 160/408] Added Cohort Details API with multiple cohortId and userId --- src/cohort/cohort.controller.ts | 46 ++++++++---------- src/cohort/cohort.service.ts | 76 +++++++++++++----------------- src/cohort/dto/query-params.dto.ts | 11 +++++ 3 files changed, 65 insertions(+), 68 deletions(-) create mode 100644 src/cohort/dto/query-params.dto.ts diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 57d229c7..5a8f90c5 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -26,6 +26,7 @@ import { Headers, Delete, UseGuards, + ValidationPipe } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -38,6 +39,7 @@ import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortService } from "./cohort.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { QueryParamsDto } from "./dto/query-params.dto"; // import { FieldsService } from "../fields/fields.service"; @ApiTags("Cohort") @Controller("cohort") @@ -83,29 +85,7 @@ export class CohortController { return this.cohortService.createCohort(request, cohortCreateDto); } - @Get("cohortList/:id") - @UseInterceptors(CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async getCohortList( - @Headers() headers, - @Param("id") id: string, - @Req() request: Request, - @Res() response: Response - ) { - let tenantid = headers["tenantid"]; - console.log(request); - return this.cohortService.getCohortList(tenantid, id, request, response); - } - - @Get("cohortDetails/:id") + @Get("cohortDetails") @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort details" }) @@ -118,14 +98,28 @@ export class CohortController { }) public async getCohortDetails( @Headers() headers, - @Param("id") cohortId: string, + @Query() queryParams: QueryParamsDto, @Req() request: Request, @Res() response: Response ) { - let tenantid = headers["tenantid"]; - return this.cohortService.getCohortsDetails(tenantid, cohortId, request, response); + queryParams.name = queryParams.name.toLocaleLowerCase(); + let data; + let tenantId = request.headers['tenantId'] + if (queryParams.name=== 'user') { + data=queryParams + return this.cohortService.getCohortsDetails(data,request,response) + } else if (queryParams.name === 'cohort') { + data=queryParams + return this.cohortService.getCohortsDetails(data,request,response) + } else { + return response.status(400).json({ + message:"Invaid Parameters" + }) + } } + + // search @Post("/search") @ApiBasicAuth("access-token") diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 0525834e..caff0cee 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -36,62 +36,27 @@ export class CohortService { private fieldsService: FieldsService, ) { } - public async getCohortsDetails(tenantId: string, - cohortId: string, + public async getCohortsDetails(userData, request: any, response: any){ - const apiId = "api.concept.cohortDetails"; - let cohortName = await this.cohortRepository.findOne({ - where:{cohortId} - }) - // let result = { - // cohortData: [], - // }; - let cohortData = { - cohortId: cohortId, - name:cohortName.name, - parentId:cohortName.parentId, - customField:{} - }; - const getDetails = await this.getCohortListDetails(cohortId); - cohortData.customField=getDetails - // result.cohortData.push(cohortData); - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - cohortData, - "OK" - ) - ); - } - - public async getCohortList( - tenantId: string, - userId: string, - request: any, - response: any - ) { - const apiId = "api.concept.editminiScreeningAnswer"; + let apiId = 'api.concept.getCohortDetails' try { - let findCohortId = await this.findCohortName(userId); + if(userData.name==='user'){ + let findCohortId = await this.findCohortName(userData?.id); let result = { cohortData: [], }; - for (let data of findCohortId) { let cohortData = { - cohortId: data.cohortId, + cohortId: data?.cohortId, name:data.name, - parentId:data.parentId, + parentId:data?.parentId, customField:{} }; - const getDetails = await this.getCohortListDetails(data.cohortId); + const getDetails = await this.getCohortListDetails(data?.cohortId); cohortData.customField=getDetails result.cohortData.push(cohortData); } - return response .status(HttpStatus.OK) .send( @@ -101,6 +66,30 @@ export class CohortService { "OK" ) ); + }else{ + let cohortName = await this.cohortRepository.findOne({ + where:{cohortId:userData?.id}, + select:['name','parentId'] + }) + let cohortData = { + cohortId: userData?.id, + name:cohortName.name, + parentId:cohortName.parentId, + customField:{} + }; + const getDetails = await this.getCohortListDetails(userData?.id); + cohortData.customField=getDetails + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + cohortData, + "OK" + ) + ); + + } } catch (error) { return response .status(HttpStatus.INTERNAL_SERVER_ERROR) @@ -121,6 +110,9 @@ export class CohortService { LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" WHERE cm."userId"=$1 AND c.status=true`; let result = await this.cohortMembersRepository.query(query, [userId]); + // if(!result.length){ + // return null; + // } return result; } diff --git a/src/cohort/dto/query-params.dto.ts b/src/cohort/dto/query-params.dto.ts new file mode 100644 index 00000000..c245a5cd --- /dev/null +++ b/src/cohort/dto/query-params.dto.ts @@ -0,0 +1,11 @@ +import { IsNotEmpty, IsString, IsInt } from 'class-validator'; + +export class QueryParamsDto { + @IsNotEmpty() + @IsString() + name: string; + + @IsNotEmpty() + @IsString() + id: string; +} From bbb32cd1effc0473a4921a8b83e80454e73f0e18 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Tue, 2 Apr 2024 17:53:28 +0530 Subject: [PATCH 161/408] Task #216715 feat : logout and refresh token apis --- src/app.controller.ts | 2 + src/auth/auth.controller.ts | 43 ++++--- src/auth/auth.service.ts | 80 ++++++++----- src/auth/dto/auth-dto.ts | 26 ++++- src/common/utils/keycloak.service.ts | 162 +++++++++++++++++---------- 5 files changed, 206 insertions(+), 107 deletions(-) diff --git a/src/app.controller.ts b/src/app.controller.ts index b92a83d0..dd325187 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,6 +1,7 @@ import { Controller, Get, Param, Res, UseGuards } from "@nestjs/common"; import { AppService } from "./app.service"; import { JwtAuthGuard } from "./common/guards/keycloak.guard"; +import { ApiBasicAuth } from "@nestjs/swagger"; @Controller() export class AppController { @@ -8,6 +9,7 @@ export class AppController { @Get() @UseGuards(JwtAuthGuard) + @ApiBasicAuth("access-token") getHello(): object { return this.appService.getHello(); } diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 5504fcff..300ea502 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -11,18 +11,20 @@ import { Get, Post, Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, SerializeOptions, Req, Res, Request, Response, Headers, + HttpStatus, + HttpCode, } from "@nestjs/common"; -import { AuthDto } from "./dto/auth-dto"; +import { + AuthDto, + RefreshTokenRequestBody, + LogoutRequestBody, +} from "./dto/auth-dto"; import { AuthService } from "./auth.service"; @ApiTags("Auth") @@ -32,17 +34,10 @@ export class AuthController { @Post("/login") @ApiBody({ type: AuthDto }) + @HttpCode(HttpStatus.OK) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async login( - @Req() request: Request, - @Res() response: Response, - @Body() authDto: AuthDto - ) { - return this.authService.login(authDto, response); + public async login(@Body() authDto: AuthDto) { + return this.authService.login(authDto); } @Get("/getUserDetails") @@ -62,4 +57,22 @@ export class AuthController { // const tenantId = headers["tenantid"]; return this.authService.getUserByAuth(request, response); } + + @Post("/refresh") + @HttpCode(HttpStatus.OK) + @ApiBody({ type: RefreshTokenRequestBody }) + refreshToken(@Body() body: RefreshTokenRequestBody) { + const { refresh_token: refreshToken } = body; + + return this.authService.refreshToken(refreshToken); + } + + @Post("/logout") + @HttpCode(HttpStatus.OK) + @ApiBody({ type: LogoutRequestBody }) + async logout(@Body() body: LogoutRequestBody) { + const { refresh_token: refreshToken } = body; + + await this.authService.logout(refreshToken); + } } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index ab57ffac..7b1a411d 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,46 +1,46 @@ -import { HttpStatus, Injectable } from "@nestjs/common"; +import { HttpStatus, Injectable, UnauthorizedException } from "@nestjs/common"; import { UserService } from "../user/user.service"; import axios from "axios"; -import qs from "qs"; import jwt_decode from "jwt-decode"; import APIResponse from "src/utils/response"; +import { KeycloakService } from "src/common/utils/keycloak.service"; +type LoginResponse = { + access_token: string; + refresh_token: string; + expires_in: number; + refresh_expires_in: number; +}; @Injectable() export class AuthService { private axiosInstance; - constructor(private readonly userService: UserService) { + constructor( + private readonly userService: UserService, + private readonly keycloakService: KeycloakService + ) { this.axiosInstance = axios.create(); } - async login(authDto, response) { - try { - const { KEYCLOAK, KEYCLOAK_USER_TOKEN, KEYCLOAK_HASURA_CLIENT_SECRET } = - process.env; - const data = qs.stringify({ - username: authDto.username, - password: authDto.password, - grant_type: "password", - client_id: "hasura", - client_secret: KEYCLOAK_HASURA_CLIENT_SECRET, - }); - - const axiosConfig = { - method: "post", - url: `${KEYCLOAK}${KEYCLOAK_USER_TOKEN}`, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - data: data, - }; + async login(authDto) { + const { username, password } = authDto; + const { + access_token, + expires_in, + refresh_token, + refresh_expires_in, + token_type, + } = await this.keycloakService.login(username, password).catch(() => { + throw new UnauthorizedException(); + }); - const res = await this.axiosInstance(axiosConfig); - return response.status(200).send(res.data); - } catch (error) { - return response - .status(error.response ? error.response.status : 500) - .send({ message: error.message }); + return { + access_token, + refresh_token, + expires_in, + refresh_expires_in, + token_type, + }; } -} public async getUserByAuth(request: any, response) { let apiId = "api.auth.getUserDetails"; @@ -64,4 +64,24 @@ export class AuthService { ); } } + + async refreshToken(refreshToken: string): Promise { + const { access_token, expires_in, refresh_token, refresh_expires_in } = + await this.keycloakService.refreshToken(refreshToken).catch(() => { + throw new UnauthorizedException(); + }); + + return { + access_token, + refresh_token, + expires_in, + refresh_expires_in, + }; + } + + async logout(refreshToken: string) { + await this.keycloakService.logout(refreshToken).catch(() => { + throw new UnauthorizedException(); + }); + } } diff --git a/src/auth/dto/auth-dto.ts b/src/auth/dto/auth-dto.ts index 18b07837..6b38c666 100644 --- a/src/auth/dto/auth-dto.ts +++ b/src/auth/dto/auth-dto.ts @@ -1,5 +1,5 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import {IsString,IsNotEmpty} from 'class-validator' +import { IsString, IsNotEmpty } from "class-validator"; export class AuthDto { @ApiProperty({ @@ -22,3 +22,27 @@ export class AuthDto { Object.assign(this, partial); } } + +export class RefreshTokenRequestBody { + @ApiProperty({ + type: String, + description: "token", + }) + refresh_token: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } +} + +export class LogoutRequestBody { + @ApiProperty({ + type: String, + description: "token", + }) + refresh_token: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } +} diff --git a/src/common/utils/keycloak.service.ts b/src/common/utils/keycloak.service.ts index 0911897f..5be96714 100644 --- a/src/common/utils/keycloak.service.ts +++ b/src/common/utils/keycloak.service.ts @@ -1,7 +1,8 @@ -import { HttpService } from '@nestjs/axios'; -import { Injectable } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { firstValueFrom } from 'rxjs'; +import { HttpService } from "@nestjs/axios"; +import { Injectable } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import axios from "axios"; +import qs from "qs"; type LoginResponse = { access_token: string; @@ -9,7 +10,6 @@ type LoginResponse = { refresh_token: string; token_type: string; session_state: string; - 'not-before-policy': number; refresh_expires_in: number; expires_in: number; }; @@ -26,75 +26,115 @@ export class KeycloakService { private realm: string; private clientId: string; private clientSecret: string; - + private axios; + userToken: any; constructor( private readonly configService: ConfigService, - private readonly httpService: HttpService, ) { - this.baseURL = this.configService.get('KEYCLOAK_BASE_URL'); - this.realm = this.configService.get('KEYCLOAK_REALM'); - this.clientId = this.configService.get('KEYCLOAK_CLIENT_ID'); - this.clientSecret = this.configService.get('KEYCLOAK_CLIENT_SECRET'); + this.baseURL = this.configService.get("KEYCLOAK"); + this.userToken = this.configService.get("KEYCLOAK_USER_TOKEN"); + this.realm = this.configService.get("KEYCLOAK_REALM"); + this.clientId = this.configService.get("KEYCLOAK_CLIENT_ID"); + this.clientSecret = this.configService.get("KEYCLOAK_CLIENT_SECRET"); + this.axios = axios.create(); } async login(username: string, password: string): Promise { - const { data } = await firstValueFrom( - this.httpService.post( - `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/token`, - new URLSearchParams({ - client_id: this.clientId, - client_secret: this.clientSecret, - grant_type: 'password', - username, - password, - }), - ), - ); - - return data; + const data = qs.stringify({ + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: "password", + username, + password, + }); + + const axiosConfig = { + method: "post", + url: `${this.baseURL}realms/${this.realm}/protocol/openid-connect/token`, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + data: data, + }; + + const res = await this.axios(axiosConfig); + + return res.data; } async getUserInfo(accessToken: string): Promise { - const { data } = await firstValueFrom( - this.httpService.get( - `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/userinfo`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - }, - }, - ), - ); - - return data; + // const { data } = await firstValueFrom( + // this.httpService.get( + // `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/userinfo`, + // { + // headers: { + // Authorization: `Bearer ${accessToken}`, + // }, + // } + // ) + // ); + + // const data = qs.stringify({ + // client_id: this.clientId, + // client_secret: this.clientSecret, + // grant_type: "refresh_token", + // refresh_token: refreshToken, + // }); + + const axiosConfig = { + method: "post", + url: `${this.baseURL}realms/${this.realm}/protocol/openid-connect/userinfo`, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Authorization: `Bearer ${accessToken}`, + }, + }; + + const res = await this.axios(axiosConfig); + + return res.data; } async refreshToken(refreshToken: string): Promise { - const { data } = await firstValueFrom( - this.httpService.post( - `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/token`, - new URLSearchParams({ - client_id: this.clientId, - client_secret: this.clientSecret, - grant_type: 'refresh_token', - refresh_token: refreshToken, - }), - ), - ); - - return data; + const data = qs.stringify({ + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: "refresh_token", + refresh_token: refreshToken, + }); + + const axiosConfig = { + method: "post", + url: `${this.baseURL}realms/${this.realm}/protocol/openid-connect/token`, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + data: data, + }; + + const res = await this.axios(axiosConfig); + + return res.data; } async logout(refreshToken: string) { - await firstValueFrom( - this.httpService.post( - `${this.baseURL}/auth/realms/${this.realm}/protocol/openid-connect/logout`, - new URLSearchParams({ - client_id: this.clientId, - client_secret: this.clientSecret, - refresh_token: refreshToken, - }), - ), - ); + const data = qs.stringify({ + client_id: this.clientId, + client_secret: this.clientSecret, + refresh_token: refreshToken, + }); + + const axiosConfig = { + method: "post", + url: `${this.baseURL}realms/${this.realm}/protocol/openid-connect/logout`, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + data: data, + }; + + const res = await this.axios(axiosConfig); + + return res.data; } -} \ No newline at end of file +} From 2cd6c21c6d612e522934c7d5db1bdd27fbf4cd5e Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 3 Apr 2024 01:49:09 +0530 Subject: [PATCH 162/408] Fix[timexone issue solved for mark attendance and validation on date for attendance by date API] --- src/attendance/dto/attendance-date.dto.ts | 23 +++++++++++++++++--- src/attendance/dto/attendance.dto.ts | 8 +++---- src/attendance/entities/attendance.entity.ts | 7 +++--- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/attendance/dto/attendance-date.dto.ts b/src/attendance/dto/attendance-date.dto.ts index 3b00e50d..6b085991 100644 --- a/src/attendance/dto/attendance-date.dto.ts +++ b/src/attendance/dto/attendance-date.dto.ts @@ -1,5 +1,21 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsNotEmpty, Matches } from "class-validator"; +import { IsDate, IsNotEmpty, Matches, Validate, ValidateIf, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator"; +import { isAfter, isBefore, isSameDay } from "date-fns"; + + +@ValidatorConstraint({ name: 'isNotAfterFromDate', async: false }) +export class IsFromDateBeforeToDateConstraint implements ValidatorConstraintInterface { + validate(fromDate: Date, args: ValidationArguments) { + const toDate = args.object[args.constraints[0]]; + const res = isSameDay(fromDate, toDate) || isBefore(fromDate, toDate); + return res + } + + defaultMessage(args: ValidationArguments) { + return 'From Date must be before or equal to To Date'; + } +} + export class AttendanceDateDto { @ApiProperty({ @@ -8,7 +24,8 @@ export class AttendanceDateDto { }) @IsNotEmpty() @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) - fromDate: string; + @Validate(IsFromDateBeforeToDateConstraint, ['toDate']) + fromDate: Date; @ApiProperty({ type: Date, @@ -16,7 +33,7 @@ export class AttendanceDateDto { }) @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @IsNotEmpty() - toDate: string; + toDate: Date; @ApiProperty({ type: String, diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 32a80d1b..abdc7911 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -4,7 +4,7 @@ import { Exclude, Expose, Transform, Type } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsObject } from 'class-validator'; import { User } from 'src/user/entities/user-entity'; -import { format, isAfter, isBefore, isValid } from 'date-fns'; // Import isAfter function from date-fns +import { addHours, format, isAfter, isBefore, isValid } from 'date-fns'; // Import isAfter function from date-fns import { HttpException, HttpStatus } from '@nestjs/common'; //for student valid enum are[present,absent] @@ -19,8 +19,8 @@ enum Attendance{ @ValidatorConstraint({ name: 'isNotAfterToday', async: false }) export class IsNotAfterToday implements ValidatorConstraintInterface { validate(date: Date, args: ValidationArguments) { - return isBefore(date, new Date()); - } + const currentDateIST = addHours(new Date(), 5.5); + return isBefore(date, currentDateIST); } defaultMessage(args: ValidationArguments) { return 'Attendance date must not be after today'; @@ -33,7 +33,7 @@ export class AttendanceDto { @Expose() tenantId: string; - @ApiProperty({ + @ApiProperty({ type: String, description: "The userid of the attendance", default: "", diff --git a/src/attendance/entities/attendance.entity.ts b/src/attendance/entities/attendance.entity.ts index 92f65564..38e21164 100644 --- a/src/attendance/entities/attendance.entity.ts +++ b/src/attendance/entities/attendance.entity.ts @@ -1,6 +1,6 @@ import { Cohort } from 'src/cohort/entities/cohort.entity'; import { User } from 'src/user/entities/user-entity'; -import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, JoinColumn } from 'typeorm'; +import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'; @Entity({name:"Attendance"}) export class AttendanceEntity { @@ -50,10 +50,11 @@ export class AttendanceEntity { @Column({ nullable: true }) contextId: string; - @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) + // @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) + @CreateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) createdAt: Date; - @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP' }) + @UpdateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) updatedAt: Date; @Column() From 423a2849b628d3f2d1c85d656096dd41e5d9eb4e Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 3 Apr 2024 11:10:01 +0530 Subject: [PATCH 163/408] Removed Swagger From the APIS --- src/Question/question.controller.ts | 130 +++++++++--------- src/adminForm/adminForm.controller.ts | 44 +++--- src/announcements/announcements.controller.ts | 47 +++---- src/assessmentset/assessmentset.controller.ts | 28 ++-- src/auth/auth.controller.ts | 3 + src/comment/comment.controller.ts | 38 ++--- src/configs/config.controller.ts | 22 +-- src/course/course.controller.ts | 36 ++--- .../courseTracking.controller.ts | 94 ++++++------- src/group/group.controller.ts | 56 ++++---- .../groupMembership.controller.ts | 42 +++--- src/holiday/holiday.controller.ts | 41 +++--- .../inAppNotification.controller.ts | 80 +++++------ src/lessonPlan/lessonPlan.controller.ts | 38 ++--- src/like/like.controller.ts | 52 +++---- .../mentorTracking.controller.ts | 62 +++++---- .../monitorTracking.controller.ts | 52 +++---- .../instantNotification.controller.ts | 40 +++--- .../scheduleNotification.controller.ts | 4 +- src/role/role.controller.ts | 46 ++++--- src/school/school.controller.ts | 30 ++-- src/student/student.controller.ts | 32 +++-- src/template/template.controller.ts | 36 ++--- .../trackassessment.controller.ts | 46 ++++--- src/workHistory/workHistory.controller.ts | 52 +++---- src/worksheet/worksheet.controller.ts | 66 ++++----- 26 files changed, 637 insertions(+), 580 deletions(-) diff --git a/src/Question/question.controller.ts b/src/Question/question.controller.ts index 0dfa1f04..013e389e 100644 --- a/src/Question/question.controller.ts +++ b/src/Question/question.controller.ts @@ -2,6 +2,7 @@ import { ApiBasicAuth, ApiBody, ApiCreatedResponse, + ApiExcludeController, ApiForbiddenResponse, ApiOkResponse, ApiQuery, @@ -31,7 +32,8 @@ import { IServicelocator } from "src/adapters/questionservicelocator"; import { QuestionDto } from "./dto/question.dto"; import { HasuraQuestionToken } from "src/adapters/hasura/question.adapter"; -@ApiTags("Question") +// @ApiTags("Question") +@ApiExcludeController() @Controller("question") export class QuestionController { constructor( @@ -44,16 +46,16 @@ export class QuestionController { @Get(":adapter/search") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) //@ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Get all Questions detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "questionType", required: false }) - @ApiQuery({ name: "subject", required: false }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "language", required: false }) - @ApiQuery({ name: "medium", required: false }) - @ApiQuery({ name: "bloomsLevel", required: false }) - @ApiQuery({ name: "topic", required: false }) - @ApiQuery({ name: "className", required: false }) + // @ApiOkResponse({ description: "Get all Questions detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "questionType", required: false }) + // @ApiQuery({ name: "subject", required: false }) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "language", required: false }) + // @ApiQuery({ name: "medium", required: false }) + // @ApiQuery({ name: "bloomsLevel", required: false }) + // @ApiQuery({ name: "topic", required: false }) + // @ApiQuery({ name: "className", required: false }) public async getAllQuestions( @Param("adapter") adapter: string, @Query("questionType") questionType: string, @@ -84,9 +86,9 @@ export class QuestionController { @Get(":adapter/questionIds") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) //@ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Get all Questions detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "questionIds", required: false }) + // @ApiOkResponse({ description: "Get all Questions detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "questionIds", required: false }) public async getAllQuestionsByQuestionIds( @Param("adapter") adapter: string, @Query("questionIds") questionIds: [string], @@ -102,9 +104,9 @@ export class QuestionController { @Get(":adapter/subjectlist") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiOkResponse({ description: "Get all subject list" }) - @ApiQuery({ name: "gradeLevel", required: true }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiOkResponse({ description: "Get all subject list" }) + // @ApiQuery({ name: "gradeLevel", required: true }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async getSubjectList( @Param("adapter") adapter: string, @Query("gradeLevel") gradeLevel: string @@ -116,9 +118,9 @@ export class QuestionController { @Get(":adapter/topicslist") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiOkResponse({ description: "Get all subject list" }) - @ApiQuery({ name: "subject", required: true }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiOkResponse({ description: "Get all subject list" }) + // @ApiQuery({ name: "subject", required: true }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async getTopicsList( @Param("adapter") adapter: string, @Query("subject") subject: string @@ -131,9 +133,9 @@ export class QuestionController { @Get(":adapter/questionid") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) // @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Get Questions detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "questionId", required: false }) + // @ApiOkResponse({ description: "Get Questions detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "questionId", required: false }) public async getOneQuestion( @Param("adapter") adapter: string, @Query("questionId") questionId: string, @@ -147,10 +149,10 @@ export class QuestionController { @Get(":adapter/competencieslist") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) //@ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Get all competencies list." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "subject", required: false }) - @ApiQuery({ name: "limit", required: false }) + // @ApiOkResponse({ description: "Get all competencies list." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "subject", required: false }) + // @ApiQuery({ name: "limit", required: false }) public async getcompetenciesList( @Param("adapter") adapter: string, @Query("subject") subject: string, @@ -164,12 +166,12 @@ export class QuestionController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Question detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiQuery({ name: "adapter" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Question detail." }) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiQuery({ name: "adapter" }) getQuestion( @Param("id") questionId: string, @Query("adapter") adapter: string, @@ -183,14 +185,14 @@ export class QuestionController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Question has been created successfully.", - }) - @ApiBody({ type: QuestionDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiQuery({ name: "adapter" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Question has been created successfully.", + // }) + // @ApiBody({ type: QuestionDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @ApiQuery({ name: "adapter" }) public async createQuestion( @Req() request: Request, @Query("adapter") adapter: string, @@ -204,13 +206,13 @@ export class QuestionController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Question has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Question has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) - @ApiQuery({ name: "adapter" }) + // @ApiQuery({ name: "adapter" }) public async updateQuestion( @Param("id") questionId: string, @Req() request: Request, @@ -234,18 +236,18 @@ export class QuestionController { @Post("filter/:adapter") @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "body", required: false }) - @ApiQuery({ name: "className", required: false }) - @ApiQuery({ name: "maxScore", required: false }) - @ApiQuery({ name: "questionId", required: false }) - @ApiQuery({ name: "subject", required: false }) - @ApiQuery({ name: "topic", required: false }) - @ApiQuery({ name: "type", required: false }) - @ApiQuery({ name: "page", required: false }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " Ok." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "body", required: false }) + // @ApiQuery({ name: "className", required: false }) + // @ApiQuery({ name: "maxScore", required: false }) + // @ApiQuery({ name: "questionId", required: false }) + // @ApiQuery({ name: "subject", required: false }) + // @ApiQuery({ name: "topic", required: false }) + // @ApiQuery({ name: "type", required: false }) + // @ApiQuery({ name: "page", required: false }) public async filterQuestion( @Param("adapter") adapter: string, @Query("limit") limit: string, @@ -289,11 +291,11 @@ export class QuestionController { } @Post(":adapter/bulkImport") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Bulk Question has been created successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Bulk Question has been created successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async bulkImport( @Param("adapter") adapter: string, diff --git a/src/adminForm/adminForm.controller.ts b/src/adminForm/adminForm.controller.ts index 9cbc19b8..f5b2daf7 100644 --- a/src/adminForm/adminForm.controller.ts +++ b/src/adminForm/adminForm.controller.ts @@ -13,6 +13,7 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, + ApiExcludeController } from "@nestjs/swagger"; import { Controller, @@ -29,7 +30,8 @@ import { } from "@nestjs/common"; import { AdminFormDto } from "./dto/adminForm.dto"; import { AdminFormSearchDto } from "./dto/adminForm-search.dto"; -@ApiTags("AdminForm") +// @ApiTags("AdminForm") +@ApiExcludeController() @Controller("adminForm") export class AdminFormController { constructor( @@ -39,9 +41,9 @@ export class AdminFormController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "AdminForm detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "AdminForm detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -50,12 +52,12 @@ export class AdminFormController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "AdminForm has been created successfully.", - }) - @ApiBody({ type: AdminFormDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "AdminForm has been created successfully.", + // }) + // @ApiBody({ type: AdminFormDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createAdminForm( @Req() request: Request, @@ -65,11 +67,11 @@ export class AdminFormController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "AdminForm has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "AdminForm has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateAdminForm( @Param("id") id: string, @@ -80,10 +82,10 @@ export class AdminFormController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "AdminForm list." }) - @ApiBody({ type: AdminFormSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "AdminForm list." }) + // @ApiBody({ type: AdminFormSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", @@ -95,3 +97,7 @@ export class AdminFormController { return await this.service.searchAdminForm(request, adminFormSearchDto); } } +function ApiExclude(): (target: typeof AdminFormController) => void | typeof AdminFormController { + throw new Error("Function not implemented."); +} + diff --git a/src/announcements/announcements.controller.ts b/src/announcements/announcements.controller.ts index 05b3f4ad..caded547 100644 --- a/src/announcements/announcements.controller.ts +++ b/src/announcements/announcements.controller.ts @@ -21,6 +21,7 @@ import { ApiBody, ApiConsumes, ApiCreatedResponse, + ApiExcludeController, ApiForbiddenResponse, ApiOkResponse, } from "@nestjs/swagger"; @@ -31,7 +32,7 @@ import { } from "src/adapters/hasura/announcements.adapter"; import { AnnouncementsFilterDto } from "./dto/announcements-filter.dto"; import { AnnouncementsDto } from "./dto/announcements.dto"; - +@ApiExcludeController() @Controller("announcements") export class AnnouncementsController { constructor( @@ -41,9 +42,9 @@ export class AnnouncementsController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Get announcement detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Get announcement detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async getAnnouncement( @Param("id") announcementId: string, @Req() request: Request @@ -53,9 +54,9 @@ export class AnnouncementsController { @Get("") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Get announcements" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Get announcements" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async getAnnouncementSet( @Query() query: AnnouncementsFilterDto, @Req() request: Request @@ -64,13 +65,13 @@ export class AnnouncementsController { } @Put("/:id") - @ApiConsumes("multipart/form-data") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Announcement has been Updated successfully.", - }) - @ApiBody({ type: AnnouncementsDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiConsumes("multipart/form-data") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Announcement has been Updated successfully.", + // }) + // @ApiBody({ type: AnnouncementsDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateAnnouncement( @Param("id") announcementId: string, @@ -86,13 +87,13 @@ export class AnnouncementsController { } @Post() - @ApiConsumes("multipart/form-data") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Announcement has been created successfully.", - }) - @ApiBody({ type: AnnouncementsDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiConsumes("multipart/form-data") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Announcement has been created successfully.", + // }) + // @ApiBody({ type: AnnouncementsDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async createAnnouncement( @Req() request: Request, @Body() announcementData: AnnouncementsDto @@ -102,8 +103,8 @@ export class AnnouncementsController { @Delete("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Deleted the announcement " }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Deleted the announcement " }) public async deleteAnnouncement( @Param("id") announcementId: string, @Req() request: Request diff --git a/src/assessmentset/assessmentset.controller.ts b/src/assessmentset/assessmentset.controller.ts index c6d91a9d..c7c6f3ff 100644 --- a/src/assessmentset/assessmentset.controller.ts +++ b/src/assessmentset/assessmentset.controller.ts @@ -5,6 +5,7 @@ import { ApiBasicAuth, ApiBody, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -24,18 +25,19 @@ import { AssessmentSetSearchDto } from "./dto/assessmentset-search-dto"; import { AssessmentsetDto } from "./dto/assessmentset.dto"; import { AssessmentsetService } from "src/adapters/hasura/assessmentset.adapter"; -@ApiTags("Assessmentset") +// @ApiTags("Assessmentset") +@ApiExcludeController() @Controller("assessmentset") export class AssessmentsetController { constructor(private service: AssessmentsetService) {} @Post("/assessmentset") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Assessment set has been created successfully.", - }) - @ApiBody({ type: AssessmentsetDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Assessment set has been created successfully.", + // }) + // @ApiBody({ type: AssessmentsetDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createAssessmentSet( @Req() request: Request, @@ -45,9 +47,9 @@ export class AssessmentsetController { } @Get("assessmentset/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Assessment set detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Assessment set detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -59,9 +61,9 @@ export class AssessmentsetController { } @Post("assessmentset/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Assessment set list." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Assessment set list." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 5504fcff..7488e061 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -21,6 +21,8 @@ import { Request, Response, Headers, + ValidationPipe, + UsePipes } from "@nestjs/common"; import { AuthDto } from "./dto/auth-dto"; import { AuthService } from "./auth.service"; @@ -33,6 +35,7 @@ export class AuthController { @Post("/login") @ApiBody({ type: AuthDto }) @ApiForbiddenResponse({ description: "Forbidden" }) + @UsePipes(ValidationPipe) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/comment/comment.controller.ts b/src/comment/comment.controller.ts index e197a797..773011b5 100644 --- a/src/comment/comment.controller.ts +++ b/src/comment/comment.controller.ts @@ -18,21 +18,23 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, + ApiExcludeController, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { CommentDto } from "./dto/comment.dto"; import { CommentSearchDto } from "./dto/comment-search.dto"; import { IServicelocator } from "src/adapters/commentservicelocator"; import { CommentAdapter } from "./commentadapter"; -@ApiTags("Comment") +// @ApiTags("Comment") +@ApiExcludeController() @Controller("comment") export class CommentController implements IServicelocator { constructor(private commentAdapter: CommentAdapter) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Comment detail." }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Comment detail." }) @SerializeOptions({ strategy: "excludeAll", }) @@ -43,12 +45,12 @@ export class CommentController implements IServicelocator { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Comment has been created successfully.", - }) - @ApiBody({ type: CommentDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Comment has been created successfully.", + // }) + // @ApiBody({ type: CommentDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createComment( @Req() request: Request, @@ -60,11 +62,11 @@ export class CommentController implements IServicelocator { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Comment has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Comment has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateComment( @Param("id") commentId: string, @@ -77,10 +79,10 @@ export class CommentController implements IServicelocator { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Comment list." }) - @ApiBody({ type: CommentSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Comment list." }) + // @ApiBody({ type: CommentSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/configs/config.controller.ts b/src/configs/config.controller.ts index deca0ff6..e67f244a 100644 --- a/src/configs/config.controller.ts +++ b/src/configs/config.controller.ts @@ -4,6 +4,7 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -19,7 +20,8 @@ import { Request } from "@nestjs/common"; import { ConfigDto } from "./dto/config.dto"; import { ConfigsAdapter } from "./configsadapter"; -@ApiTags("Config") +// @ApiTags("Config") +@ApiExcludeController() @Controller("config") export class ConfigController { constructor(private configsAdapter: ConfigsAdapter) {} @@ -27,8 +29,8 @@ export class ConfigController { @Get(":module/all") @ApiBasicAuth("access-token") @UseInterceptors(ClassSerializerInterceptor) - @ApiCreatedResponse({ description: "Config detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiCreatedResponse({ description: "Config detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -37,10 +39,10 @@ export class ConfigController { } @Post("") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Config has been created successfully." }) - @ApiBody({ type: ConfigDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Config has been created successfully." }) + // @ApiBody({ type: ConfigDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createConfig( @Req() request: Request, @@ -52,9 +54,9 @@ export class ConfigController { } @Post(":multipleConfigs") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Config has been created successfully." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Config has been created successfully." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createModuleConfigs( @Req() request: Request, diff --git a/src/course/course.controller.ts b/src/course/course.controller.ts index 3e24859f..df28e9f6 100644 --- a/src/course/course.controller.ts +++ b/src/course/course.controller.ts @@ -1,4 +1,5 @@ import { + ApiExcludeController, ApiForbiddenResponse, ApiOkResponse, ApiQuery, @@ -20,7 +21,8 @@ import { import { DikshaCourseToken } from "src/adapters/diksha/dikshaCourse.adapter"; import { IServicelocator } from "src/adapters/courseservicelocator"; -@ApiTags("Course") +// @ApiTags("Course") +@ApiExcludeController() @Controller("course") export class CourseController { constructor( @@ -29,13 +31,13 @@ export class CourseController { @Get(":adapter/search") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiOkResponse({ description: "Get all Course detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "subject", required: false }) - @ApiQuery({ name: "audience", required: false }) - @ApiQuery({ name: "className", required: false }) - @ApiQuery({ name: "medium", required: false }) - @ApiQuery({ name: "limit", required: false }) + // @ApiOkResponse({ description: "Get all Course detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "subject", required: false }) + // @ApiQuery({ name: "audience", required: false }) + // @ApiQuery({ name: "className", required: false }) + // @ApiQuery({ name: "medium", required: false }) + // @ApiQuery({ name: "limit", required: false }) public async getAllCourse( @Param("adapter") adapter: string, @Query("subject") subject: [string], @@ -59,9 +61,9 @@ export class CourseController { @Get(":adapter/courseIds") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiOkResponse({ description: "Get all Course detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "courseIds", required: false }) + // @ApiOkResponse({ description: "Get all Course detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "courseIds", required: false }) public async getCoursesByIds( @Param("adapter") adapter: string, @Query("courseIds") courseIds: [string], @@ -73,9 +75,9 @@ export class CourseController { } @Get(":adapter/hierarchy/courseid") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiOkResponse({ description: "Get Course detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "courseId", required: false }) + // @ApiOkResponse({ description: "Get Course detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "courseId", required: false }) public async getCourseHierarchy( @Param("adapter") adapter: string, @Query("courseId") courseId: string, @@ -88,9 +90,9 @@ export class CourseController { @Get(":adapter/content/courseid") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiOkResponse({ description: "Get Course detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "courseId", required: false }) + // @ApiOkResponse({ description: "Get Course detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "courseId", required: false }) public async getCourseDetail( @Param("adapter") adapter: string, @Query("courseId") courseId: string, diff --git a/src/courseTracking/courseTracking.controller.ts b/src/courseTracking/courseTracking.controller.ts index 0cc586bd..893849d2 100644 --- a/src/courseTracking/courseTracking.controller.ts +++ b/src/courseTracking/courseTracking.controller.ts @@ -6,6 +6,7 @@ import { ApiBody, ApiQuery, ApiOkResponse, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -25,27 +26,28 @@ import { import { CourseTrackingService } from "src/adapters/hasura/courseTracking.adapter"; import { CourseTrackingDto } from "./dto/courseTracking.dto"; -@ApiTags("Course Tracking") +// @ApiTags("Course Tracking") +@ApiExcludeController() @Controller("coursetracking") export class CourseTrackingController { constructor(private service: CourseTrackingService) {} @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Course Tracking has been created successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiQuery({ name: "progressDetail", required: false }) - @ApiQuery({ name: "courseId", required: false }) - @ApiQuery({ name: "userId", required: false }) - @ApiQuery({ name: "contentIds", required: false }) - @ApiQuery({ name: "startTime", required: false }) - @ApiQuery({ name: "endTime", required: false }) - @ApiQuery({ name: "certificate", required: false }) - @ApiQuery({ name: "status", required: false }) - @ApiQuery({ name: "source", required: false }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Course Tracking has been created successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @ApiQuery({ name: "progressDetail", required: false }) + // @ApiQuery({ name: "courseId", required: false }) + // @ApiQuery({ name: "userId", required: false }) + // @ApiQuery({ name: "contentIds", required: false }) + // @ApiQuery({ name: "startTime", required: false }) + // @ApiQuery({ name: "endTime", required: false }) + // @ApiQuery({ name: "certificate", required: false }) + // @ApiQuery({ name: "status", required: false }) + // @ApiQuery({ name: "source", required: false }) public async createCourse( @Req() request: Request, @Query("progressDetail") progressDetail: string, @@ -74,9 +76,9 @@ export class CourseTrackingController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Course Tracking detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Course Tracking detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -88,21 +90,21 @@ export class CourseTrackingController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Course Tracking has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Course Tracking has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) - @ApiQuery({ name: "progressDetail", required: false }) - @ApiQuery({ name: "courseId", required: false }) - @ApiQuery({ name: "userId", required: false }) - @ApiQuery({ name: "contentIds", required: false }) - @ApiQuery({ name: "startTime", required: false }) - @ApiQuery({ name: "endTime", required: false }) - @ApiQuery({ name: "certificate", required: false }) - @ApiQuery({ name: "status", required: false }) - @ApiQuery({ name: "source", required: false }) + // @ApiQuery({ name: "progressDetail", required: false }) + // @ApiQuery({ name: "courseId", required: false }) + // @ApiQuery({ name: "userId", required: false }) + // @ApiQuery({ name: "contentIds", required: false }) + // @ApiQuery({ name: "startTime", required: false }) + // @ApiQuery({ name: "endTime", required: false }) + // @ApiQuery({ name: "certificate", required: false }) + // @ApiQuery({ name: "status", required: false }) + // @ApiQuery({ name: "source", required: false }) public async updateTracking( @Param("id") courseTrackingId: string, @Req() request: Request, @@ -132,19 +134,19 @@ export class CourseTrackingController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Course Tracking list." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "courseId", required: false }) - @ApiQuery({ name: "userId", required: false }) - @ApiQuery({ name: "status", required: false }) - @ApiQuery({ name: "page", required: false }) - @ApiQuery({ name: "source", required: false }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Course Tracking list." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "courseId", required: false }) + // @ApiQuery({ name: "userId", required: false }) + // @ApiQuery({ name: "status", required: false }) + // @ApiQuery({ name: "page", required: false }) + // @ApiQuery({ name: "source", required: false }) public async searchCourseTracking( @Query("limit") limit: string, @Query("courseId") courseId: string, diff --git a/src/group/group.controller.ts b/src/group/group.controller.ts index 9257bdb8..21bfcddf 100644 --- a/src/group/group.controller.ts +++ b/src/group/group.controller.ts @@ -6,6 +6,7 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiConsumes, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -31,16 +32,17 @@ import { diskStorage } from "multer"; import { GroupAdapter } from "./groupadapter"; -@ApiTags("Group") +// @ApiTags("Group") +@ApiExcludeController() @Controller("group") export class GroupController { constructor(private groupAdapter: GroupAdapter) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Group detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -49,9 +51,9 @@ export class GroupController { } @Post() - @ApiConsumes("multipart/form-data") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group has been created successfully." }) + // @ApiConsumes("multipart/form-data") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Group has been created successfully." }) @UseInterceptors( FileInterceptor("image", { storage: diskStorage({ @@ -61,8 +63,8 @@ export class GroupController { fileFilter: imageFileFilter, }) ) - @ApiBody({ type: GroupDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBody({ type: GroupDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createGroup( @Req() request: Request, @@ -78,9 +80,9 @@ export class GroupController { } @Put("/:id") - @ApiConsumes("multipart/form-data") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group has been updated successfully." }) + // @ApiConsumes("multipart/form-data") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Group has been updated successfully." }) @UseInterceptors( FileInterceptor("image", { storage: diskStorage({ @@ -90,8 +92,8 @@ export class GroupController { fileFilter: imageFileFilter, }) ) - @ApiBody({ type: GroupDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBody({ type: GroupDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateGroup( @Param("id") groupId: string, @@ -110,10 +112,10 @@ export class GroupController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group list." }) - @ApiBody({ type: GroupSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Group list." }) + // @ApiBody({ type: GroupSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", @@ -129,9 +131,9 @@ export class GroupController { @Get(":groupId/participants") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Group detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Group detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async findMembersOfGroup( @Param("groupId") id: string, @Query("role") role: string, @@ -144,9 +146,9 @@ export class GroupController { @Get("participant/:userId") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Group detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Group detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async getGroupsByUserId( @Param("userId") id: string, @Query("role") role: string, @@ -159,9 +161,9 @@ export class GroupController { @Get(":groupId/child") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Group detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Group detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) public async findMembersOfChildGroup( @Param("groupId") id: string, @Query("role") role: string, diff --git a/src/groupMembership/groupMembership.controller.ts b/src/groupMembership/groupMembership.controller.ts index e0fe4ff2..9cdd38aa 100644 --- a/src/groupMembership/groupMembership.controller.ts +++ b/src/groupMembership/groupMembership.controller.ts @@ -4,6 +4,7 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -24,16 +25,17 @@ import { GroupMembershipDto } from "./dto/groupMembership.dto"; import { GroupMembershipSearchDto } from "./dto/groupMembership-search.dto"; import { GroupMembershipService } from "src/adapters/hasura/groupMembership.adapter"; -@ApiTags("Group Membership") +// @ApiTags("Group Membership") +@ApiExcludeController() @Controller("groupmembership") export class GroupMembershipController { constructor(private service: GroupMembershipService) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group Membership detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Group Membership detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -45,12 +47,12 @@ export class GroupMembershipController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Group Membership has been created successfully.", - }) - @ApiBody({ type: GroupMembershipDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Group Membership has been created successfully.", + // }) + // @ApiBody({ type: GroupMembershipDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createGroupMembership( @Req() request: Request, @@ -60,12 +62,12 @@ export class GroupMembershipController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Group Membership has been updated successfully.", - }) - @ApiBody({ type: GroupMembershipDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Group Membership has been updated successfully.", + // }) + // @ApiBody({ type: GroupMembershipDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateGroupMembership( @Param("id") groupMembershipId: string, @@ -80,10 +82,10 @@ export class GroupMembershipController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group Membership list." }) - @ApiBody({ type: GroupMembershipSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Group Membership list." }) + // @ApiBody({ type: GroupMembershipSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/holiday/holiday.controller.ts b/src/holiday/holiday.controller.ts index 52fda8b4..fb50b69a 100644 --- a/src/holiday/holiday.controller.ts +++ b/src/holiday/holiday.controller.ts @@ -20,20 +20,23 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { HolidayDto } from "./dto/holiday.dto"; import { HolidaySearchDto } from "./dto/holiday-search.dto"; import { Request } from "@nestjs/common"; import { HolidayAdapter } from "./holidayadapter"; -@ApiTags("Holiday") +// @ApiTags("Holiday") + +@ApiExcludeController() @Controller("holiday") export class HolidayController { constructor(private holidayProvider: HolidayAdapter) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Holiday detail." }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Holiday detail." }) @SerializeOptions({ strategy: "excludeAll", }) @@ -44,10 +47,10 @@ export class HolidayController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Holiday has been created successfully." }) - @ApiBody({ type: HolidayDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Holiday has been created successfully." }) + // @ApiBody({ type: HolidayDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createHoliday( @Req() request: Request, @@ -59,9 +62,9 @@ export class HolidayController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Holiday has been updated successfully." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Holiday has been updated successfully." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateHoliday( @Param("id") holidayId: string, @@ -74,10 +77,10 @@ export class HolidayController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Holiday list." }) - @ApiBody({ type: HolidaySearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Holiday list." }) + // @ApiBody({ type: HolidaySearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", @@ -93,11 +96,11 @@ export class HolidayController { @Get("") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "fromDate" }) - @ApiQuery({ name: "toDate" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " Ok." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "fromDate" }) + // @ApiQuery({ name: "toDate" }) public async holidayFilter( @Query("fromDate") date: string, @Query("toDate") toDate: string, diff --git a/src/inAppNotification/inAppNotification.controller.ts b/src/inAppNotification/inAppNotification.controller.ts index b0c77f32..64c1609d 100644 --- a/src/inAppNotification/inAppNotification.controller.ts +++ b/src/inAppNotification/inAppNotification.controller.ts @@ -4,6 +4,7 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -17,21 +18,22 @@ import { } from "@nestjs/common"; import { InAppNotificationService } from "src/adapters/sunbirdrc/inAppNotification.adapter"; -@ApiTags("In App Notification") +// @ApiTags("In App Notification") +@ApiExcludeController() @Controller("inappnotification") export class InAppNotificationController { constructor(private service: InAppNotificationService) {} @Post("inappnotification") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Notification has been sent successfully.", - }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Notification has been sent successfully.", + // }) @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "module" }) - @ApiQuery({ name: "groupId" }) - @ApiQuery({ name: "templateId" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "module" }) + // @ApiQuery({ name: "groupId" }) + // @ApiQuery({ name: "templateId" }) public async inAppNotification( @Query("module") module: string, @Query("groupId") groupId: string, @@ -42,16 +44,16 @@ export class InAppNotificationController { } @Get("/userhistory") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "User Notification History.", - }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "User Notification History.", + // }) @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "userId" }) - @ApiQuery({ name: "provider" }) - @ApiQuery({ name: "startDate" }) - @ApiQuery({ name: "endDate" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "userId" }) + // @ApiQuery({ name: "provider" }) + // @ApiQuery({ name: "startDate" }) + // @ApiQuery({ name: "endDate" }) public async userHistoryNotification( @Query("userId") userId: string, @Query("provider") provider: string, @@ -69,16 +71,16 @@ export class InAppNotificationController { } @Get("/bothistory") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Bot Notification History.", - }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Bot Notification History.", + // }) @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "botId" }) - @ApiQuery({ name: "provider" }) - @ApiQuery({ name: "startDate" }) - @ApiQuery({ name: "endDate" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "botId" }) + // @ApiQuery({ name: "provider" }) + // @ApiQuery({ name: "startDate" }) + // @ApiQuery({ name: "endDate" }) public async botHistoryNotification( @Query("botId") botId: string, @Query("provider") provider: string, @@ -96,19 +98,19 @@ export class InAppNotificationController { } @Post("readreceipt") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Read Receipt.", - }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Read Receipt.", + // }) @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "eventType", required: false }) - @ApiQuery({ name: "externalId", required: false }) - @ApiQuery({ name: "destAdd", required: false }) - @ApiQuery({ name: "fcmDestAdd", required: false }) - @ApiQuery({ name: "messageId", required: false }) - @ApiQuery({ name: "text", required: false }) - @ApiQuery({ name: "from", required: false }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "eventType", required: false }) + // @ApiQuery({ name: "externalId", required: false }) + // @ApiQuery({ name: "destAdd", required: false }) + // @ApiQuery({ name: "fcmDestAdd", required: false }) + // @ApiQuery({ name: "messageId", required: false }) + // @ApiQuery({ name: "text", required: false }) + // @ApiQuery({ name: "from", required: false }) public async readReceipt( @Query("eventType") eventType: string, @Query("externalId") externalId: string, diff --git a/src/lessonPlan/lessonPlan.controller.ts b/src/lessonPlan/lessonPlan.controller.ts index 792c9861..baeb894f 100644 --- a/src/lessonPlan/lessonPlan.controller.ts +++ b/src/lessonPlan/lessonPlan.controller.ts @@ -18,20 +18,22 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, + ApiExcludeController, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { LessonPlanDto } from "./dto/lessonPlan.dto"; import { LessonPlanSearchDto } from "./dto/lessonPlan.search.dto"; import { LessonPlanService } from "src/adapters/sunbirdrc/lessonPlan.adapter"; -@ApiTags("Lesson Plan") +// @ApiTags("Lesson Plan") +@ApiExcludeController() @Controller("lessonPlan") export class LessonPlanController { constructor(private readonly service: LessonPlanService) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "LessonPlan detail." }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "LessonPlan detail." }) @SerializeOptions({ strategy: "excludeAll", }) @@ -40,12 +42,12 @@ export class LessonPlanController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "LessonPlan has been created successfully.", - }) - @ApiBody({ type: LessonPlanDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "LessonPlan has been created successfully.", + // }) + // @ApiBody({ type: LessonPlanDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createLessonPlan( @Req() request: Request, @@ -55,11 +57,11 @@ export class LessonPlanController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "LessonPlan has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "LessonPlan has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateLessonPlan( @Param("id") lessonPlanId: string, @@ -74,10 +76,10 @@ export class LessonPlanController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "LessonPlan list." }) - @ApiBody({ type: LessonPlanSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "LessonPlan list." }) + // @ApiBody({ type: LessonPlanSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/like/like.controller.ts b/src/like/like.controller.ts index 67f4a14a..4b8be67b 100644 --- a/src/like/like.controller.ts +++ b/src/like/like.controller.ts @@ -21,20 +21,22 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { LikeDto } from "./dto/like.dto"; import { LikeSearchDto } from "./dto/like-search.dto"; import { LikeAdapter } from "./likeadapter"; -@ApiTags("Like") +// @ApiTags("Like") +@ApiExcludeController() @Controller("like") export class LikeController { constructor(private likeAdapter: LikeAdapter) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Like detail." }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Like detail." }) @SerializeOptions({ strategy: "excludeAll", }) @@ -43,23 +45,23 @@ export class LikeController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Like has been created successfully.", - }) - @ApiBody({ type: LikeDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Like has been created successfully.", + // }) + // @ApiBody({ type: LikeDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) public async createLike(@Req() request: Request, @Body() likeDto: LikeDto) { return this.likeAdapter.buildLikeAdapter().createLike(request, likeDto); } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Like has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Like has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateLike( @Param("id") likeId: string, @@ -72,10 +74,10 @@ export class LikeController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Like list." }) - @ApiBody({ type: LikeSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Like list." }) + // @ApiBody({ type: LikeSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", @@ -91,10 +93,10 @@ export class LikeController { @Post("/getAllLikes") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "All Like." }) - @ApiQuery({ name: "contextId" }) - @ApiQuery({ name: "context" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "All Like." }) + // @ApiQuery({ name: "contextId" }) + // @ApiQuery({ name: "context" }) public async getCountLike( @Query("contextId") contextId: string, @Query("context") context: string, @@ -107,8 +109,8 @@ export class LikeController { @Delete("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Delete like. " }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Delete like. " }) public async deleteLike( @Param("id") likeId: string, @Req() request: Request diff --git a/src/mentorTracking/mentorTracking.controller.ts b/src/mentorTracking/mentorTracking.controller.ts index 7ffa394e..2b1a7010 100644 --- a/src/mentorTracking/mentorTracking.controller.ts +++ b/src/mentorTracking/mentorTracking.controller.ts @@ -25,6 +25,7 @@ import { ApiBasicAuth, ApiQuery, ApiConsumes, + ApiExcludeController, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { MentorTrackingDto } from "./dto/mentorTracking.dto"; @@ -33,15 +34,16 @@ import { FileInterceptor } from "@nestjs/platform-express"; import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; import { diskStorage } from "multer"; import { FeedbackCreateDto } from "./dto/feedback-create.dto"; -@ApiTags("Mentor Tracking") +// @ApiTags("Mentor Tracking") +@ApiExcludeController() @Controller("mentortracking") export class MentorTrackingController { constructor(private readonly service: MentorTrackingService) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Mentor Tracking detail." }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Mentor Tracking detail." }) @SerializeOptions({ strategy: "excludeAll", }) @@ -50,11 +52,11 @@ export class MentorTrackingController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Mentor Tracking has been created successfully.", - }) - @ApiBody({ type: MentorTrackingDto }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Mentor Tracking has been created successfully.", + // }) + // @ApiBody({ type: MentorTrackingDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({})) @@ -66,11 +68,11 @@ export class MentorTrackingController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Mentor Tracking has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Mentor Tracking has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({})) public async updateMentor( @@ -86,9 +88,9 @@ export class MentorTrackingController { } @Put("feedback/:id") - @ApiConsumes("multipart/form-data") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group has been updated successfully." }) + // @ApiConsumes("multipart/form-data") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Group has been updated successfully." }) @UseInterceptors( FileInterceptor("image", { storage: diskStorage({ @@ -98,8 +100,8 @@ export class MentorTrackingController { fileFilter: imageFileFilter, }) ) - @ApiBody({ type: FeedbackCreateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBody({ type: FeedbackCreateDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async feedback( @Param("id") mentorTrackingId: string, @@ -121,18 +123,18 @@ export class MentorTrackingController { @Post("/search") @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "mentorTrackingId", required: false }) - @ApiQuery({ name: "mentorId", required: false }) - @ApiQuery({ name: "teacherId", required: false }) - @ApiQuery({ name: "schoolId", required: false }) - @ApiQuery({ name: "scheduleVisitDate", required: false }) - @ApiQuery({ name: "visitDate", required: false }) - @ApiQuery({ name: "page", required: false }) - @ApiQuery({ name: "status", required: false }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " Ok." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "mentorTrackingId", required: false }) + // @ApiQuery({ name: "mentorId", required: false }) + // @ApiQuery({ name: "teacherId", required: false }) + // @ApiQuery({ name: "schoolId", required: false }) + // @ApiQuery({ name: "scheduleVisitDate", required: false }) + // @ApiQuery({ name: "visitDate", required: false }) + // @ApiQuery({ name: "page", required: false }) + // @ApiQuery({ name: "status", required: false }) public async searchMentorTracking( @Query("limit") limit: string, @Query("mentorTrackingId") mentorTrackingId: string, diff --git a/src/monitorTracking/monitorTracking.controller.ts b/src/monitorTracking/monitorTracking.controller.ts index cbb4dc59..8d878bfd 100644 --- a/src/monitorTracking/monitorTracking.controller.ts +++ b/src/monitorTracking/monitorTracking.controller.ts @@ -22,20 +22,22 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { MonitorTrackingDto } from "./dto/monitorTracking.dto"; import { MonitorTrackingService } from "src/adapters/hasura/monitorTracking.adapter"; -@ApiTags("Monitor Tracking") +// @ApiTags("Monitor Tracking") +@ApiExcludeController() @Controller("monitortracking") export class MonitorTrackingController { constructor(private readonly service: MonitorTrackingService) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Monitor Tracking detail." }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Monitor Tracking detail." }) @SerializeOptions({ strategy: "excludeAll", }) @@ -44,12 +46,12 @@ export class MonitorTrackingController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Monitor Tracking has been created successfully.", - }) - @ApiBody({ type: MonitorTrackingDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Monitor Tracking has been created successfully.", + // }) + // @ApiBody({ type: MonitorTrackingDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({})) public async createMonitor( @@ -60,11 +62,11 @@ export class MonitorTrackingController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Monitor Tracking has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Monitor Tracking has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({})) public async updateMonitor( @@ -81,17 +83,17 @@ export class MonitorTrackingController { @Post("/search") @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "monitorTrackingId", required: false }) - @ApiQuery({ name: "monitorId", required: false }) - @ApiQuery({ name: "schoolId", required: false }) - @ApiQuery({ name: "groupId", required: false }) - @ApiQuery({ name: "scheduleVisitDate", required: false }) - @ApiQuery({ name: "visitDate", required: false }) - @ApiQuery({ name: "page", required: false }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " Ok." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "monitorTrackingId", required: false }) + // @ApiQuery({ name: "monitorId", required: false }) + // @ApiQuery({ name: "schoolId", required: false }) + // @ApiQuery({ name: "groupId", required: false }) + // @ApiQuery({ name: "scheduleVisitDate", required: false }) + // @ApiQuery({ name: "visitDate", required: false }) + // @ApiQuery({ name: "page", required: false }) public async searchMonitorTracking( @Query("limit") limit: string, @Query("monitorTrackingId") monitorTrackingId: string, diff --git a/src/notification/instantNotification.controller.ts b/src/notification/instantNotification.controller.ts index f87660cf..f20c7398 100644 --- a/src/notification/instantNotification.controller.ts +++ b/src/notification/instantNotification.controller.ts @@ -6,6 +6,7 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -24,24 +25,25 @@ import { import { NotificationService } from "src/adapters/sunbirdrc/notification.adapter"; import { NotificationSearchDto } from "./dto/notification-search.dto"; -@ApiTags("Instant Notification") +// @ApiTags("Instant Notification") @Controller("instantNotification") +@ApiExcludeController() export class instantNotificationController { constructor(private service: NotificationService) {} @Post("instantSend") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Notification has been sent successfully.", - }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Notification has been sent successfully.", + // }) @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "module" }) - @ApiQuery({ name: "eventTrigger" }) - @ApiQuery({ name: "templateId" }) - @ApiQuery({ name: "senderId" }) - @ApiQuery({ name: "groupId" }) - @ApiQuery({ name: "channel" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "module" }) + // @ApiQuery({ name: "eventTrigger" }) + // @ApiQuery({ name: "templateId" }) + // @ApiQuery({ name: "senderId" }) + // @ApiQuery({ name: "groupId" }) + // @ApiQuery({ name: "channel" }) public async instantSendNotification( @Query("module") module: string, @Query("eventTrigger") eventTrigger: string, @@ -64,9 +66,9 @@ export class instantNotificationController { @Get("log/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Notification Log detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Notification Log detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -78,10 +80,10 @@ export class instantNotificationController { } @Post("log/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Notification log list." }) - @ApiBody({ type: NotificationSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Notification log list." }) + // @ApiBody({ type: NotificationSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/notification/scheduleNotification.controller.ts b/src/notification/scheduleNotification.controller.ts index ef5f1aa2..c6e3c360 100644 --- a/src/notification/scheduleNotification.controller.ts +++ b/src/notification/scheduleNotification.controller.ts @@ -6,6 +6,7 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -25,7 +26,8 @@ import { import { NotificationService } from "src/adapters/sunbirdrc/notification.adapter"; import { NotificationSearchDto } from "./dto/notification-search.dto"; -@ApiTags("Schedule Notification") +// @ApiTags("Schedule Notification") +@ApiExcludeController() @Controller("scheduleNotification") export class scheduleNotificationController { constructor(private service: NotificationService) {} diff --git a/src/role/role.controller.ts b/src/role/role.controller.ts index c6832b8e..50bf606b 100644 --- a/src/role/role.controller.ts +++ b/src/role/role.controller.ts @@ -20,20 +20,22 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, + ApiExcludeController, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { RoleDto } from "./dto/role.dto"; import { RoleService } from "src/adapters/hasura/role.adapter"; -@ApiTags("Role") +// @ApiTags("Role") +@ApiExcludeController() @Controller("role") export class RoleController { constructor(private readonly service: RoleService) {} @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "role detail." }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "role detail." }) @SerializeOptions({ strategy: "excludeAll", }) @@ -42,23 +44,23 @@ export class RoleController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Role has been created successfully.", - }) - @ApiBody({ type: RoleDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Role has been created successfully.", + // }) + // @ApiBody({ type: RoleDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async creatRole(@Req() request: Request, @Body() roleDto: RoleDto) { return this.service.createRole(request, roleDto); } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Role has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Role has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateRole( @Param("id") roleId: string, @@ -70,14 +72,14 @@ export class RoleController { @Post("/search") @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "roleId", required: false }) - @ApiQuery({ name: "title", required: false }) - @ApiQuery({ name: "parentId", required: false }) - @ApiQuery({ name: "status", required: false }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " Ok." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "roleId", required: false }) + // @ApiQuery({ name: "title", required: false }) + // @ApiQuery({ name: "parentId", required: false }) + // @ApiQuery({ name: "status", required: false }) public async searchRole( @Query("limit") limit: string, @Query("roleId") roleId: string, diff --git a/src/school/school.controller.ts b/src/school/school.controller.ts index e78633db..7a5368dd 100644 --- a/src/school/school.controller.ts +++ b/src/school/school.controller.ts @@ -20,10 +20,12 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, + ApiExcludeController, } from "@nestjs/swagger"; import { SchoolSearchDto } from "./dto/school-search.dto"; import { SchoolAdapter } from "./schooladapter"; -@ApiTags("School") +// @ApiTags("School") +@ApiExcludeController() @Controller("school") export class SchoolController { constructor(private schoolAdapter: SchoolAdapter) {} @@ -31,8 +33,8 @@ export class SchoolController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "School detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiOkResponse({ description: "School detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -41,10 +43,10 @@ export class SchoolController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "School has been created successfully." }) - @ApiBody({ type: SchoolDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "School has been created successfully." }) + // @ApiBody({ type: SchoolDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createSchool( @Req() request: Request, @@ -56,9 +58,9 @@ export class SchoolController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "School has been updated successfully." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "School has been updated successfully." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateSchool( @Param("id") id: string, @@ -70,10 +72,10 @@ export class SchoolController { .updateSchool(id, request, schoolDto); } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "School list." }) - @ApiBody({ type: SchoolSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "School list." }) + // @ApiBody({ type: SchoolSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/student/student.controller.ts b/src/student/student.controller.ts index 25deb27f..3a7331aa 100644 --- a/src/student/student.controller.ts +++ b/src/student/student.controller.ts @@ -17,6 +17,7 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -35,7 +36,8 @@ import { StudentDto } from "./dto/student.dto"; import { StudentSearchDto } from "./dto/student-search.dto"; import { IServicelocator } from "src/adapters/studentservicelocator"; import { StudentAdapter } from "./studentadapter"; -@ApiTags("Student") +// @ApiTags("Student") +@ApiExcludeController() @Controller("student") export class StudentController { constructor( @@ -47,9 +49,9 @@ export class StudentController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Student detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Student detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -60,10 +62,10 @@ export class StudentController { } @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Student has been created successfully." }) - @ApiBody({ type: StudentDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Student has been created successfully." }) + // @ApiBody({ type: StudentDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createStudent( @Req() request: Request, @@ -75,9 +77,9 @@ export class StudentController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Student has been updated successfully." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Student has been updated successfully." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateStudent( @Param("id") id: string, @@ -90,10 +92,10 @@ export class StudentController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Student list." }) - @ApiBody({ type: StudentSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Student list." }) + // @ApiBody({ type: StudentSearchDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", diff --git a/src/template/template.controller.ts b/src/template/template.controller.ts index 3903c30b..04f626c7 100644 --- a/src/template/template.controller.ts +++ b/src/template/template.controller.ts @@ -6,6 +6,7 @@ import { ApiForbiddenResponse, ApiOkResponse, ApiTags, + ApiExcludeController, } from "@nestjs/swagger"; import { Body, @@ -25,18 +26,19 @@ import { TemplateService } from "src/adapters/sunbirdrc/template.adapter"; import { TemplateProcessDto } from "./dto/template-process.dto"; import { TemplateCreateDto } from "./dto/template-create.dto"; -@ApiTags("Template") +// @ApiTags("Template") +@ApiExcludeController() @Controller("template") export class TemplateController { constructor(private service: TemplateService) {} @Post("create") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: " Template has been created successfully.", - }) - @ApiBody({ type: TemplateCreateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: " Template has been created successfully.", + // }) + // @ApiBody({ type: TemplateCreateDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createTemplate( @Req() request: Request, @@ -46,10 +48,10 @@ export class TemplateController { } @Post("process") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: " template process." }) - @ApiBody({ type: TemplateProcessDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: " template process." }) + // @ApiBody({ type: TemplateProcessDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async processTemplate( @Req() request: Request, @@ -60,9 +62,9 @@ export class TemplateController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " template detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " template detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -72,9 +74,9 @@ export class TemplateController { @Get(":/searchByTag") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) //@ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Get all Questions detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "tag", required: true }) + // @ApiOkResponse({ description: "Get all Questions detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "tag", required: true }) public async getTemplates( @Query("tag") tag: string, @Req() request: Request diff --git a/src/trackAssessment/trackassessment.controller.ts b/src/trackAssessment/trackassessment.controller.ts index c5e3df3d..8cf61811 100644 --- a/src/trackAssessment/trackassessment.controller.ts +++ b/src/trackAssessment/trackassessment.controller.ts @@ -6,6 +6,7 @@ import { ApiBody, ApiQuery, ApiOkResponse, + ApiExcludeController, } from "@nestjs/swagger"; import { Controller, @@ -27,18 +28,19 @@ import { TrackAssessmentService } from "src/adapters/hasura/trackassessment.adap import { TrackAssessmentDto } from "./dto/trackassessment.dto"; import { isUUID } from "class-validator"; -@ApiTags("Track Assessment") +// @ApiTags("Track Assessment") +@ApiExcludeController() @Controller("trackassessment") export class AssessmentController { constructor(private service: TrackAssessmentService) {} @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Track Assessment has been created successfully.", - }) - @ApiBody({ type: TrackAssessmentDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Track Assessment has been created successfully.", + // }) + // @ApiBody({ type: TrackAssessmentDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({})) public async createAssessment( @@ -50,9 +52,9 @@ export class AssessmentController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Track Assessment detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Track Assessment detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -64,22 +66,22 @@ export class AssessmentController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Track Assessment list." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Track Assessment list." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) - @ApiQuery({ name: "fromDate", required: false }) - @ApiQuery({ name: "toDate", required: false }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "source", required: false }) - @ApiQuery({ name: "studentId", required: false }) - @ApiQuery({ name: "teacherId", required: false }) - @ApiQuery({ name: "groupId", required: false }) - @ApiQuery({ name: "subject", required: false }) - @ApiQuery({ name: "page", required: false }) + // @ApiQuery({ name: "fromDate", required: false }) + // @ApiQuery({ name: "toDate", required: false }) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "source", required: false }) + // @ApiQuery({ name: "studentId", required: false }) + // @ApiQuery({ name: "teacherId", required: false }) + // @ApiQuery({ name: "groupId", required: false }) + // @ApiQuery({ name: "subject", required: false }) + // @ApiQuery({ name: "page", required: false }) public async searchAssessment( @Query("fromDate") date: string, @Query("toDate") toDate: string, diff --git a/src/workHistory/workHistory.controller.ts b/src/workHistory/workHistory.controller.ts index b82889c5..11703b70 100644 --- a/src/workHistory/workHistory.controller.ts +++ b/src/workHistory/workHistory.controller.ts @@ -2,6 +2,7 @@ import { ApiBasicAuth, ApiBody, ApiCreatedResponse, + ApiExcludeController, ApiForbiddenResponse, ApiOkResponse, ApiQuery, @@ -26,18 +27,19 @@ import { import { WorkHistoryService } from "../adapters/hasura/workhistory.adapter"; import { WorkHistoryDto } from "./dto/work-history.dto"; -@ApiTags("Work History") +// @ApiTags("Work History") +@ApiExcludeController() @Controller("workhistory") export class WorkHistoryController { constructor(private service: WorkHistoryService) {} @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Work History has been created successfully.", - }) - @ApiBody({ type: WorkHistoryDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Work History has been created successfully.", + // }) + // @ApiBody({ type: WorkHistoryDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createWorkHistory( @Req() request: Request, @@ -47,11 +49,11 @@ export class WorkHistoryController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Work History has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Work History has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateWorkHistory( @Param("id") id: string, @@ -63,9 +65,9 @@ export class WorkHistoryController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Work History detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Work History detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -77,16 +79,16 @@ export class WorkHistoryController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Work History list." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "workHistoryId", required: false }) - @ApiQuery({ name: "userId", required: false }) - @ApiQuery({ name: "dateOfJoining", required: false }) - @ApiQuery({ name: "dateOfRelieving", required: false }) - @ApiQuery({ name: "page", required: false }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Work History list." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) + // @ApiQuery({ name: "limit", required: false }) + // @ApiQuery({ name: "workHistoryId", required: false }) + // @ApiQuery({ name: "userId", required: false }) + // @ApiQuery({ name: "dateOfJoining", required: false }) + // @ApiQuery({ name: "dateOfRelieving", required: false }) + // @ApiQuery({ name: "page", required: false }) public async searchWorkHistory( @Query("limit") limit: string, @Query("workHistoryId") workHistoryId: string, diff --git a/src/worksheet/worksheet.controller.ts b/src/worksheet/worksheet.controller.ts index 95872038..bbe1f662 100644 --- a/src/worksheet/worksheet.controller.ts +++ b/src/worksheet/worksheet.controller.ts @@ -2,6 +2,7 @@ import { ApiBasicAuth, ApiBody, ApiCreatedResponse, + ApiExcludeController, ApiForbiddenResponse, ApiOkResponse, ApiQuery, @@ -26,18 +27,19 @@ import { WorksheetService } from "src/adapters/hasura/worksheet.adapter"; import { WorksheetDto } from "./dto/worksheet.dto"; import { WorksheetSearchDto } from "./dto/worksheet-search.dto"; -@ApiTags("Worksheet") +// @ApiTags("Worksheet") +@ApiExcludeController() @Controller("worksheet") export class WorksheetController { constructor(private service: WorksheetService) {} @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Worksheet has been created successfully.", - }) - @ApiBody({ type: WorksheetDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Worksheet has been created successfully.", + // }) + // @ApiBody({ type: WorksheetDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async createWorksheet( @Req() request: Request, @@ -47,11 +49,11 @@ export class WorksheetController { } @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Worksheet has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ + // description: "Worksheet has been updated successfully.", + // }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) public async updateWorksheet( @Param("id") id: string, @@ -63,9 +65,9 @@ export class WorksheetController { @Get("/:id") @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Worksheet detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Worksheet detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) @@ -77,9 +79,9 @@ export class WorksheetController { } @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Worksheet list." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Worksheet list." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", @@ -93,11 +95,11 @@ export class WorksheetController { @Post(":worksheet/pdf") @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "worksheetId", required: true }) - @ApiQuery({ name: "templateId", required: true }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " Ok." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "worksheetId", required: true }) + // @ApiQuery({ name: "templateId", required: true }) public async getWorksheetPdf( @Query("worksheetId") worksheetId: string, @Query("templateId") templateId: number, @@ -108,15 +110,15 @@ export class WorksheetController { @Post("/share") @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "studentIds", required: true }) - @ApiQuery({ name: "teacherId", required: true }) - @ApiQuery({ name: "templateId", required: true }) - @ApiQuery({ name: "link", required: true }) - @ApiQuery({ name: "subject", required: true }) - @ApiQuery({ name: "topic", required: true }) + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: " Ok." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiQuery({ name: "studentIds", required: true }) + // @ApiQuery({ name: "teacherId", required: true }) + // @ApiQuery({ name: "templateId", required: true }) + // @ApiQuery({ name: "link", required: true }) + // @ApiQuery({ name: "subject", required: true }) + // @ApiQuery({ name: "topic", required: true }) public async sendWorksheet( @Query("studentIds") studentIds: [string], @Query("teacherId") teacherId: string, From 4efe2f6d0f4e1d525ac3fd9b1c16298cbd54a1cd Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 3 Apr 2024 11:10:55 +0530 Subject: [PATCH 164/408] Revert "Added Cohort Details API with multiple cohortId and userId" This reverts commit d36f8afa23b624abe6a84c8d73aaee5d680f5b35. --- src/cohort/cohort.controller.ts | 46 ++++++++++-------- src/cohort/cohort.service.ts | 76 +++++++++++++++++------------- src/cohort/dto/query-params.dto.ts | 11 ----- 3 files changed, 68 insertions(+), 65 deletions(-) delete mode 100644 src/cohort/dto/query-params.dto.ts diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 5a8f90c5..57d229c7 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -26,7 +26,6 @@ import { Headers, Delete, UseGuards, - ValidationPipe } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -39,7 +38,6 @@ import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortService } from "./cohort.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; -import { QueryParamsDto } from "./dto/query-params.dto"; // import { FieldsService } from "../fields/fields.service"; @ApiTags("Cohort") @Controller("cohort") @@ -85,7 +83,29 @@ export class CohortController { return this.cohortService.createCohort(request, cohortCreateDto); } - @Get("cohortDetails") + @Get("cohortList/:id") + @UseInterceptors(CacheInterceptor) + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Cohort detail" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async getCohortList( + @Headers() headers, + @Param("id") id: string, + @Req() request: Request, + @Res() response: Response + ) { + let tenantid = headers["tenantid"]; + console.log(request); + return this.cohortService.getCohortList(tenantid, id, request, response); + } + + @Get("cohortDetails/:id") @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort details" }) @@ -98,28 +118,14 @@ export class CohortController { }) public async getCohortDetails( @Headers() headers, - @Query() queryParams: QueryParamsDto, + @Param("id") cohortId: string, @Req() request: Request, @Res() response: Response ) { - queryParams.name = queryParams.name.toLocaleLowerCase(); - let data; - let tenantId = request.headers['tenantId'] - if (queryParams.name=== 'user') { - data=queryParams - return this.cohortService.getCohortsDetails(data,request,response) - } else if (queryParams.name === 'cohort') { - data=queryParams - return this.cohortService.getCohortsDetails(data,request,response) - } else { - return response.status(400).json({ - message:"Invaid Parameters" - }) - } + let tenantid = headers["tenantid"]; + return this.cohortService.getCohortsDetails(tenantid, cohortId, request, response); } - - // search @Post("/search") @ApiBasicAuth("access-token") diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index caff0cee..0525834e 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -36,27 +36,62 @@ export class CohortService { private fieldsService: FieldsService, ) { } - public async getCohortsDetails(userData, + public async getCohortsDetails(tenantId: string, + cohortId: string, request: any, response: any){ - let apiId = 'api.concept.getCohortDetails' + const apiId = "api.concept.cohortDetails"; + let cohortName = await this.cohortRepository.findOne({ + where:{cohortId} + }) + // let result = { + // cohortData: [], + // }; + let cohortData = { + cohortId: cohortId, + name:cohortName.name, + parentId:cohortName.parentId, + customField:{} + }; + const getDetails = await this.getCohortListDetails(cohortId); + cohortData.customField=getDetails + // result.cohortData.push(cohortData); + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + cohortData, + "OK" + ) + ); + } + + public async getCohortList( + tenantId: string, + userId: string, + request: any, + response: any + ) { + const apiId = "api.concept.editminiScreeningAnswer"; try { - if(userData.name==='user'){ - let findCohortId = await this.findCohortName(userData?.id); + let findCohortId = await this.findCohortName(userId); let result = { cohortData: [], }; + for (let data of findCohortId) { let cohortData = { - cohortId: data?.cohortId, + cohortId: data.cohortId, name:data.name, - parentId:data?.parentId, + parentId:data.parentId, customField:{} }; - const getDetails = await this.getCohortListDetails(data?.cohortId); + const getDetails = await this.getCohortListDetails(data.cohortId); cohortData.customField=getDetails result.cohortData.push(cohortData); } + return response .status(HttpStatus.OK) .send( @@ -66,30 +101,6 @@ export class CohortService { "OK" ) ); - }else{ - let cohortName = await this.cohortRepository.findOne({ - where:{cohortId:userData?.id}, - select:['name','parentId'] - }) - let cohortData = { - cohortId: userData?.id, - name:cohortName.name, - parentId:cohortName.parentId, - customField:{} - }; - const getDetails = await this.getCohortListDetails(userData?.id); - cohortData.customField=getDetails - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - cohortData, - "OK" - ) - ); - - } } catch (error) { return response .status(HttpStatus.INTERNAL_SERVER_ERROR) @@ -110,9 +121,6 @@ export class CohortService { LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" WHERE cm."userId"=$1 AND c.status=true`; let result = await this.cohortMembersRepository.query(query, [userId]); - // if(!result.length){ - // return null; - // } return result; } diff --git a/src/cohort/dto/query-params.dto.ts b/src/cohort/dto/query-params.dto.ts deleted file mode 100644 index c245a5cd..00000000 --- a/src/cohort/dto/query-params.dto.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { IsNotEmpty, IsString, IsInt } from 'class-validator'; - -export class QueryParamsDto { - @IsNotEmpty() - @IsString() - name: string; - - @IsNotEmpty() - @IsString() - id: string; -} From e71a9b5144837d28a43ce1f212e1b9a0b1fccb71 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 3 Apr 2024 13:28:17 +0530 Subject: [PATCH 165/408] TypeORMError: Provided take value is not a number. Please provide a numeric value --- src/cohort/cohort.controller.ts | 3 +++ src/cohort/dto/cohort-search.dto.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 57d229c7..85a35cce 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -26,6 +26,8 @@ import { Headers, Delete, UseGuards, + ValidationPipe, + UsePipes, } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -133,6 +135,7 @@ export class CohortController { @ApiBody({ type: CohortSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UseInterceptors(ClassSerializerInterceptor) + @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", }) diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index b1a76b6f..c265abb4 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -1,10 +1,13 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { IsNumberString } from "class-validator"; + export class CohortSearchDto { @ApiProperty({ type: String, description: "Limit", }) + @IsNumberString() limit: string; @ApiProperty({ From 02603cb0c40b8058383c9f8a99732e2eeb3ec8e2 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 15:55:18 +0530 Subject: [PATCH 166/408] chore : Add validation to auth api --- src/auth/auth.controller.ts | 6 +++++- src/auth/dto/auth-dto.ts | 10 +++++++--- src/common/utils/keycloak.service.ts | 4 +--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 300ea502..4cfd0650 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -16,9 +16,10 @@ import { Res, Request, Response, - Headers, HttpStatus, HttpCode, + UsePipes, + ValidationPipe, } from "@nestjs/common"; import { AuthDto, @@ -34,6 +35,7 @@ export class AuthController { @Post("/login") @ApiBody({ type: AuthDto }) + @UsePipes(ValidationPipe) @HttpCode(HttpStatus.OK) @ApiForbiddenResponse({ description: "Forbidden" }) public async login(@Body() authDto: AuthDto) { @@ -61,6 +63,7 @@ export class AuthController { @Post("/refresh") @HttpCode(HttpStatus.OK) @ApiBody({ type: RefreshTokenRequestBody }) + @UsePipes(ValidationPipe) refreshToken(@Body() body: RefreshTokenRequestBody) { const { refresh_token: refreshToken } = body; @@ -68,6 +71,7 @@ export class AuthController { } @Post("/logout") + @UsePipes(ValidationPipe) @HttpCode(HttpStatus.OK) @ApiBody({ type: LogoutRequestBody }) async logout(@Body() body: LogoutRequestBody) { diff --git a/src/auth/dto/auth-dto.ts b/src/auth/dto/auth-dto.ts index 6b38c666..f6bbaebf 100644 --- a/src/auth/dto/auth-dto.ts +++ b/src/auth/dto/auth-dto.ts @@ -18,7 +18,7 @@ export class AuthDto { @IsNotEmpty() password: string; - constructor(partial: Partial) { + constructor(partial: AuthDto) { Object.assign(this, partial); } } @@ -28,9 +28,11 @@ export class RefreshTokenRequestBody { type: String, description: "token", }) + @IsString() + @IsNotEmpty() refresh_token: string; - constructor(partial: Partial) { + constructor(partial: RefreshTokenRequestBody) { Object.assign(this, partial); } } @@ -40,9 +42,11 @@ export class LogoutRequestBody { type: String, description: "token", }) + @IsString() + @IsNotEmpty() refresh_token: string; - constructor(partial: Partial) { + constructor(partial: LogoutRequestBody) { Object.assign(this, partial); } } diff --git a/src/common/utils/keycloak.service.ts b/src/common/utils/keycloak.service.ts index 5be96714..9232c646 100644 --- a/src/common/utils/keycloak.service.ts +++ b/src/common/utils/keycloak.service.ts @@ -28,9 +28,7 @@ export class KeycloakService { private clientSecret: string; private axios; userToken: any; - constructor( - private readonly configService: ConfigService, - ) { + constructor(private readonly configService: ConfigService) { this.baseURL = this.configService.get("KEYCLOAK"); this.userToken = this.configService.get("KEYCLOAK_USER_TOKEN"); this.realm = this.configService.get("KEYCLOAK_REALM"); From 8186558dc299cb136cc2e72751314f52491a4e79 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 16:15:26 +0530 Subject: [PATCH 167/408] chore : removed Sunbird RC adapters --- src/adapters/sunbirdrc/adminForm.adapter.ts | 174 ---- src/adapters/sunbirdrc/attendance.adapter.ts | 766 ------------------ src/adapters/sunbirdrc/comment.adapter.ts | 186 ----- src/adapters/sunbirdrc/config.adapter.ts | 267 ------ src/adapters/sunbirdrc/group.adapter.ts | 431 ---------- src/adapters/sunbirdrc/holiday.adapter.ts | 175 ---- .../sunbirdrc/inAppNotification.adapter.ts | 250 ------ src/adapters/sunbirdrc/lessonPlan.adapter.ts | 178 ---- src/adapters/sunbirdrc/like.adapter.ts | 235 ------ .../sunbirdrc/notification.adapter.ts | 618 -------------- src/adapters/sunbirdrc/school.adapter.ts | 156 ---- src/adapters/sunbirdrc/student.adapter.ts | 226 ------ src/adapters/sunbirdrc/subnbird.module.ts | 38 - src/adapters/sunbirdrc/template.adapter.ts | 133 --- src/adapters/sunbirdrc/user.adapter.ts | 294 ------- 15 files changed, 4127 deletions(-) delete mode 100644 src/adapters/sunbirdrc/adminForm.adapter.ts delete mode 100644 src/adapters/sunbirdrc/attendance.adapter.ts delete mode 100644 src/adapters/sunbirdrc/comment.adapter.ts delete mode 100644 src/adapters/sunbirdrc/config.adapter.ts delete mode 100644 src/adapters/sunbirdrc/group.adapter.ts delete mode 100644 src/adapters/sunbirdrc/holiday.adapter.ts delete mode 100644 src/adapters/sunbirdrc/inAppNotification.adapter.ts delete mode 100644 src/adapters/sunbirdrc/lessonPlan.adapter.ts delete mode 100644 src/adapters/sunbirdrc/like.adapter.ts delete mode 100644 src/adapters/sunbirdrc/notification.adapter.ts delete mode 100644 src/adapters/sunbirdrc/school.adapter.ts delete mode 100644 src/adapters/sunbirdrc/student.adapter.ts delete mode 100644 src/adapters/sunbirdrc/subnbird.module.ts delete mode 100644 src/adapters/sunbirdrc/template.adapter.ts delete mode 100644 src/adapters/sunbirdrc/user.adapter.ts diff --git a/src/adapters/sunbirdrc/adminForm.adapter.ts b/src/adapters/sunbirdrc/adminForm.adapter.ts deleted file mode 100644 index 79fd7b30..00000000 --- a/src/adapters/sunbirdrc/adminForm.adapter.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable, HttpException } from "@nestjs/common"; -const resolvePath = require("object-resolve-path"); -import { AxiosResponse } from "axios"; -import { AdminFormDto } from "src/adminForm/dto/adminForm.dto"; -import { first, map, Observable } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { AdminFormSearchDto } from "src/adminForm/dto/adminForm-search.dto"; -@Injectable() -export class AdminFormService { - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}/AdminForm`; - - public async getAdminForm(adminFormId: string, request: any) { - return this.httpService - .get(`${this.url}/${adminFormId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = [axiosResponse.data]; - - const adminFormDto = await this.mappedResponse(data); - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: adminFormDto[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async createAdminForm(request: any, adminFormDto: AdminFormDto) { - return this.httpService - .post(`${this.url}`, adminFormDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateAdminForm( - adminFormId: string, - request: any, - adminFormDto: AdminFormDto - ) { - var axios = require("axios"); - var data = adminFormDto; - - var config = { - method: "put", - url: `${this.url}/${adminFormId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchAdminForm( - request: any, - adminFormSearchDto: AdminFormSearchDto - ) { - return this.httpService - .post(`${this.url}/search`, adminFormSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = await this.mappedResponse(response.data); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: responsedata, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async adminFormFilter(fromDate: string, toDate: string, request: any) { - let axios = require("axios"); - let filters = { - fromDate, - toDate, - }; - const filterArray = Object.keys(filters).filter( - (value, key) => filters[value] && filters[value] !== "" - ); - let data = { date: { between: [] } }; - filterArray.forEach((value, key) => { - if (["fromDate", "toDate"].includes(value)) { - data["date"].between.push(filters[value]); - } - }); - - let config = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: { filters: data }, - }; - - const response = await axios(config); - - let result = response?.data && response.data; - const responsedata = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: responsedata, - }); - } - - public async mappedResponse(result: any) { - const adminFormResponse = result.map((obj: any) => { - const adminFormMapping = { - adminFormId: obj?.osid ? `${obj.osid}` : "", - moduleId: obj?.moduleId ? `${obj.moduleId}` : "", - formSchema: obj?.formSchema ? `${obj.formSchema}` : "", - createdAt: obj?.osCreatedAt ? `${obj.osCreatedAt}` : "", - updatedAt: obj?.osUpdatedAt ? `${obj.osUpdatedAt}` : "", - createdBy: obj?.osCreatedBy ? `${obj.osCreatedBy}` : "", - updatedBy: obj?.osUpdatedBy ? `${obj.osUpdatedBy}` : "", - }; - return new AdminFormDto(adminFormMapping); - }); - - return adminFormResponse; - } -} diff --git a/src/adapters/sunbirdrc/attendance.adapter.ts b/src/adapters/sunbirdrc/attendance.adapter.ts deleted file mode 100644 index 9bfe90de..00000000 --- a/src/adapters/sunbirdrc/attendance.adapter.ts +++ /dev/null @@ -1,766 +0,0 @@ -import { Injectable, HttpException } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { AxiosResponse } from "axios"; -import { map } from "rxjs"; -import { AttendanceDto } from "src/attendance/dto/attendance.dto"; -import { SuccessResponse } from "src/success-response"; -import { ErrorResponse } from "src/error-response"; -import { catchError } from "rxjs/operators"; -import { AttendanceSearchDto } from "src/attendance/dto/attendance-search.dto"; -import { SegmentDto } from "src/common-dto/userSegment.dto"; -import moment from "moment"; - -import { IServicelocator } from "../attendanceservicelocator"; -import { StudentDto } from "src/student/dto/student.dto"; -import { AttendanceDateDto } from "src/attendance/dto/attendance-date.dto"; -export const SunbirdAttendanceToken = "SunbirdAttendance"; - -@Injectable() -export class AttendanceService implements IServicelocator { - constructor(private httpService: HttpService) {} - checkAndAddAttendance(request: Request, attendanceDto: AttendanceDto): unknown { - throw new Error("Method not implemented."); - } - attendanceByDate(tenantId: string, request: any, attendanceSearchDto: AttendanceDateDto) { - throw new Error("Method not implemented."); - } - url = `${process.env.BASEAPIURL}/Attendance`; - studentAPIUrl = `${process.env.BASEAPIURL}/Student`; - baseUrl = process.env.BASEAPIURL; - public async getAttendance( - tenantId: string, - attendanceId: any, - request: any - ) { - return this.httpService - .get(`${this.url}/${attendanceId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - const data = axiosResponse.data; - const result = [data]; - const mappedResponse = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: mappedResponse[0], - }); - }) - ); - } - - public async updateAttendance( - attendanceId: string, - request: any, - attendanceDto: AttendanceDto - ) { - var axios = require("axios"); - var data = attendanceDto; - - var config = { - method: "put", - url: `${this.url}/${attendanceId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchAttendance( - tenantId: string, - request: any, - attendanceSearchDto: AttendanceSearchDto - ) { - return this.httpService - .post(`${this.url}/search`, attendanceSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const mappedResponse = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: mappedResponse, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async userSegment( - groupId: string, - attendance: string, - date: string, - request: any - ) { - let axios = require("axios"); - - let data: any = { - filters: { - attendance: { - eq: `${attendance}`, - }, - groupId: { - eq: `${groupId}`, - }, - }, - }; - switch (date) { - case "today": - data.filters = { - ...data.filters, - attendanceDate: { - eq: `${moment().format("Y-MM-DD")}`, - }, - }; - break; - - case "yesterday": - data.filters = { - ...data.filters, - attendanceDate: { - eq: `${moment().add(-1, "days").format("Y-MM-DD")}`, - }, - }; - break; - - case "lastthreedays": - data.filters = { - ...data.filters, - attendanceDate: { - eq: `${moment().add(-3, "days").format("Y-MM-DD")}`, - }, - }; - break; - - case "thisweek": - data.filters = { - ...data.filters, - attendanceDate: { - between: [ - moment().startOf("week").format("Y-MM-DD"), - moment().endOf("week").format("Y-MM-DD"), - ], - }, - }; - break; - - case "lastweek": - data.filters = { - ...data.filters, - attendanceDate: { - between: [ - moment() - .subtract(1, "weeks") - .startOf("week") - .format("YYYY-MM-DD"), - moment().subtract(1, "weeks").endOf("week").format("YYYY-MM-DD"), - ], - }, - }; - - break; - - case "thismonth": - data.filters = { - ...data.filters, - attendanceDate: { - between: [ - moment().startOf("month").format("Y-MM-DD"), - moment().endOf("month").format("Y-MM-DD"), - ], - }, - }; - break; - - case "lastmonth": - data.filters = { - ...data.filters, - attendanceDate: { - between: [ - moment() - .subtract(1, "months") - .startOf("month") - .format("YYYY-MM-DD"), - moment() - .subtract(1, "months") - .endOf("month") - .format("YYYY-MM-DD"), - ], - }, - }; - - break; - } - - let config = { - method: "post", - url: `${this.url}/search`, - - data: data, - }; - - let startDates: any; - let endDates: any; - - if (data.filters.attendanceDate.between === undefined) { - startDates = ""; - endDates = ""; - } else { - startDates = data.filters.attendanceDate?.between[0] - ? data.filters.attendanceDate.between[0] - : ""; - endDates = data.filters.attendanceDate?.between[1] - ? data.filters.attendanceDate.between[1] - : ""; - } - - const response = await axios(config); - let resData = response?.data; - - let dateData = resData.map((e: any) => { - return e.attendanceDate; - }); - - const groupData = await axios.get(`${this.baseUrl}/Class/${groupId}`); - - const teacherData = await axios.get( - `${this.baseUrl}/User/${groupData.data.teacherId}` - ); - - const schoolData = await axios.get( - `${this.baseUrl}/School/${groupData.data.schoolId}` - ); - - let arrayIds = resData.map((e: any) => { - return e.userId; - }); - - let studentArray = []; - for (let value of arrayIds) { - let config = { - method: "get", - url: `${this.studentAPIUrl}/${value}`, - }; - const response = await axios(config); - const data = response?.data; - - const date = new Date(dateData[0]); - const month = date.toLocaleString("default", { month: "long" }); - - const studentDto = { - id: data.osid, - name: data?.firstName + " " + data?.lastName, - phoneNo: data.guardianPhoneNumber, - parentName: data?.guardianFirstName + " " + data?.guardianLastName, - attendanceDate: dateData[0], - month: month, - teacherName: - teacherData.data.firstName + " " + teacherData.data.lastName, - schoolName: schoolData.data.schoolName, - startDate: startDates, - endDate: endDates, - }; - let studentDtoData = new SegmentDto(studentDto); - studentArray.push(studentDtoData); - } - - return new SuccessResponse({ - data: studentArray, - }); - } - - public async attendanceFilter( - fromDate: string, - toDate: string, - userId: string, - userType: string, - attendance: string, - groupId: string, - schoolId: string, - eventId: string, - topicId: string, - request: any - ) { - let axios = require("axios"); - let filters = { - fromDate, - toDate, - userId, - userType, - attendance, - groupId, - schoolId, - eventId, - topicId, - }; - const filterArray = Object.keys(filters).filter( - (value, key) => filters[value] && filters[value] !== "" - ); - let data = { attendanceDate: { between: [] } }; - filterArray.forEach((value, key) => { - if (["fromDate", "toDate"].includes(value)) { - data["attendanceDate"].between.push(filters[value]); - } else { - data[value] = { eq: filters[value] }; - } - }); - - let config = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: { filters: data }, - }; - - const response = await axios(config); - let result = response?.data && response.data; - const mappedResponse = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: mappedResponse, - }); - } - - public async createAttendance(request: any, attendanceDto: AttendanceDto) { - let axios = require("axios"); - let data = { - filters: { - userId: { - eq: `${attendanceDto.userId}`, - }, - attendanceDate: { - eq: `${attendanceDto.attendanceDate}`, - }, - }, - }; - - let attendanceCreate = { - method: "post", - url: `${this.url}/search`, - - data: data, - }; - - const response = await axios(attendanceCreate); - let resData = response?.data; - let result = await this.mappedResponse(resData); - - let attendanceId = result.map(function (AttendanceDto) { - return AttendanceDto.attendanceId; - }); - - if (resData.length > 0) { - var updateData = attendanceDto; - var updateAttendance = { - method: "put", - url: `${this.url}/${attendanceId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: updateData, - }; - - const response = await axios(updateAttendance); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } else { - var createAttendance = attendanceDto; - var create = { - method: "post", - url: `${this.url}`, - headers: { - Authorization: request.headers.authorization, - }, - data: createAttendance, - }; - - const response = await axios(create); - - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - } - public async multipleAttendance( - tenantId: string, - request: any, - attendanceData: [Object] - ) { - let attendeeData = attendanceData["attendanceData"]; - const result = Promise.all( - attendeeData.map(async (data: any) => { - data["schoolId"] = attendanceData["schoolId"] - ? attendanceData["schoolId"] - : ""; - data["userType"] = attendanceData["userType"] - ? attendanceData["userType"] - : ""; - data["groupId"] = attendanceData["groupId"] - ? attendanceData["groupId"] - : ""; - data["topicId"] = attendanceData["topicId"] - ? attendanceData["topicId"] - : ""; - data["eventId"] = attendanceData["eventId"] - ? attendanceData["eventId"] - : ""; - data["attendanceDate"] = attendanceData["attendanceDate"] - ? attendanceData["attendanceDate"] - : ""; - data["latitude"] = attendanceData["latitude"] - ? attendanceData["latitude"] - : 0; - data["longitude"] = attendanceData["longitude"] - ? attendanceData["longitude"] - : 0; - data["image"] = attendanceData["image"] ? attendanceData["image"] : ""; - data["metaData"] = attendanceData["metaData"] - ? attendanceData["metaData"] - : []; - data["syncTime"] = attendanceData["syncTime"] - ? attendanceData["syncTime"] - : ""; - - let attendanceDto = data; - let axios = require("axios"); - let dataSearch = { - filters: { - userId: { - eq: `${attendanceDto.userId}`, - }, - attendanceDate: { - eq: `${attendanceDto.attendanceDate}`, - }, - }, - }; - - let attendanceCreate = { - method: "post", - url: `${this.url}/search`, - - data: dataSearch, - }; - - const response = await axios(attendanceCreate); - let resData = response?.data; - let result = await this.mappedResponse(resData); - - let attendanceId = result.map(function (AttendanceDto) { - return AttendanceDto.attendanceId; - }); - - if (resData.length > 0) { - var updateData = attendanceDto; - var updateAttendance = { - method: "put", - url: `${this.url}/${attendanceId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: updateData, - }; - - const response = await axios(updateAttendance); - return await response.data; - } else { - var createAttendance = attendanceDto; - var create = { - method: "post", - url: `${this.url}`, - headers: { - Authorization: request.headers.authorization, - }, - data: createAttendance, - }; - - const response = await axios(create); - return await response.data; - } - }) - ); - const responseArray = await result; - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: responseArray, - }); - } - - public async studentAttendanceByGroup( - date: string, - groupId: string, - request: any - ) { - let axios = require("axios"); - try { - let studentArray = []; - let data = { - filters: { - groupId: { - eq: `${groupId}`, - }, - attendanceDate: { - eq: `${date}`, - }, - }, - }; - let config = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - - const response = await axios(config); - - if (response.data.length > 0) { - const studentIds = response.data.map((e: any) => { - return e.userId; - }); - - for (let studentId of studentIds) { - const studentData = await axios.get( - `${this.studentAPIUrl}/${studentId}`, - { - headers: { - Authorization: request.headers.authorization, - }, - } - ); - - let responseData = await this.StudentMappedResponse([ - studentData.data, - ]); - let result = responseData[0]; - const updatedStudent = { - ...result, - attendance: response.data[0].attendance, - attendanceDate: response.data[0].attendanceDate, - }; - studentArray.push(updatedStudent); - } - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: studentArray, - }); - } else { - return new SuccessResponse({ - statusCode: 200, - message: "Attendance not marked for this class yet", - data: [], - }); - } - } catch (e) { - return new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - } - } - - public async studentAttendanceByUserId( - date: string, - userId: string, - request: any - ) { - let axios = require("axios"); - try { - let data = { - filters: { - userId: { - eq: `${userId}`, - }, - attendanceDate: { - eq: `${date}`, - }, - }, - }; - let config = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - - const response = await axios(config); - const studentId = response.data[0].userId; - const studentData = await axios.get( - `${this.studentAPIUrl}/${studentId}`, - { - headers: { - Authorization: request.headers.authorization, - }, - } - ); - - let responseData = await this.StudentMappedResponse([studentData.data]); - let result = responseData[0]; - const updatedStudent = { - ...result, - attendance: response.data[0].attendance, - attendanceDate: response.data[0].attendanceDate, - }; - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: updatedStudent, - }); - } catch (e) { - return `${e}`; - } - } - - public async mappedResponse(result: any) { - const attendanceResponse = result.map((item: any) => { - const attendanceMapping = { - attendanceId: item?.osid ? `${item.osid}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - userType: item?.userType ? `${item.userType}` : "", - userId: item?.userId ? `${item.userId}` : "", - groupId: item?.groupId ? `${item.groupId}` : "", - topicId: item?.topicId ? `${item.topicId}` : "", - eventId: item?.eventId ? `${item.eventId}` : "", - remark: item?.remark ? `${item.remark}` : "", - attendance: item?.attendance ? `${item.attendance}` : "", - attendanceDate: item?.attendanceDate ? `${item.attendanceDate}` : "", - latitude: item?.latitude ? item.latitude : 0, - longitude: item?.longitude ? item.longitude : 0, - image: item?.image ? `${item.image}` : "", - syncTime: item?.syncTime ? `${item.syncTime}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - - return new AttendanceDto(attendanceMapping); - }); - - return attendanceResponse; - } - - public async StudentMappedResponse(result: any) { - const studentResponse = result.map((item: any) => { - const studentMapping = { - studentId: item?.osid ? `${item.osid}` : "", - refId1: item?.admissionNo ? `${item.admissionNo}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - groupId: item?.groupId ? `${item.groupId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - studentEmail: item?.studentEmail ? `${item.studentEmail}` : "", - studentPhoneNumber: item?.studentPhoneNumber - ? item.studentPhoneNumber - : "", - iscwsn: item?.iscwsn ? `${item.iscwsn}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - religion: item?.religion ? `${item.religion}` : "", - singleGirl: item?.singleGirl ? item.singleGirl : "", - weight: item?.weight ? `${item.weight}` : "", - height: item?.height ? `${item.height}` : "", - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - homeless: item?.homeless ? item.homeless : "", - bpl: item?.bpl ? item.bpl : "", - migrant: item?.migrant ? item.migrant : "", - status: item?.status ? `${item.status}` : "", - - fatherFirstName: item?.fatherFirstName ? `${item.fatherFirstName}` : "", - - fatherMiddleName: item?.fatherMiddleName - ? `${item.fatherMiddleName}` - : "", - - fatherLastName: item?.fatherLastName ? `${item.fatherLastName}` : "", - fatherPhoneNumber: item?.fatherPhoneNumber - ? item.fatherPhoneNumber - : "", - fatherEmail: item?.fatherEmail ? `${item.fatherEmail}` : "", - - motherFirstName: item?.motherFirstName ? `${item.motherFirstName}` : "", - motherMiddleName: item?.motherMiddleName - ? `${item.motherMiddleName}` - : "", - motherLastName: item?.motherLastName ? `${item.motherLastName}` : "", - motherPhoneNumber: item?.motherPhoneNumber - ? item.motherPhoneNumber - : "", - motherEmail: item?.motherEmail ? `${item.motherEmail}` : "", - - guardianFirstName: item?.guardianFirstName - ? `${item.guardianFirstName}` - : "", - guardianMiddleName: item?.guardianMiddleName - ? `${item.guardianMiddleName}` - : "", - guardianLastName: item?.guardianLastName - ? `${item.guardianLastName}` - : "", - guardianPhoneNumber: item?.guardianPhoneNumber - ? item.guardianPhoneNumber - : "", - guardianEmail: item?.guardianEmail ? `${item.guardianEmail}` : "", - image: item?.image ? `${item.image}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - studentAddress: item?.studentAddress ? `${item.studentAddress}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new StudentDto(studentMapping); - }); - - return studentResponse; - } -} diff --git a/src/adapters/sunbirdrc/comment.adapter.ts b/src/adapters/sunbirdrc/comment.adapter.ts deleted file mode 100644 index cec0e14a..00000000 --- a/src/adapters/sunbirdrc/comment.adapter.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable, HttpException } from "@nestjs/common"; -import { AxiosResponse } from "axios"; -import { map } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { CommentDto } from "src/comment/dto/comment.dto"; -import { CommentSearchDto } from "src/comment/dto/comment-search.dto"; -import jwt_decode from "jwt-decode"; -import { IServicelocator } from "../commentservicelocator"; -export const SunbirdCommentToken = "SunbirdComment"; -@Injectable() -export class SunbirdCommentService implements IServicelocator { - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}/Comment`; - userUrl = `${process.env.BASEAPIURL}/User`; - - public async getComment(commentId: string, request: any) { - return this.httpService - .get(`${this.url}/${commentId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = [axiosResponse.data]; - - const commentDto = await this.mappedResponse(data); - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: commentDto[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async createComment(request: any, commentDto: CommentDto) { - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let axios = require("axios"); - let data = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let config = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - const result = response.data[0]; - commentDto.userId = result.osid; - - return this.httpService - .post(`${this.url}`, commentDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateComment( - commentId: string, - request: any, - commentDto: CommentDto - ) { - var axios = require("axios"); - var data = commentDto; - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let updateData = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let configData = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: updateData, - }; - const userResponse = await axios(configData); - const result = userResponse.data[0]; - commentDto.userId = result.osid; - - var config = { - method: "put", - url: `${this.url}/${commentId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchComment(request: any, commentSearchDto: CommentSearchDto) { - return this.httpService - .post(`${this.url}/search`, commentSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const commentDto = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: commentDto, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async mappedResponse(result: any) { - const commentResponse = result.map((obj: any) => { - const commentMapping = { - commentId: obj?.osid ? `${obj.osid}` : "", - contextId: obj?.contextId ? `${obj.contextId}` : "", - context: obj?.context ? `${obj.context}` : "", - userId: obj?.userId ? `${obj.userId}` : "", - comment: obj?.comment ? `${obj.comment}` : "", - privacy: obj?.privacy ? `${obj.privacy}` : "", - parentId: obj?.parentId ? `${obj.parentId}` : "", - status: obj?.status ? `${obj.status}` : "", - createdAt: obj?.osCreatedAt ? `${obj.osCreatedAt}` : "", - updatedAt: obj?.osUpdatedAt ? `${obj.osUpdatedAt}` : "", - createdBy: obj?.osCreatedBy ? `${obj.osCreatedBy}` : "", - updatedBy: obj?.osUpdatedBy ? `${obj.osUpdatedBy}` : "", - }; - return new CommentDto(commentMapping); - }); - - return commentResponse; - } -} diff --git a/src/adapters/sunbirdrc/config.adapter.ts b/src/adapters/sunbirdrc/config.adapter.ts deleted file mode 100644 index 5d1f7d7b..00000000 --- a/src/adapters/sunbirdrc/config.adapter.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable, HttpException } from "@nestjs/common"; -const resolvePath = require("object-resolve-path"); -import { AxiosResponse } from "axios"; -import { ConfigDto } from "src/configs/dto/config.dto"; -import { first, map, Observable } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import jwt_decode from "jwt-decode"; -import { UserDto } from "../../user/dto/user.dto"; -import { IServicelocator } from "../configservicelocator"; -export const SunbirdConfigToken = "SunbirdConfig"; -@Injectable() -export class SunbirdConfigService implements IServicelocator { - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}config`; - - public async createConfig(request: any, configDto: ConfigDto) { - let axios = require("axios"); - let data = { - filters: { - module: { - eq: `${configDto.module}`, - }, - key: { - eq: `${configDto.key}`, - }, - }, - }; - - let config = { - method: "post", - url: `${this.url}/search`, - - data: data, - }; - - const response = await axios(config); - let resData = response?.data; - let result = await this.mappedResponse(resData); - let configId = result.map(function (ConfigDto) { - return ConfigDto.configId; - }); - - if (resData.length > 0) { - var udateData = configDto; - var updateConfig = { - method: "put", - url: `${this.url}/${configId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: udateData, - }; - const response = await axios(updateConfig); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } else { - var createData = configDto; - var createConfig = { - method: "post", - url: `${this.url}`, - headers: { - Authorization: request.headers.authorization, - }, - data: createData, - }; - - const response = await axios(createConfig); - - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - } - - public async getConfig(request: any) { - let axios = require("axios"); - let data = { - filters: {}, - }; - let globalConfig = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - - const globalConfigData = await axios(globalConfig); - let gobalConfigResult = await this.mappedResponse( - globalConfigData?.data && globalConfigData.data - ); - // get Logged In user data - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let teacherData = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let config = { - method: "post", - url: `${process.env.BASEAPIURL}/User/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: teacherData, - }; - const response = await axios(config); - - let teacherProfileData = await this.userMappedResponse( - response?.data && response.data - ); - - let schoolId = teacherProfileData.map(function (UserDto) { - return UserDto.schoolId; - }); - - let teacherConfig = { - filters: { - contextId: { - eq: `${schoolId}`, - }, - }, - }; - - let final = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: teacherConfig, - }; - const confifResponse = await axios(final); - - let overridenResult = await this.mappedResponse( - confifResponse?.data && confifResponse.data - ); - var result = gobalConfigResult.filter((obj) => obj.contextId == ""); - - for (let i = 0; i < result.length; i++) { - let overridenData = overridenResult.filter( - (obj) => obj.key == result[i].key && obj.module == result[i].module - ); - if (overridenData.length > 0) { - result[i] = overridenData[0]; - } - } - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: result, - }); - } - - public async createModuleConfigs(request: any, configAllData: [Object]) { - configAllData.forEach((element) => { - element["data"].forEach((data) => { - data["module"] = element["module"]; - data["context"] = element["context"] ? element["context"] : ""; - data["contextId"] = element["contextId"] ? element["contextId"] : ""; - data["key"] = data["key"] ? data["key"] : ""; - data["value"] = data["value"] ? data["value"] : []; - data["isPublic"] = data["isPublic"] ? data["isPublic"] : true; - data["canOverride"] = data["canOverride"] ? data["canOverride"] : true; - data["overrideBy"] = data["overrideBy"] ? data["overrideBy"] : ""; - - this.createConfig(request, data); - }); - }); - } - - public async mappedResponse(result: any) { - const configResponse = result.map((item: any) => { - const configMapping = { - configId: item?.osid ? `${item.osid}` : "", - module: item?.module ? `${item.module}` : "", - key: item?.key ? `${item.key}` : "", - value: item?.value, - context: item?.context ? `${item.context}` : "", - contextId: item?.contextId ? `${item.contextId}` : "", - canOverride: item?.canOverride, - overrideBy: item?.overrideBy ? `${item.overrideBy}` : "", - isPublic: item?.isPublic, - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new ConfigDto(configMapping); - }); - - return configResponse; - } - - public async userMappedResponse(result: any) { - const userResponse = result.map((item: any) => { - const userMapping = { - userId: item?.osid ? `${item.osid}` : "", - refId1: item?.refId1 ? `${item.refId1}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - refId3: item?.refId3 ? `${item.refId3}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - phoneNumber: item?.phoneNumber ? `${item.phoneNumber}` : "", - email: item?.email ? `${item.email}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - designation: item?.designation ? `${item.designation}` : "", - cadre: item?.cadre ? `${item.cadre}` : "", - profQualification: item?.profQualification - ? `${item.profQualification}` - : "", - joiningDate: item?.joiningDate ? `${item.joiningDate}` : "", - subjectIds: item.subjectIds ? item.subjectIds : [], - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - maritalStatus: item?.maritalStatus ? `${item.maritalStatus}` : "", - compSkills: item?.compSkills ? `${item.compSkills}` : "", - disability: item?.disability ? `${item.disability}` : "", - religion: item?.religion ? `${item.religion}` : "", - homeDistance: item?.homeDistance ? `${item.homeDistance}` : "", - employmentType: item?.employmentType ? `${item.employmentType}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - address: item?.address ? `${item.address}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - image: item?.image ? `${item.image}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - reportsTo: item?.reportsTo ? `${item.reportsTo}` : "", - retirementDate: item?.retirementDate ? `${item.retirementDate}` : "", - workingStatus: item?.workingStatus ? `${item.workingStatus}` : "", - fcmToken: item?.fcmToken ? `${item.fcmToken}` : "", - role: item?.role ? `${item.role}` : "", - employeeCode: item?.employeeCode ? `${item.employeeCode}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new UserDto(userMapping); - }); - - return userResponse; - } -} diff --git a/src/adapters/sunbirdrc/group.adapter.ts b/src/adapters/sunbirdrc/group.adapter.ts deleted file mode 100644 index 457b42e3..00000000 --- a/src/adapters/sunbirdrc/group.adapter.ts +++ /dev/null @@ -1,431 +0,0 @@ -import { Injectable, HttpException } from "@nestjs/common"; -import { GroupInterface } from "../../group/interfaces/group.interface"; -import { HttpService } from "@nestjs/axios"; -import { AxiosResponse } from "axios"; -import { first, map, Observable } from "rxjs"; -import { response } from "express"; -import { SuccessResponse } from "src/success-response"; -const resolvePath = require("object-resolve-path"); -import { GroupDto } from "src/group/dto/group.dto"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { GroupSearchDto } from "src/group/dto/group-search.dto"; -import { IServicelocatorgroup } from "../groupservicelocator"; -import { StudentDto } from "src/student/dto/student.dto"; -import { UserDto } from "src/user/dto/user.dto"; -export const SunbirdGroupToken = "SunbirdGroup"; -@Injectable() -export class SunbirdGroupService implements IServicelocatorgroup { - private group: GroupInterface; - - constructor(private httpService: HttpService) {} - - url = `${process.env.BASEAPIURL}`; - - public async getGroup(groupId: any, request: any) { - return this.httpService - .get(`${this.url}/Class/${groupId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = axiosResponse.data; - const groupDto = [data]; - const groupResponse = await this.mappedResponse(groupDto); - return new SuccessResponse({ - statusCode: 200, - message: "Ok..", - data: groupResponse[0], - }); - }) - ); - } - - public async createGroup(request: any, groupDto: GroupDto) { - return this.httpService - .post(`${this.url}/Class`, groupDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async updateGroup(groupId: string, request: any, groupDto: GroupDto) { - var axios = require("axios"); - var data = groupDto; - - var config = { - method: "put", - url: `${this.url}/Class/${groupId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchGroup(request: any, groupSearchDto: GroupSearchDto) { - return this.httpService - .post(`${this.url}/Class/search`, groupSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const groupResponse = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: groupResponse, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async findMembersOfGroup(id: string, role: string, request: any) { - if (role == "Student") { - let axios = require("axios"); - let data = { - filters: { - currentClassId: { - eq: `${id}`, - }, - }, - }; - - let config = { - method: "post", - url: `${this.url}/Student/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - - const response = await axios(config); - let result = await this.StudentMappedResponse( - response?.data && response.data - ); - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: result, - }); - } else if (role == "Teacher") { - let axios = require("axios"); - - let final = { - method: "get", - url: `${this.url}/Class/${id}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const response = await axios(final); - let classObj = response?.data; - let resData = []; - if (classObj?.teacherId) { - let classFinal = { - method: "get", - url: `${this.url}/User/${classObj.teacherId}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const responseData = await axios(classFinal); - - let response = await this.userMappedResponse([responseData.data]); - resData = response; - } - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: resData, - }); - } else { - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: { msg: "Unable to get data !!" }, - }); - } - } - - public async findGroupsByUserId(id: string, role: string, request: any) { - let responseData = []; - - if (role === "Teacher") { - let axios = require("axios"); - let data = { - filters: { - teacherId: { - eq: `${id}`, - }, - }, - }; - - let final = { - method: "post", - url: `${this.url}/Class/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - - const response = await axios(final); - responseData = response.data; - } else if (role === "Student") { - let axios = require("axios"); - const config = { - method: "get", - url: `${this.url}/Student/${id}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const response = await axios(config); - let studentObj = response?.data; - - if (studentObj?.groupId) { - let studentFinal = { - method: "get", - url: `${this.url}/Class/${studentObj.groupId}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - const resData = await axios(studentFinal); - - responseData = resData?.data ? [resData.data] : []; - } - } - - const groupResponse = await this.mappedResponse(responseData); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: groupResponse, - }); - } - public async findMembersOfChildGroup( - groupId: string, - role: string, - request: any - ) {} - - public async mappedResponse(result: any) { - const groupResponse = result.map((item: any) => { - const groupMapping = { - groupId: item?.osid ? `${item.osid}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - name: item?.name ? `${item.name}` : "", - type: item?.type ? `${item.type}` : "", - section: item?.section ? `${item.section}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - mediumOfInstruction: item?.mediumOfInstruction - ? `${item.mediumOfInstruction}` - : "", - teacherId: item?.teacherId ? `${item.teacherId}` : "", - parentId: item?.parentId ? `${item.parentId}` : "", - image: item?.image ? `${item.image}` : "", - metaData: item?.metaData ? item.metaData : [], - option: item?.option ? item.option : [], - gradeLevel: item?.gradeLevel ? `${item.gradeLevel}` : "", - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new GroupDto(groupMapping); - }); - - return groupResponse; - } - public async StudentMappedResponse(result: any) { - const studentResponse = result.map((item: any) => { - const studentMapping = { - studentId: item?.osid ? `${item.osid}` : "", - refId1: item?.admissionNo ? `${item.admissionNo}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - groupId: item?.groupId ? `${item.groupId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - studentEmail: item?.studentEmail ? `${item.studentEmail}` : "", - studentPhoneNumber: item?.studentPhoneNumber - ? item.studentPhoneNumber - : "", - iscwsn: item?.iscwsn ? `${item.iscwsn}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - religion: item?.religion ? `${item.religion}` : "", - singleGirl: item?.singleGirl ? item.singleGirl : "", - weight: item?.weight ? `${item.weight}` : "", - height: item?.height ? `${item.height}` : "", - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - homeless: item?.homeless ? item.homeless : "", - bpl: item?.bpl ? item.bpl : "", - migrant: item?.migrant ? item.migrant : "", - status: item?.status ? `${item.status}` : "", - - fatherFirstName: item?.fatherFirstName ? `${item.fatherFirstName}` : "", - - fatherMiddleName: item?.fatherMiddleName - ? `${item.fatherMiddleName}` - : "", - - fatherLastName: item?.fatherLastName ? `${item.fatherLastName}` : "", - fatherPhoneNumber: item?.fatherPhoneNumber - ? item.fatherPhoneNumber - : "", - fatherEmail: item?.fatherEmail ? `${item.fatherEmail}` : "", - - motherFirstName: item?.motherFirstName ? `${item.motherFirstName}` : "", - motherMiddleName: item?.motherMiddleName - ? `${item.motherMiddleName}` - : "", - motherLastName: item?.motherLastName ? `${item.motherLastName}` : "", - motherPhoneNumber: item?.motherPhoneNumber - ? item.motherPhoneNumber - : "", - motherEmail: item?.motherEmail ? `${item.motherEmail}` : "", - - guardianFirstName: item?.guardianFirstName - ? `${item.guardianFirstName}` - : "", - guardianMiddleName: item?.guardianMiddleName - ? `${item.guardianMiddleName}` - : "", - guardianLastName: item?.guardianLastName - ? `${item.guardianLastName}` - : "", - guardianPhoneNumber: item?.guardianPhoneNumber - ? item.guardianPhoneNumber - : "", - guardianEmail: item?.guardianEmail ? `${item.guardianEmail}` : "", - image: item?.image ? `${item.image}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - studentAddress: item?.studentAddress ? `${item.studentAddress}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new StudentDto(studentMapping); - }); - - return studentResponse; - } - - public async userMappedResponse(result: any) { - const userResponse = result.map((item: any) => { - const userMapping = { - userId: item?.osid ? `${item.osid}` : "", - refId1: item?.refId1 ? `${item.refId1}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - refId3: item?.refId3 ? `${item.refId3}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - phoneNumber: item?.phoneNumber ? `${item.phoneNumber}` : "", - email: item?.email ? `${item.email}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - designation: item?.designation ? `${item.designation}` : "", - cadre: item?.cadre ? `${item.cadre}` : "", - profQualification: item?.profQualification - ? `${item.profQualification}` - : "", - joiningDate: item?.joiningDate ? `${item.joiningDate}` : "", - subjectIds: item.subjectIds ? item.subjectIds : [], - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - maritalStatus: item?.maritalStatus ? `${item.maritalStatus}` : "", - compSkills: item?.compSkills ? `${item.compSkills}` : "", - disability: item?.disability ? `${item.disability}` : "", - religion: item?.religion ? `${item.religion}` : "", - homeDistance: item?.homeDistance ? `${item.homeDistance}` : "", - employmentType: item?.employmentType ? `${item.employmentType}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - address: item?.address ? `${item.address}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - image: item?.image ? `${item.image}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - reportsTo: item?.reportsTo ? `${item.reportsTo}` : "", - retirementDate: item?.retirementDate ? `${item.retirementDate}` : "", - workingStatus: item?.workingStatus ? `${item.workingStatus}` : "", - fcmToken: item?.fcmToken ? `${item.fcmToken}` : "", - role: item?.role ? `${item.role}` : "", - employeeCode: item?.employeeCode ? `${item.employeeCode}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new UserDto(userMapping); - }); - - return userResponse; - } -} diff --git a/src/adapters/sunbirdrc/holiday.adapter.ts b/src/adapters/sunbirdrc/holiday.adapter.ts deleted file mode 100644 index edc5cfbe..00000000 --- a/src/adapters/sunbirdrc/holiday.adapter.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable, HttpException } from "@nestjs/common"; -const resolvePath = require("object-resolve-path"); -import { AxiosResponse } from "axios"; -import { HolidayDto } from "src/holiday/dto/holiday.dto"; -import { first, map, Observable } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { HolidaySearchDto } from "src/holiday/dto/holiday-search.dto"; -import { IServicelocator } from "../holidayservicelocator"; -export const SunbirdHolidayToken = "SunbirdHoliday"; -@Injectable() -export class SunbirdHolidayService implements IServicelocator { - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}/Holiday`; - - public async getHoliday(holidayId: string, request: any) { - return this.httpService - .get(`${this.url}/${holidayId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = [axiosResponse.data]; - const holidayData = await this.mappedResponse(data); - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: holidayData[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async createHoliday(request: any, holidayDto: HolidayDto) { - return this.httpService - .post(`${this.url}`, holidayDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateHoliday( - holidayId: string, - request: any, - holidayDto: HolidayDto - ) { - var axios = require("axios"); - var data = holidayDto; - - var config = { - method: "put", - url: `${this.url}/${holidayId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchHoliday(request: any, holidaySearchDto: HolidaySearchDto) { - return this.httpService - .post(`${this.url}/search`, holidaySearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const holidayData = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: holidayData, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async holidayFilter(fromDate: string, toDate: string, request: any) { - let axios = require("axios"); - let filters = { - fromDate, - toDate, - }; - const filterArray = Object.keys(filters).filter( - (value, key) => filters[value] && filters[value] !== "" - ); - let data = { date: { between: [] } }; - filterArray.forEach((value, key) => { - if (["fromDate", "toDate"].includes(value)) { - data["date"].between.push(filters[value]); - } - }); - - let config = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: { filters: data }, - }; - - const response = await axios(config); - - let result = response?.data && response.data; - const holidayData = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: holidayData, - }); - } - - public async mappedResponse(result: any) { - const holidayResponse = result.map((item: any) => { - const holidayMapping = { - holidayId: item?.osid ? `${item.osid}` : "", - date: item?.remark ? item.remark : "", - remark: item?.remark ? `${item.remark}` : "", - year: item?.year ? item.year : "", - context: item?.context ? `${item.context}` : "", - contextId: item?.contextId ? `${item.contextId}` : "", - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new HolidayDto(holidayMapping); - }); - - return holidayResponse; - } -} diff --git a/src/adapters/sunbirdrc/inAppNotification.adapter.ts b/src/adapters/sunbirdrc/inAppNotification.adapter.ts deleted file mode 100644 index a8f02dec..00000000 --- a/src/adapters/sunbirdrc/inAppNotification.adapter.ts +++ /dev/null @@ -1,250 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { GroupDto } from "src/group/dto/group.dto"; -import moment from "moment"; - -@Injectable() -export class InAppNotificationService { - constructor(private httpService: HttpService) {} - url = process.env.HISTORYAPIURL; - UCIURL = process.env.UCIAPI; - templaterURL = process.env.TEMPLATERURL; - groupURL = `${process.env.BASEAPIURL}/Class`; - public async userHistoryNotification( - userId: string, - provider: string, - startDate: string, - endDate: string, - request: any - ) { - var axios = require("axios"); - - var config = { - method: "get", - url: `${this.url}history?userId=${userId}&provider=${provider}&endDate=${endDate}&startDate=${startDate}`, - headers: {}, - }; - - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: response.data.result, - }); - } - - public async botHistoryNotification( - botId: string, - provider: string, - startDate: string, - endDate: string, - request: any - ) { - var axios = require("axios"); - - var config = { - method: "get", - url: `${this.url}history/dump?provider=${provider}&botId=${botId}&endDate=${endDate}&startDate=${startDate}`, - headers: {}, - }; - - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: response.data.result, - }); - } - - public async inAppNotification( - module: string, - groupId: string, - request: any, - templateId: string - ) { - try { - var axios = require("axios"); - const result = Math.random().toString(27).substring(1, 8); - var confi = { - method: "get", - url: `${this.templaterURL}${templateId}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const getContent = await axios(confi); - const contentData = getContent.data; - - // Conversation Logic - var conversationData = { - data: { - name: `Firebase Broadcast ${result}`, - transformers: [ - { - id: process.env.TRANSFORMERSID, - meta: { - body: contentData.body, - type: contentData.type, - params: ["name", "phoneNo"], - }, - type: "broadcast", - }, - ], - adapter: contentData.user, - }, - }; - - const conversation = await axios.post( - `${this.UCIURL}/conversationLogic/create`, - conversationData, - { - headers: { - "admin-token": process.env.UCIADMINTOKEN, - "Content-Type": "application/json", - }, - } - ); - - const resData = conversation.data; - const consversationLogicID = resData.result.data.id; - - var data = { - filters: { - osid: { - eq: groupId, - }, - }, - }; - - const responseData = await axios.post(`${this.groupURL}/search`, data, { - headers: { - Authorization: request.headers.authorization, - }, - }); - - const dtoResponse = await this.GroupMappedResponse(responseData.data); - - const filterObj = dtoResponse.filter((e: any) => e); - let option = filterObj[0].option; - let optionStr = JSON.stringify(option); - var jsonObj = JSON.parse(optionStr); - let params = JSON.parse(jsonObj); - - var botData = { - data: { - startingMessage: `Hi Shiksha Firebase Broadcast ${result}`, - name: `Shiksha Firebase Broadcast ${result}`, - users: [params.inAppNotification.teacherSegment], - logic: [consversationLogicID], - status: "enabled", - startDate: moment().format("Y-MM-DD"), - endDate: moment().format("Y-MM-DD"), - }, - }; - - const botResponse = await axios.post( - `${this.UCIURL}/bot/create`, - botData, - { - headers: { - "admin-token": process.env.UCIADMINTOKEN, - "Content-Type": "application/json", - }, - } - ); - - const botResData = botResponse.data; - const botCreateID = botResData.result.data.id; - - var configs = { - method: "get", - url: `${process.env.BOTCALL}${botCreateID}`, - headers: {}, - }; - - const botres = await axios(configs); - - const sendData = botres.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: sendData, - }); - } catch (e) { - return { data: e.response.data }; - } - } - - public async readReceipt( - eventType: string, - externalId: string, - destAdd: string, - fcmDestAdd: string, - messageId: string, - text: string, - from: string, - request: any - ) { - var axios = require("axios"); - var data = { - text: text, - from: from, - messageId: messageId, - eventType: eventType, - report: { - externalId: externalId, - destAdd: destAdd, - fcmDestAdd: fcmDestAdd, - }, - }; - - var config = { - method: "post", - url: "http://139.59.14.252:9080/firebase/web", - headers: { - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: response.data, - }); - } - public async GroupMappedResponse(result: any) { - const groupResponse = result.map((item: any) => { - const groupMapping = { - groupId: item?.groupId ? `${item.groupId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - name: item?.name ? `${item.name}` : "", - type: item?.type ? `${item.type}` : "", - section: item?.section ? `${item.section}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - mediumOfInstruction: item?.mediumOfInstruction - ? `${item.mediumOfInstruction}` - : "", - teacherId: item?.teacherId ? `${item.teacherId}` : "", - parentId: item?.parentId ? `${item.parentId}` : "", - image: item?.image ? `${item.image}` : "", - metaData: item?.metaData ? item.metaData : [], - option: item?.option ? item.option : [], - gradeLevel: item?.gradeLevel ? `${item.gradeLevel}` : "", - createdAt: item?.created_at ? `${item.created_at}` : "", - updatedAt: item?.updated_at ? `${item.updated_at}` : "", - }; - return new GroupDto(groupMapping); - }); - - return groupResponse; - } -} diff --git a/src/adapters/sunbirdrc/lessonPlan.adapter.ts b/src/adapters/sunbirdrc/lessonPlan.adapter.ts deleted file mode 100644 index d31f62f2..00000000 --- a/src/adapters/sunbirdrc/lessonPlan.adapter.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable, HttpException } from "@nestjs/common"; -const resolvePath = require("object-resolve-path"); -import { AxiosResponse } from "axios"; -import { LessonPlanDto } from "src/lessonPlan/dto/lessonPlan.dto"; -import { map } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { LessonPlanSearchDto } from "src/lessonPlan/dto/lessonPlan.search.dto"; -@Injectable() -export class LessonPlanService { - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}/Content`; - - public async getLessonPlan(lessonPlanId: string, request: any) { - return this.httpService - .get(`${this.url}/${lessonPlanId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = [axiosResponse.data]; - const lessonPlanDto = await this.mappedResponse(data); - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: lessonPlanDto[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async createLessonPlan(request: any, lessonPlanDto: LessonPlanDto) { - return this.httpService - .post(`${this.url}`, lessonPlanDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateLessonPlan( - lessonPlanId: string, - request: any, - lessonPlanDto: LessonPlanDto - ) { - var axios = require("axios"); - var data = lessonPlanDto; - - var config = { - method: "put", - url: `${this.url}/${lessonPlanId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchLessonPlan( - request: any, - lessonPlanSearchDto: LessonPlanSearchDto - ) { - return this.httpService - .post(`${this.url}/search`, lessonPlanSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = await this.mappedResponse(response.data); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: responsedata, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async mappedResponse(result: any) { - const lessonPlanResponse = result.map((obj: any) => { - const lessonPlanMapping = { - contentId: obj?.osid ? `${obj.osid}` : "", - name: `${obj.name}`, - code: obj?.code ? `${obj.code}` : "", - status: obj?.status ? `${obj.status}` : "", - channel: obj?.channel ? `${obj.channel}` : "", - mediaType: obj?.mediaType ? `${obj.mediaType}` : "", - compatibilityLevel: obj?.compatibilityLevel - ? `${obj.compatibilityLevel}` - : "", - audience: obj?.audience ? obj.audience : [], - posterImage: obj?.posterImage ? `${obj.posterImage}` : "", - duration: obj?.duration ? `${obj.duration}` : "", - downloadUrl: obj?.downloadUrl ? `${obj.downloadUrl}` : "", - previewUrl: obj?.previewUrl ? `${obj.previewUrl}` : "", - author: obj?.author ? `${obj.author}` : "", - languageCode: obj?.languageCode ? obj.languageCode : [], - language: obj?.language ? obj.language : [], - ageGroup: obj?.ageGroup ? obj.ageGroup : [], - contentType: obj?.contentType ? `${obj.contentType}` : "", - category: obj?.category ? obj.category : [], - teachingMode: obj?.teachingMode ? `${obj.teachingMode}` : "", - skills: obj?.skills ? obj.skills : [], - keywords: obj?.keywords ? obj.keywords : [], - description: obj?.osid ? `${obj.osid}` : "", - instructions: obj?.osid ? `${obj.osid}` : "", - body: obj?.body ? obj.body : "", - learningObjective: obj?.learningObjective ? obj.learningObjective : [], - creator: obj?.creator ? `${obj.creator}` : "", - reviewer: obj?.reviewer ? `${obj.reviewer}` : "", - lastSubmittedBy: obj?.lastSubmittedBy ? `${obj.lastSubmittedBy}` : "", - lastSubmittedOn: obj?.lastSubmittedOn ? `${obj.lastSubmittedOn}` : "", - lastPublishedBy: obj?.lastPublishedBy ? `${obj.lastPublishedBy}` : "", - lastPublishedOn: obj?.astPublishedOn ? `${obj.astPublishedOn}` : "", - subject: obj?.subject ? obj.subject : [], - questionCategories: obj?.questionCategories - ? obj.questionCategories - : [], - medium: obj?.medium ? obj.medium : [], - gradeLevel: obj?.gradeLevel ? obj.gradeLevel : [], - topic: obj?.topic ? obj.topic : [], - subjectCodes: obj?.subjectCodes ? obj.subjectCodes : [], - difficultyLevel: obj?.difficultyLevel ? `${obj.difficultyLevel}` : "", - board: obj?.board ? `${obj.board}` : "", - primaryCategory: obj?.primaryCategory ? `${obj.primaryCategory}` : "", - accessibility: obj?.accessibility ? obj.accessibility : [], - createdAt: obj?.osCreatedAt ? `${obj.osCreatedAt}` : "", - updatedAt: obj?.osUpdatedAt ? `${obj.osUpdatedAt}` : "", - createdBy: obj?.osCreatedBy ? `${obj.osCreatedBy}` : "", - updatedBy: obj?.osUpdatedBy ? `${obj.osUpdatedBy}` : "", - }; - return new LessonPlanDto(lessonPlanMapping); - }); - - return lessonPlanResponse; - } -} diff --git a/src/adapters/sunbirdrc/like.adapter.ts b/src/adapters/sunbirdrc/like.adapter.ts deleted file mode 100644 index 18c86965..00000000 --- a/src/adapters/sunbirdrc/like.adapter.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable, HttpException } from "@nestjs/common"; -import { AxiosResponse } from "axios"; -import { map } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { LikeDto } from "src/like/dto/like.dto"; -import { LikeSearchDto } from "src/like/dto/like-search.dto"; -import jwt_decode from "jwt-decode"; -import { IServicelocator } from "../likeservicelocator"; -export const SunbirdLikeToken = "SunbirdLike"; -@Injectable() -export class SunbirdLikeService implements IServicelocator { - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}/Like`; - userUrl = `${process.env.BASEAPIURL}/User`; - - public async getLike(likeId: string, request: any) { - return this.httpService - .get(`${this.url}/${likeId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = [axiosResponse.data]; - const likeDto = await this.mappedResponse(data); - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: likeDto[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async createLike(request: any, likeDto: LikeDto) { - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let axios = require("axios"); - let data = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let config = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - const result = response.data[0]; - likeDto.userId = result.osid; - return this.httpService - .post(`${this.url}`, likeDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateLike(likeId: string, request: any, likeDto: LikeDto) { - var axios = require("axios"); - var data = likeDto; - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let updateData = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let configData = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: updateData, - }; - const userResponse = await axios(configData); - const result = userResponse.data[0]; - data.userId = result.osid; - - var config = { - method: "put", - url: `${this.url}/${likeId}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchLike(request: any, likeSearchDto: LikeSearchDto) { - return this.httpService - .post(`${this.url}/search`, likeSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const likeDto = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: likeDto, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async getCountLike(contextId: string, context: string, request: any) { - let axios = require("axios"); - let data = { - filters: { - contextId: { - eq: `${contextId}`, - }, - context: { - eq: `${context}`, - }, - }, - }; - - let config = { - method: "post", - url: `${this.url}/search`, - - data: data, - }; - - const response = await axios(config); - let resData = response?.data; - const likeDto = await this.mappedResponse(resData); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: likeDto.length, - }); - } - - public async deleteLike(likeId: string, request: any) { - return this.httpService - .delete(`${this.url}/${likeId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - let data = axiosResponse.data; - - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async mappedResponse(result: any) { - const likeResponse = result.map((obj: any) => { - const likeMapping = { - likeId: obj?.osid ? `${obj.osid}` : "", - contextId: obj?.contextId ? `${obj.contextId}` : "", - context: obj?.context ? `${obj.context}` : "", - userId: obj?.userId ? `${obj.userId}` : "", - type: obj?.type ? `${obj.type}` : "", - createdAt: obj?.osCreatedAt ? `${obj.osCreatedAt}` : "", - updatedAt: obj?.osUpdatedAt ? `${obj.osUpdatedAt}` : "", - createdBy: obj?.osCreatedBy ? `${obj.osCreatedBy}` : "", - updatedBy: obj?.osUpdatedBy ? `${obj.osUpdatedBy}` : "", - }; - return new LikeDto(likeMapping); - }); - - return likeResponse; - } -} diff --git a/src/adapters/sunbirdrc/notification.adapter.ts b/src/adapters/sunbirdrc/notification.adapter.ts deleted file mode 100644 index 2dd05ad1..00000000 --- a/src/adapters/sunbirdrc/notification.adapter.ts +++ /dev/null @@ -1,618 +0,0 @@ -import { Injectable, HttpException, Param } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import axios, { AxiosResponse } from "axios"; -import { map } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError, takeLast } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { NotificationLogDto } from "src/notification/dto/notification.dto"; -import { NotificationSearchDto } from "src/notification/dto/notification-search.dto"; -import moment from "moment"; -import { GroupDto } from "src/group/dto/group.dto"; -import { CronJob } from "cron"; -import { SchedulerRegistry } from "@nestjs/schedule"; -import jwt_decode from "jwt-decode"; - -@Injectable() -export class NotificationService { - constructor( - private httpService: HttpService, - private schedulerRegistry: SchedulerRegistry - ) {} - baseURL = `${process.env.BASEAPIURL}`; - UCIURL = `${process.env.UCIAPI}`; - url = process.env.TEMPLATERURL; - groupURL = `${process.env.BASEAPIURL}/Class`; - - public async instantSendNotification( - module: any, - eventTrigger: string, - templateId: string, - senderId: string, - groupId: string, - channel: string, - request: any - ) { - try { - var axios = require("axios"); - const result = Math.random().toString(27).substring(1, 8); - var confi = { - method: "get", - url: `${this.url}${templateId}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const getContent = await axios(confi); - const contentData = getContent.data; - - var data = { - filters: { - osid: { - eq: groupId, - }, - }, - }; - - const responseData = await axios.post(`${this.groupURL}/search`, data, { - headers: { - Authorization: request.headers.authorization, - }, - }); - - const dtoResponse = await this.groupResponse(responseData.data); - const filterObj = dtoResponse.filter((e: any) => e); - let option = filterObj[0].option; - let optionStr = JSON.stringify(option); - var jsonObj = JSON.parse(optionStr); - let params = JSON.parse(jsonObj); - var notificationModule = params.filter( - (obj: any) => obj.module === module - ); - const triggers = notificationModule[0].eventTriggers; - var notificationTrigger = triggers.filter( - (obj: any) => obj.name === eventTrigger - ); - let botIdChecked = notificationTrigger[0].botId; - - let botCreateID: any; - - if (botIdChecked.length > 0) { - botCreateID = notificationTrigger[0].botId; - } else { - // Conversation Logic - var conversationData = { - data: { - name: `Shiksha ${channel} Broadcast ${result}`, - transformers: [ - { - id: process.env.TRANSFORMERSID, - meta: { - body: contentData.body, - type: contentData.type, - user: process.env.TRANSFORMERSUSER, - }, - type: "broadcast", - }, - ], - adapter: contentData.user, - }, - }; - - const conversation = await axios.post( - `${this.UCIURL}/conversationLogic/create`, - conversationData, - { - headers: { - "admin-token": process.env.UCIADMINTOKEN, - "Content-Type": "application/json", - }, - } - ); - - const resData = conversation.data; - const consversationLogicID = resData.result.data.id; - - var botData = { - data: { - startingMessage: `Hi Shiksha ${channel} Broadcast ${result}`, - name: `Shiksha Notification Broadcast ${result}`, - users: [notificationTrigger[0].userSegment], - logic: [consversationLogicID], - status: "enabled", - startDate: moment().format("Y-MM-DD"), - endDate: moment().format("Y-MM-DD"), - }, - }; - - const botResponse = await axios.post( - `${this.UCIURL}/bot/create`, - botData, - { - headers: { - "admin-token": process.env.UCIADMINTOKEN, - "Content-Type": "application/json", - }, - } - ); - - const botResData = botResponse.data; - botCreateID = botResData.result.data.id; - } - - var configs = { - method: "get", - url: `${process.env.BOTCALL}${botCreateID}`, - headers: {}, - }; - - const botres = await axios(configs); - - const sendData = botres.data; - // Notification Log - - var notificationData = { - medium: channel, - templateId: templateId, - recepients: [notificationTrigger[0].userSegment], - sentDate: new Date(), - sentBy: senderId, - module: notificationModule[0].module, - options: "", - content: contentData.body, - }; - - const logRes = await axios.post( - `${this.baseURL}Notificationlog`, - notificationData, - { - headers: { - Authorization: request.headers.authorization, - }, - } - ); - const logResponse = logRes.data; - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: logResponse, - }); - } catch (e) { - return e.response.data; - } - } - - //Notificationschedule - public async scheduleSendNotification( - module: any, - eventTrigger: string, - templateId: string, - senderId: string, - groupId: string, - channel: string, - month: string, - date: string, - hours: string, - minutes: String, - jobName: string, - request: any - ) { - try { - var axios = require("axios"); - - //content data api - var confi = { - method: "get", - url: `${this.url}${templateId}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - const getContent = await axios(confi); - const contentData = getContent.data; - - //params data - var axios = require("axios"); - var data = { - filters: { - osid: { - eq: groupId, - }, - }, - }; - - var getSegment = { - method: "post", - url: `${this.groupURL}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const responseData = await axios(getSegment); - - const dtoResponse = await this.groupResponse(responseData.data); - - const filterObj = dtoResponse.filter((e: any) => e); - - let option = filterObj[0].option; - - let optionStr = JSON.stringify(option); - var jsonObj = JSON.parse(optionStr); - let params = JSON.parse(jsonObj); - var notificationModule = params.filter( - (obj: any) => obj.module === module - ); - const triggers = notificationModule[0].eventTriggers; - var notificationTrigger = triggers.filter( - (obj: any) => obj.name === eventTrigger - ); - let botIdChecked = notificationTrigger[0].botId; - let botCreateID: any; - - //save notification - let notificationScheduleData = { - medium: channel, - templateId: templateId, - recepients: [notificationTrigger[0].userSegment], - sentDate: date, - sentBy: senderId, - module: notificationModule[0].module, - options: "", - content: contentData.body, - scheduleDate: date, - hours, - minutes, - month, - }; - - var logConfig = { - method: "post", - url: `${this.baseURL}Notificationschedule`, - headers: { - Authorization: request.headers.authorization, - }, - data: notificationScheduleData, - }; - - const logRes = await axios(logConfig); - const logResponse = logRes.data; - - //cronJob logic - - let osid = logResponse.result.Notificationschedule.osid; - - var yy = date.slice(0, 4); - let year = parseInt(yy); - - var dd = date.slice(-2); - let d = parseInt(dd); - - var mm = date.slice(5, 7); - let mon = parseInt(mm); - mon = mon - 1; - - let hrs = parseInt(hours); - let mins = +minutes; - - let ist = new Date(year, mon, d, hrs, mins); - let utc = moment.utc(ist).format("YYYY-MM-DD HH:mm:ss "); - let utcMin = utc.slice(14, 16); - let utcHrs = utc.slice(11, 13); - let utcDay = utc.slice(8, 11); - let utcMon = utc.slice(5, 7); - const job = new CronJob( - // `0 ${utcMin} ${utcHrs} ${utcDay} ${utcMon} *`, - `0 ${mins} ${hrs} ${d} ${mon} *`, - async () => { - try { - var axios = require("axios"); - const result = Math.random().toString(27).substring(1, 8); - - if (botIdChecked.length > 0) { - botCreateID = notificationTrigger[0].botId; - } else { - // Conversation Logic - var conversationData = { - data: { - name: `Shiksha ${channel} Broadcast ${result}`, - transformers: [ - { - id: process.env.TRANSFORMERSID, - meta: { - body: contentData.body, - type: contentData.type, - user: process.env.TRANSFORMERSUSER, - }, - type: "broadcast", - }, - ], - adapter: contentData.user, - }, - }; - - const conversation = await axios.post( - `${this.UCIURL}/conversationLogic/create`, - conversationData, - { - headers: { - "admin-token": process.env.UCIADMINTOKEN, - "Content-Type": "application/json", - }, - } - ); - - const resData = conversation.data; - const consversationLogicID = resData.result.data.id; - - var botData = { - data: { - startingMessage: `Hi Shiksha ${channel} Broadcast ${result}`, - name: `Shiksha Notification Broadcast ${result}`, - users: [notificationTrigger[0].userSegment], - logic: [consversationLogicID], - status: "enabled", - startDate: moment().format("Y-MM-DD"), - endDate: moment().format("Y-MM-DD"), - }, - }; - - const botResponse = await axios.post( - `${this.UCIURL}/bot/create`, - botData, - { - headers: { - "admin-token": process.env.UCIADMINTOKEN, - "Content-Type": "application/json", - }, - } - ); - - const botResData = botResponse.data; - botCreateID = botResData.result.data.id; - } - - var configs = { - method: "get", - url: `${process.env.BOTCALL}${botCreateID}`, - headers: {}, - }; - const botres = await axios(configs); - - const sendData = botres.data; - // Notification Log - - var notificationData = { - medium: channel, - templateId: templateId, - recepients: [notificationTrigger[0].userSegment], - sentDate: date, - sentBy: senderId, - module: module, - options: "", - content: contentData.body, - scheduleDate: date, - hours, - minutes, - month, - }; - const logRes = await axios.post( - `${this.baseURL}Notificationlog`, - notificationData, - { - headers: { - Authorization: request.headers.authorization, - }, - } - ); - const logResponse = logRes.data; - - var deleteCron = { - method: "delete", - url: `${this.baseURL}Notificationschedule/${osid}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - const deletedNotification = await axios(deleteCron); - - job.stop(); - } catch (e) { - return e.response.data; - } - } - ); - - this.schedulerRegistry.addCronJob(jobName, job); - job.start(); - - return `SMS set for EOD at ${hours}:${minutes} `; - } catch (e) { - return `${e}`; - } - } - - public async getNotification(notificationId: string, request: any) { - return this.httpService - .get(`${this.baseURL}/Notificationlog/${notificationId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let notificationData = [axiosResponse.data]; - const NotificationLogDto = await this.notificationLog( - notificationData - ); - - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: NotificationLogDto[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async searchNotification( - request: any, - notificationSearchDto: NotificationSearchDto - ) { - return this.httpService - .post(`${this.baseURL}/Notificationlog/search`, notificationSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = await this.notificationLog(response.data); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: responsedata, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - //schedule - public async searchSchedulehNotification( - request: any, - notificationSearchDto: NotificationSearchDto - ) { - return this.httpService - .post( - `${this.baseURL}/Notificationschedule/search`, - notificationSearchDto, - { - headers: { - Authorization: request.headers.authorization, - }, - } - ) - .pipe( - map(async (response) => { - const responsedata = await this.notificationLog(response.data); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: responsedata, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async getScheduleNotification( - ScheduleNotificationid: string, - request: any - ) { - return this.httpService - .get(`${this.baseURL}/Notificationschedule/${ScheduleNotificationid}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let scheduleNotificationData = [axiosResponse.data]; - const responsedata = await this.notificationLog( - scheduleNotificationData - ); - - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: responsedata[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async notificationLog(result: any) { - const notificationLog = result.map((item: any) => { - const notificationLogMapping = { - notificationLogId: item?.osid ? `${item.osid}` : "", - content: item?.content ? `${item.content}` : "", - recepients: item?.recepients ? item.recepients : [], - module: item?.module ? `${item.module}` : "", - templateContentId: item?.templateContentId - ? `${item.templateContentId}` - : "", - templateId: item?.templateId ? `${item.templateId}` : "", - medium: item?.medium ? `${item.medium}` : "", - sentDate: item?.sentDate ? `${item.sentDate}` : "", - sentBy: item?.sentBy ? `${item.sentBy}` : "", - scheduleDate: item?.scheduleDate ? `${item.scheduleDate}` : "", - options: item?.options ? item.options : "", - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new NotificationLogDto(notificationLogMapping); - }); - - return notificationLog; - } - public async groupResponse(result: any) { - const groupResponse = result.map((item: any) => { - const groupMapping = { - groupId: item?.osid ? `${item.osid}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - name: item?.name ? `${item.name}` : "", - type: item?.type ? `${item.type}` : "", - section: item?.section ? `${item.section}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - mediumOfInstruction: item?.mediumOfInstruction - ? `${item.mediumOfInstruction}` - : "", - teacherId: item?.teacherId ? `${item.teacherId}` : "", - parentId: item?.parentId ? `${item.parentId}` : "", - image: item?.image ? `${item.image}` : "", - metaData: item?.metaData ? item.metaData : [], - option: item?.option ? item.option : [], - gradeLevel: item?.gradeLevel ? `${item.gradeLevel}` : "", - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new GroupDto(groupMapping); - }); - - return groupResponse; - } -} diff --git a/src/adapters/sunbirdrc/school.adapter.ts b/src/adapters/sunbirdrc/school.adapter.ts deleted file mode 100644 index 2e73cf31..00000000 --- a/src/adapters/sunbirdrc/school.adapter.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { HttpException, Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { AxiosResponse } from "axios"; -import { catchError, map } from "rxjs"; -import { SchoolDto } from "src/school/dto/school.dto"; -import { SchoolSearchDto } from "src/school/dto/school-search.dto"; -import { SuccessResponse } from "src/success-response"; -import { ErrorResponse } from "src/error-response"; -import { IServicelocator } from "../schoolservicelocator"; -export const SunbirdSchoolToken = "SunbirdSchool"; -@Injectable() -export class SchoolService implements IServicelocator { - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}/School`; - - public async getSchool(id: any, request: any) { - return this.httpService - .get(`${this.url}/${id}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - const data = axiosResponse.data; - const schoolDto = await this.mappedResponse(data); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: schoolDto[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async createSchool(request: any, schoolDto: SchoolDto) { - return this.httpService - .post(`${this.url}`, schoolDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateSchool(id: string, request: any, schoolDto: SchoolDto) { - var axios = require("axios"); - var data = schoolDto; - - var config = { - method: "put", - url: `${this.url}/${id}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchSchool(request: any, schoolSearchDto: SchoolSearchDto) { - return this.httpService - .post(`${this.url}/search`, schoolSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const schoolDto = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: schoolDto, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async mappedResponse(result: any) { - const schoolResponse = result.map((item: any) => { - const schoolMapping = { - schoolId: item?.osid ? `${item.osid}` : "", - schoolName: item?.schoolName ? `${item.schoolName}` : "", - email: item?.email ? `${item.email}` : "", - udise: item?.udise ? `${item.udise}` : "", - mediumOfInstruction: item?.mediumOfInstruction - ? item.mediumOfInstruction - : "", - phoneNumber: item?.phoneNumber ? item.phoneNumber : "", - address: item?.address ? item.address : "", - schoolType: item?.schoolType ? `${item.schoolType}` : "", - website: item?.website ? `${item.website}` : "", - headMaster: item?.headMaster ? `${item.headMaster}` : "", - board: item?.board ? `${item.board}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - cluster: item?.cluster ? `${item.cluster}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - enrollCount: item?.enrollCount ? `${item.enrollCount}` : "", - status: item?.status ? `${item.status}` : "", - latitude: item?.latitude ? item.latitude : "", - longitude: item?.longitude ? item.longitude : "", - metaData: item?.metaData ? item.metaData : [], - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new SchoolDto(schoolMapping); - }); - - return schoolResponse; - } -} diff --git a/src/adapters/sunbirdrc/student.adapter.ts b/src/adapters/sunbirdrc/student.adapter.ts deleted file mode 100644 index 12c4fd22..00000000 --- a/src/adapters/sunbirdrc/student.adapter.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { Injectable, HttpException } from "@nestjs/common"; -import { StudentDto } from "../../student/dto/student.dto"; -import { HttpService } from "@nestjs/axios"; -import { AxiosResponse } from "axios"; -import { map } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { StudentSearchDto } from "src/student/dto/student-search.dto"; -import { IServicelocator } from "../studentservicelocator"; -export const SunbirdStudentToken = "SunbirdStudent"; -@Injectable() -export class StudentService implements IServicelocator { - private student: StudentDto; - - constructor(private httpService: HttpService) {} - url = `${process.env.BASEAPIURL}/Student`; - - public async getStudent(studentId: any, request: any) { - return this.httpService - .get(`${this.url}/${studentId}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = axiosResponse.data; - - const studentDto = [data]; - const studentResponse = await this.mappedResponse(studentDto); - return new SuccessResponse({ - statusCode: 200, - message: "student found Successfully", - data: studentResponse[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async createStudent(request: any, studentDto: StudentDto) { - return this.httpService - .post(`${this.url}`, studentDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateStudent(id: string, request: any, studentDto: StudentDto) { - var axios = require("axios"); - var data = studentDto; - - var config = { - method: "put", - url: `${this.url}/${id}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: response.data, - }); - } - - public async searchStudent(request: any, studentSearchDto: StudentSearchDto) { - let studentSearchData = studentSearchDto; - - let searchData: any; - Object.keys(studentSearchData).forEach((e) => { - if (studentSearchData[e].studentId) { - searchData = { - filters: { - osid: { - eq: `${studentSearchData[e].studentId.eq}`, - }, - ...studentSearchData.filters, - }, - }; - - delete searchData.filters.studentId; - } else { - searchData = studentSearchData; - } - }); - return this.httpService - .post(`${this.url}/search`, studentSearchDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const studentResponse = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok.", - data: studentResponse, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async mappedResponse(result: any) { - const studentResponse = result.map((item: any) => { - const studentMapping = { - studentId: item?.osid ? `${item.osid}` : "", - refId1: item?.admissionNo ? `${item.admissionNo}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - groupId: item?.groupId ? `${item.groupId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - studentEmail: item?.studentEmail ? `${item.studentEmail}` : "", - studentPhoneNumber: item?.studentPhoneNumber - ? item.studentPhoneNumber - : "", - iscwsn: item?.iscwsn ? `${item.iscwsn}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - religion: item?.religion ? `${item.religion}` : "", - singleGirl: item?.singleGirl ? item.singleGirl : "", - weight: item?.weight ? `${item.weight}` : "", - height: item?.height ? `${item.height}` : "", - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - homeless: item?.homeless ? item.homeless : "", - bpl: item?.bpl ? item.bpl : "", - migrant: item?.migrant ? item.migrant : "", - status: item?.status ? `${item.status}` : "", - - fatherFirstName: item?.fatherFirstName ? `${item.fatherFirstName}` : "", - - fatherMiddleName: item?.fatherMiddleName - ? `${item.fatherMiddleName}` - : "", - - fatherLastName: item?.fatherLastName ? `${item.fatherLastName}` : "", - fatherPhoneNumber: item?.fatherPhoneNumber - ? item.fatherPhoneNumber - : "", - fatherEmail: item?.fatherEmail ? `${item.fatherEmail}` : "", - - motherFirstName: item?.motherFirstName ? `${item.motherFirstName}` : "", - motherMiddleName: item?.motherMiddleName - ? `${item.motherMiddleName}` - : "", - motherLastName: item?.motherLastName ? `${item.motherLastName}` : "", - motherPhoneNumber: item?.motherPhoneNumber - ? item.motherPhoneNumber - : "", - motherEmail: item?.motherEmail ? `${item.motherEmail}` : "", - - guardianFirstName: item?.guardianFirstName - ? `${item.guardianFirstName}` - : "", - guardianMiddleName: item?.guardianMiddleName - ? `${item.guardianMiddleName}` - : "", - guardianLastName: item?.guardianLastName - ? `${item.guardianLastName}` - : "", - guardianPhoneNumber: item?.guardianPhoneNumber - ? item.guardianPhoneNumber - : "", - guardianEmail: item?.guardianEmail ? `${item.guardianEmail}` : "", - image: item?.image ? `${item.image}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - studentAddress: item?.studentAddress ? `${item.studentAddress}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new StudentDto(studentMapping); - }); - - return studentResponse; - } -} diff --git a/src/adapters/sunbirdrc/subnbird.module.ts b/src/adapters/sunbirdrc/subnbird.module.ts deleted file mode 100644 index 004a7725..00000000 --- a/src/adapters/sunbirdrc/subnbird.module.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { Module } from "@nestjs/common"; -import { AttendanceService } from "./attendance.adapter"; -import { SunbirdCommentService } from "./comment.adapter"; -import { SunbirdConfigService } from "./config.adapter"; -import { SunbirdGroupService } from "./group.adapter"; -import { SunbirdHolidayService } from "./holiday.adapter"; -import { SunbirdLikeService } from "./like.adapter"; -import { SchoolService } from "./school.adapter"; -import { StudentService } from "./student.adapter"; -import { UserService } from "./user.adapter"; - -@Module({ - imports: [HttpModule], - providers: [ - AttendanceService, - StudentService, - UserService, - SchoolService, - SunbirdGroupService, - SunbirdCommentService, - SunbirdConfigService, - SunbirdLikeService, - SunbirdHolidayService, - ], - exports: [ - AttendanceService, - StudentService, - UserService, - SchoolService, - SunbirdGroupService, - SunbirdCommentService, - SunbirdConfigService, - SunbirdLikeService, - SunbirdHolidayService, - ], -}) -export class SunbirdModule {} diff --git a/src/adapters/sunbirdrc/template.adapter.ts b/src/adapters/sunbirdrc/template.adapter.ts deleted file mode 100644 index 6645335f..00000000 --- a/src/adapters/sunbirdrc/template.adapter.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Injectable, HttpException } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { AxiosResponse } from "axios"; -import { map } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { catchError } from "rxjs/operators"; -import { ErrorResponse } from "src/error-response"; -import { TemplateProcessDto } from "src/template/dto/template-process.dto"; -import { TemplateCreateDto } from "src/template/dto/template-create.dto"; - -@Injectable() -export class TemplateService { - constructor(private httpService: HttpService) {} - url = process.env.TEMPLATERURL; - - public async createTemplate(request: any, templateDto: TemplateCreateDto) { - var axios = require("axios"); - - var config = { - method: "post", - url: this.url, - headers: { - Authorization: request.headers.authorization, - }, - data: templateDto, - }; - - const response = await axios(config); - const responseData = response.data; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: responseData, - }); - } - - public async getTemplate(id: any, request: any) { - return this.httpService - .get(`${this.url}${id}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = [axiosResponse.data]; - - const templateDto = await this.templateCreate(data); - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: templateDto[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - public async processTemplate( - request: any, - templateProcessDto: TemplateProcessDto - ) { - var axios = require("axios"); - - var config = { - method: "post", - url: `${this.url}process`, - headers: { - Authorization: request.headers.authorization, - }, - data: templateProcessDto, - }; - - const response = await axios(config); - const responseData = response.data; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: responseData, - }); - } - public async getTemplateByTag(tag: string, request: any) { - var axios = require("axios"); - - let config = { - method: "get", - url: `${this.url}search/tag?queryString=${tag}`, - }; - - const response = await axios(config); - const data = response?.data; - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: data, - }); - } - - public async templateCreate(result: any) { - const templateCreateResponse = result.map((item: any) => { - const templateMapping = { - body: item?.body ? `${item.body}` : "", - type: item?.type ? `${item.type}` : "", - user: item?.user ? `${item.user}` : "", - tag: item?.tag, - createdAt: item?.createdAt ? `${item.createdAt}` : "", - updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", - }; - return new TemplateCreateDto(templateMapping); - }); - - return templateCreateResponse; - } - - public async templateProcess(result: any) { - const templateProcessResponse = result.map((item: any) => { - const templateMapping = { - id: item?.id ? item.id : "", - data: item?.data ? item.data : "", - }; - return new TemplateCreateDto(templateMapping); - }); - - return templateProcessResponse; - } -} diff --git a/src/adapters/sunbirdrc/user.adapter.ts b/src/adapters/sunbirdrc/user.adapter.ts deleted file mode 100644 index e1016be5..00000000 --- a/src/adapters/sunbirdrc/user.adapter.ts +++ /dev/null @@ -1,294 +0,0 @@ -import { Injectable, HttpException } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { AxiosResponse } from "axios"; -import { map } from "rxjs"; -import { catchError } from "rxjs/operators"; -import { SuccessResponse } from "src/success-response"; -import { ErrorResponse } from "src/error-response"; -import { UserSearchDto } from "src/user/dto/user-search.dto"; -import { UserDto } from "../../user/dto/user.dto"; -import jwt_decode from "jwt-decode"; -import { IServicelocator } from "../userservicelocator"; -import { UserSegmentDto } from "src/user/dto/user-segment.dto"; -import { UserCreateDto } from "src/user/dto/user-create.dto"; -export const SunbirdUserToken = "SunbirdUser"; -@Injectable() -export class UserService implements IServicelocator { - constructor(private httpService: HttpService) {} - checkAndAddUser(request: any, userDto: UserCreateDto) { - throw new Error("Method not implemented."); - } - url = `${process.env.BASEAPIURL}/User`; - templaterURL = process.env.TEMPLATERURL; - - public async getUser(tenantId: string, id: any, request: any) { - return this.httpService - .get(`${this.url}/${id}`, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (axiosResponse: AxiosResponse) => { - let data = [axiosResponse.data]; - - const teacherResponse = await this.mappedResponse(data); - return new SuccessResponse({ - statusCode: 200, - message: "User found Successfully", - data: teacherResponse[0], - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async createUser(request: any, teacherDto: UserDto) { - return this.httpService - .post(`${this.url}`, teacherDto, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map((axiosResponse: AxiosResponse) => { - return new SuccessResponse({ - statusCode: 200, - message: "User created Successfully", - data: axiosResponse.data, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response?.status, - errorMessage: e.response?.data?.params?.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async updateUser(id: string, request: any, teacherDto: UserDto) { - var axios = require("axios"); - var data = teacherDto; - - var config = { - method: "put", - url: `${this.url}/${id}`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - return new SuccessResponse({ - statusCode: 200, - message: "User updated Successfully", - data: response.data, - }); - } - public async searchUser( - tenantId: string, - request: any, - teacherSearchDto: UserSearchDto - ) { - let userSearchData = teacherSearchDto; - - let searchData: any; - Object.keys(userSearchData).forEach((e) => { - if (userSearchData[e].userId) { - searchData = { - filters: { - osid: { - eq: `${userSearchData[e].userId.eq}`, - }, - ...userSearchData.filters, - }, - }; - - delete searchData.filters.userId; - } else { - searchData = userSearchData; - } - }); - - return this.httpService - .post(`${this.url}/search`, searchData, { - headers: { - Authorization: request.headers.authorization, - }, - }) - .pipe( - map(async (response) => { - const responsedata = response.data; - const teacherResponse = await this.mappedResponse(responsedata); - return new SuccessResponse({ - statusCode: response.status, - message: "Ok", - data: teacherResponse, - }); - }), - catchError((e) => { - var error = new ErrorResponse({ - errorCode: e.response.status, - errorMessage: e.response.data.params.errmsg, - }); - throw new HttpException(error, e.response.status); - }) - ); - } - - public async getUserByAuth(tenantId: string, request: any) { - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - - let axios = require("axios"); - let data = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let config = { - method: "post", - url: `${this.url}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: data, - }; - const response = await axios(config); - let result = response?.data && response.data; - const teacherResponse = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: teacherResponse, - }); - } - - public async teacherSegment( - schoolId: string, - templateId: string, - request: any - ) { - const teacherSearchDto = { - filters: { - schoolId: { - eq: `${schoolId}`, - }, - }, - }; - var axios = require("axios"); - var getTemplate = { - method: "get", - url: `${this.templaterURL}${templateId}`, - }; - const getfcmClickActionUrl = await axios(getTemplate); - const fcmClickActionUrlData = getfcmClickActionUrl.data; - let tagString = JSON.stringify(fcmClickActionUrlData.tag[0]); - var jsonToObj = JSON.parse(tagString); - let fcmClickActionUrl = JSON.parse(jsonToObj); - - let config = { - method: "post", - url: `${this.url}/search`, - - data: teacherSearchDto, - }; - const response = await axios(config); - let responseData = response.data.map((item: any) => { - const userSegment = { - fcmToken: item?.fcmToken ? `${item.fcmToken}` : "", - phoneNo: item?.phoneNumber ? `${item.phoneNumber}` : "", - name: item?.firstName ? `${item.firstName}` : "", - fcmClickActionUrl: item?.fcmClickActionUrl - ? `${item.fcmClickActionUrl}` - : "", - }; - return new UserSegmentDto(userSegment); - }); - - const teachersegment = responseData.map((obj: any) => { - return { ...obj, fcmClickActionUrl: fcmClickActionUrl.attendance }; - }); - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: teachersegment, - }); - } - public async mappedResponse(result: any) { - const userResponse = result.map((item: any) => { - const userMapping = { - userId: item?.osid ? `${item.osid}` : "", - refId1: item?.refId1 ? `${item.refId1}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - refId3: item?.refId3 ? `${item.refId3}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - phoneNumber: item?.phoneNumber ? `${item.phoneNumber}` : "", - email: item?.email ? `${item.email}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - designation: item?.designation ? `${item.designation}` : "", - cadre: item?.cadre ? `${item.cadre}` : "", - profQualification: item?.profQualification - ? `${item.profQualification}` - : "", - joiningDate: item?.joiningDate ? `${item.joiningDate}` : "", - subjectIds: item.subjectIds ? item.subjectIds : [], - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - maritalStatus: item?.maritalStatus ? `${item.maritalStatus}` : "", - compSkills: item?.compSkills ? `${item.compSkills}` : "", - disability: item?.disability ? `${item.disability}` : "", - religion: item?.religion ? `${item.religion}` : "", - homeDistance: item?.homeDistance ? `${item.homeDistance}` : "", - employmentType: item?.employmentType ? `${item.employmentType}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - address: item?.address ? `${item.address}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - image: item?.image ? `${item.image}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - reportsTo: item?.reportsTo ? `${item.reportsTo}` : "", - retirementDate: item?.retirementDate ? `${item.retirementDate}` : "", - workingStatus: item?.workingStatus ? `${item.workingStatus}` : "", - fcmToken: item?.fcmToken ? `${item.fcmToken}` : "", - role: item?.role ? `${item.role}` : "", - employeeCode: item?.employeeCode ? `${item.employeeCode}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new UserDto(userMapping); - }); - - return userResponse; - } - - resetUserPassword(request: any, username: string, newPassword: string) { - throw new Error("Method not implemented."); - } -} From 03ecc328e71dc86e3804eb36ed8753627d752ae5 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 16:31:45 +0530 Subject: [PATCH 168/408] chore : removed adminForm module --- src/adminForm/adminForm.controller.spec.ts | 18 ---- src/adminForm/adminForm.controller.ts | 97 ---------------------- src/adminForm/adminForm.module.ts | 16 ---- src/adminForm/dto/adminForm-search.dto.ts | 28 ------- src/adminForm/dto/adminForm.dto.ts | 29 ------- src/app.module.ts | 2 - 6 files changed, 190 deletions(-) delete mode 100644 src/adminForm/adminForm.controller.spec.ts delete mode 100644 src/adminForm/adminForm.controller.ts delete mode 100644 src/adminForm/adminForm.module.ts delete mode 100644 src/adminForm/dto/adminForm-search.dto.ts delete mode 100644 src/adminForm/dto/adminForm.dto.ts diff --git a/src/adminForm/adminForm.controller.spec.ts b/src/adminForm/adminForm.controller.spec.ts deleted file mode 100644 index d82053df..00000000 --- a/src/adminForm/adminForm.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from "@nestjs/testing"; -import { AdminFormController } from "./adminForm.controller"; - -describe("AdminFormController", () => { - let controller: AdminFormController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [AdminFormController], - }).compile(); - - controller = module.get(AdminFormController); - }); - - it("should be defined", () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/adminForm/adminForm.controller.ts b/src/adminForm/adminForm.controller.ts deleted file mode 100644 index 9cbc19b8..00000000 --- a/src/adminForm/adminForm.controller.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { AdminFormService } from "../adapters/sunbirdrc/adminForm.adapter"; - -import { - CacheInterceptor, - CACHE_MANAGER, - Inject, - Request, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Post, - Body, - Put, - Patch, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, -} from "@nestjs/common"; -import { AdminFormDto } from "./dto/adminForm.dto"; -import { AdminFormSearchDto } from "./dto/adminForm-search.dto"; -@ApiTags("AdminForm") -@Controller("adminForm") -export class AdminFormController { - constructor( - private service: AdminFormService, - @Inject(CACHE_MANAGER) private cacheManager - ) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "AdminForm detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getAdminForm(@Param("id") adminFormId: string, @Req() request: Request) { - return this.service.getAdminForm(adminFormId, request); - } - - @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "AdminForm has been created successfully.", - }) - @ApiBody({ type: AdminFormDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createAdminForm( - @Req() request: Request, - @Body() adminFormDto: AdminFormDto - ) { - return this.service.createAdminForm(request, adminFormDto); - } - - @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "AdminForm has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateAdminForm( - @Param("id") id: string, - @Req() request: Request, - @Body() adminFormDto: AdminFormDto - ) { - return await this.service.updateAdminForm(id, request, adminFormDto); - } - - @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "AdminForm list." }) - @ApiBody({ type: AdminFormSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchAdminForm( - @Req() request: Request, - @Body() adminFormSearchDto: AdminFormSearchDto - ) { - return await this.service.searchAdminForm(request, adminFormSearchDto); - } -} diff --git a/src/adminForm/adminForm.module.ts b/src/adminForm/adminForm.module.ts deleted file mode 100644 index 1aa9cfcb..00000000 --- a/src/adminForm/adminForm.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { CacheModule, Module } from "@nestjs/common"; -import { AdminFormController } from "./adminForm.controller"; -import { AdminFormService } from "../adapters/sunbirdrc/adminForm.adapter"; -import { HttpModule } from "@nestjs/axios"; -const ttl = process.env.TTL as never; -@Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], - controllers: [AdminFormController], - providers: [AdminFormService], -}) -export class AdminFormModule {} diff --git a/src/adminForm/dto/adminForm-search.dto.ts b/src/adminForm/dto/adminForm-search.dto.ts deleted file mode 100644 index 41c69074..00000000 --- a/src/adminForm/dto/adminForm-search.dto.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Exclude, Expose } from "class-transformer"; -import { - MaxLength, - IsNotEmpty, - IsEmail, - IsString, - IsNumber, -} from "class-validator"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class AdminFormSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/adminForm/dto/adminForm.dto.ts b/src/adminForm/dto/adminForm.dto.ts deleted file mode 100644 index 856693d2..00000000 --- a/src/adminForm/dto/adminForm.dto.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { Exclude, Expose } from "class-transformer"; - -export class AdminFormDto { - @Expose() - adminFormId: string; - @ApiProperty() - @Expose() - moduleId: string; - @ApiProperty() - @Expose() - formSchema: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/app.module.ts b/src/app.module.ts index ae137d59..796cee19 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -13,7 +13,6 @@ import { WorksheetModule } from "./worksheet/worksheet.module"; import { MulterModule } from "@nestjs/platform-express/multer"; import { QuestionModule } from "./Question/question.module"; import { LessonPlanModule } from "./lessonPlan/lessonPlan.module"; -import { AdminFormModule } from "./adminForm/adminForm.module"; import { LikeModule } from "./like/like.module"; import { CommentModule } from "./comment/comment.module"; import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; @@ -54,7 +53,6 @@ import { SwaggerModule } from "@nestjs/swagger"; WorksheetModule, QuestionModule, LessonPlanModule, - AdminFormModule, LikeModule, CommentModule, TrackAssessmentModule, From 0349395e703d834a56da37a2f2f125b3cfe25bbe Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 16:34:25 +0530 Subject: [PATCH 169/408] chore : removed notification module --- src/app.module.ts | 2 - .../dto/notification-search.dto.ts | 20 --- src/notification/dto/notification.dto.ts | 73 ----------- .../instantNotification.controller.ts | 98 --------------- src/notification/notification.module.ts | 19 --- .../scheduleNotification.controller.ts | 114 ------------------ 6 files changed, 326 deletions(-) delete mode 100644 src/notification/dto/notification-search.dto.ts delete mode 100644 src/notification/dto/notification.dto.ts delete mode 100644 src/notification/instantNotification.controller.ts delete mode 100644 src/notification/notification.module.ts delete mode 100644 src/notification/scheduleNotification.controller.ts diff --git a/src/app.module.ts b/src/app.module.ts index 796cee19..f4d52bb3 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AttendanceModule } from "./attendance/attendance.module"; import { HolidayModule } from "./holiday/holiday.module"; import { ConfigurationModule } from "./configs/configuration.module"; import { ConfigModule } from "@nestjs/config"; -import { NotificationModule } from "./notification/notification.module"; import { TemplateModule } from "./template/template.module"; import { WorksheetModule } from "./worksheet/worksheet.module"; import { MulterModule } from "@nestjs/platform-express/multer"; @@ -49,7 +48,6 @@ import { SwaggerModule } from "@nestjs/swagger"; HolidayModule, ConfigurationModule, TemplateModule, - NotificationModule, WorksheetModule, QuestionModule, LessonPlanModule, diff --git a/src/notification/dto/notification-search.dto.ts b/src/notification/dto/notification-search.dto.ts deleted file mode 100644 index 5fc7d630..00000000 --- a/src/notification/dto/notification-search.dto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class NotificationSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/notification/dto/notification.dto.ts b/src/notification/dto/notification.dto.ts deleted file mode 100644 index 094d9319..00000000 --- a/src/notification/dto/notification.dto.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class NotificationLogDto { - @Expose() - notificationLogId: string; - @ApiProperty({ - description: "Content of notification", - }) - @Expose() - content: string; - - @ApiProperty({ - description: "Recepients of notification", - }) - @Expose() - recepients: []; - - @ApiProperty({ - description: "Module of notification", - }) - @Expose() - module: string; - - @ApiProperty({ - description: "Template content Id", - }) - @Expose() - templateContentId: string; - - @ApiProperty({ - description: "medium of notification", - }) - @Expose() - medium: string; - - @ApiProperty({ - description: "Sent date of notification", - }) - @Expose() - sentDate: string; - - @Expose() - sentBy: string; - - @ApiProperty({ - description: "options of notification", - }) - @Expose() - options: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - @Expose() - templateId: string; - - @Expose() - scheduleDate: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/notification/instantNotification.controller.ts b/src/notification/instantNotification.controller.ts deleted file mode 100644 index f87660cf..00000000 --- a/src/notification/instantNotification.controller.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Post, - Body, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Request, - CacheInterceptor, - Query, -} from "@nestjs/common"; - -import { NotificationService } from "src/adapters/sunbirdrc/notification.adapter"; -import { NotificationSearchDto } from "./dto/notification-search.dto"; -@ApiTags("Instant Notification") -@Controller("instantNotification") -export class instantNotificationController { - constructor(private service: NotificationService) {} - - @Post("instantSend") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Notification has been sent successfully.", - }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "module" }) - @ApiQuery({ name: "eventTrigger" }) - @ApiQuery({ name: "templateId" }) - @ApiQuery({ name: "senderId" }) - @ApiQuery({ name: "groupId" }) - @ApiQuery({ name: "channel" }) - public async instantSendNotification( - @Query("module") module: string, - @Query("eventTrigger") eventTrigger: string, - @Query("templateId") templateId: string, - @Query("senderId") senderId: string, - @Query("groupId") groupId: string, - @Query("channel") channel: string, - @Req() request: Request - ) { - return this.service.instantSendNotification( - module, - eventTrigger, - templateId, - senderId, - groupId, - channel, - request - ); - } - - @Get("log/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Notification Log detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getNotification( - @Param("id") id: string, - @Req() request: Request - ) { - return this.service.getNotification(id, request); - } - - @Post("log/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Notification log list." }) - @ApiBody({ type: NotificationSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchStudent( - @Req() request: Request, - @Body() notificationSearchDto: NotificationSearchDto - ) { - return await this.service.searchNotification( - request, - notificationSearchDto - ); - } -} diff --git a/src/notification/notification.module.ts b/src/notification/notification.module.ts deleted file mode 100644 index 11d7aa07..00000000 --- a/src/notification/notification.module.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CacheModule, Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { NotificationService } from "src/adapters/sunbirdrc/notification.adapter"; -import { instantNotificationController } from "./instantNotification.controller"; -import { scheduleNotificationController } from "./scheduleNotification.controller"; -import { ScheduleModule } from "@nestjs/schedule"; -const ttl = process.env.TTL as never; -@Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ScheduleModule.forRoot(), - ], - controllers: [instantNotificationController, scheduleNotificationController], - providers: [NotificationService], -}) -export class NotificationModule {} diff --git a/src/notification/scheduleNotification.controller.ts b/src/notification/scheduleNotification.controller.ts deleted file mode 100644 index ef5f1aa2..00000000 --- a/src/notification/scheduleNotification.controller.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Post, - Body, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Request, - CacheInterceptor, - Query, -} from "@nestjs/common"; - -import { NotificationService } from "src/adapters/sunbirdrc/notification.adapter"; -import { NotificationSearchDto } from "./dto/notification-search.dto"; - -@ApiTags("Schedule Notification") -@Controller("scheduleNotification") -export class scheduleNotificationController { - constructor(private service: NotificationService) {} - - @Post("scheduledSend") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Notification has been sent successfully.", - }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "module" }) - @ApiQuery({ name: "eventTrigger" }) - @ApiQuery({ name: "templateId" }) - @ApiQuery({ name: "senderId" }) - @ApiQuery({ name: "groupId" }) - @ApiQuery({ name: "channel" }) - @ApiQuery({ name: "month" }) - @ApiQuery({ name: "date" }) - @ApiQuery({ name: "hours" }) - @ApiQuery({ name: "minutes" }) - @ApiQuery({ name: "taskName" }) - public async scheduledSendNotification( - @Query("module") module: string, - @Query("eventTrigger") eventTrigger: string, - @Query("templateId") templateId: string, - @Query("senderId") senderId: string, - @Query("groupId") groupId: string, - @Query("channel") channel: string, - @Query("month") month: string, - @Query("date") date: string, - @Query("hours") hours: string, - @Query("minutes") minutes: string, - @Query("taskName") taskName: string, - @Req() request: Request - ) { - return this.service.scheduleSendNotification( - module, - eventTrigger, - templateId, - senderId, - groupId, - channel, - month, - date, - hours, - minutes, - taskName, - request - ); - } - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Notification Log detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getNotification( - @Param("id") id: string, - @Req() request: Request - ) { - return this.service.getScheduleNotification(id, request); - } - - @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Notification log list." }) - @ApiBody({ type: NotificationSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchStudent( - @Req() request: Request, - @Body() notificationSearchDto: NotificationSearchDto - ) { - return await this.service.searchSchedulehNotification( - request, - notificationSearchDto - ); - } -} From bb15745dc7cd39737154a7f3d000fac946e6c543 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 16:36:28 +0530 Subject: [PATCH 170/408] chore : removed inAppNotification module --- src/app.module.ts | 2 - .../inAppNotification.controller.ts | 133 ------------------ .../inAppNotification.module.ts | 18 --- 3 files changed, 153 deletions(-) delete mode 100644 src/inAppNotification/inAppNotification.controller.ts delete mode 100644 src/inAppNotification/inAppNotification.module.ts diff --git a/src/app.module.ts b/src/app.module.ts index f4d52bb3..404b800a 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -16,7 +16,6 @@ import { LikeModule } from "./like/like.module"; import { CommentModule } from "./comment/comment.module"; import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; import { AssessmentSetModule } from "./assessmentset/assessmentset.module"; -import { InAppNotificationModule } from "./inAppNotification/inAppNotification.module"; import { MentorTrackingModule } from "./mentorTracking/mentorTracking.module"; import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module"; import { CourseModule } from "./course/course.module"; @@ -55,7 +54,6 @@ import { SwaggerModule } from "@nestjs/swagger"; CommentModule, TrackAssessmentModule, AssessmentSetModule, - InAppNotificationModule, MentorTrackingModule, MonitorTrackingModule, CourseModule, diff --git a/src/inAppNotification/inAppNotification.controller.ts b/src/inAppNotification/inAppNotification.controller.ts deleted file mode 100644 index b0c77f32..00000000 --- a/src/inAppNotification/inAppNotification.controller.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { - ApiTags, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, -} from "@nestjs/swagger"; -import { - Controller, - Post, - UseInterceptors, - ClassSerializerInterceptor, - Req, - Request, - Query, - Get, -} from "@nestjs/common"; -import { InAppNotificationService } from "src/adapters/sunbirdrc/inAppNotification.adapter"; - -@ApiTags("In App Notification") -@Controller("inappnotification") -export class InAppNotificationController { - constructor(private service: InAppNotificationService) {} - - @Post("inappnotification") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Notification has been sent successfully.", - }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "module" }) - @ApiQuery({ name: "groupId" }) - @ApiQuery({ name: "templateId" }) - public async inAppNotification( - @Query("module") module: string, - @Query("groupId") groupId: string, - @Query("templateId") templateId: string, - @Req() request: Request - ) { - return this.service.inAppNotification(module, groupId, request, templateId); - } - - @Get("/userhistory") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "User Notification History.", - }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "userId" }) - @ApiQuery({ name: "provider" }) - @ApiQuery({ name: "startDate" }) - @ApiQuery({ name: "endDate" }) - public async userHistoryNotification( - @Query("userId") userId: string, - @Query("provider") provider: string, - @Query("startDate") startDate: string, - @Query("endDate") endDate: string, - @Req() request: Request - ) { - return this.service.userHistoryNotification( - userId, - provider, - startDate, - endDate, - request - ); - } - - @Get("/bothistory") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Bot Notification History.", - }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "botId" }) - @ApiQuery({ name: "provider" }) - @ApiQuery({ name: "startDate" }) - @ApiQuery({ name: "endDate" }) - public async botHistoryNotification( - @Query("botId") botId: string, - @Query("provider") provider: string, - @Query("startDate") startDate: string, - @Query("endDate") endDate: string, - @Req() request: Request - ) { - return this.service.botHistoryNotification( - botId, - provider, - startDate, - endDate, - request - ); - } - - @Post("readreceipt") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Read Receipt.", - }) - @UseInterceptors(ClassSerializerInterceptor) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "eventType", required: false }) - @ApiQuery({ name: "externalId", required: false }) - @ApiQuery({ name: "destAdd", required: false }) - @ApiQuery({ name: "fcmDestAdd", required: false }) - @ApiQuery({ name: "messageId", required: false }) - @ApiQuery({ name: "text", required: false }) - @ApiQuery({ name: "from", required: false }) - public async readReceipt( - @Query("eventType") eventType: string, - @Query("externalId") externalId: string, - @Query("destAdd") destAdd: string, - @Query("fcmDestAdd") fcmDestAdd: string, - @Query("messageId") messageId: string, - @Query("text") text: string, - @Query("from") from: string, - @Req() request: Request - ) { - return this.service.readReceipt( - eventType, - externalId, - destAdd, - fcmDestAdd, - messageId, - text, - from, - request - ); - } -} diff --git a/src/inAppNotification/inAppNotification.module.ts b/src/inAppNotification/inAppNotification.module.ts deleted file mode 100644 index b63978c7..00000000 --- a/src/inAppNotification/inAppNotification.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { CacheModule, Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { ScheduleModule } from "@nestjs/schedule"; -import { InAppNotificationController } from "./inAppNotification.controller"; -import { InAppNotificationService } from "src/adapters/sunbirdrc/inAppNotification.adapter"; -const ttl = process.env.TTL as never; -@Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ScheduleModule.forRoot(), - ], - controllers: [InAppNotificationController], - providers: [InAppNotificationService], -}) -export class InAppNotificationModule {} From 9e98d9ace1e32236e78449539bf64860e516928a Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 16:42:57 +0530 Subject: [PATCH 171/408] chore : removed lessonPlan module --- src/app.module.ts | 2 - src/lessonPlan/dto/lessonPlan.dto.ts | 182 -------------------- src/lessonPlan/dto/lessonPlan.search.dto.ts | 20 --- src/lessonPlan/lessonPlan.controller.ts | 91 ---------- src/lessonPlan/lessonPlan.module.ts | 16 -- 5 files changed, 311 deletions(-) delete mode 100644 src/lessonPlan/dto/lessonPlan.dto.ts delete mode 100644 src/lessonPlan/dto/lessonPlan.search.dto.ts delete mode 100644 src/lessonPlan/lessonPlan.controller.ts delete mode 100644 src/lessonPlan/lessonPlan.module.ts diff --git a/src/app.module.ts b/src/app.module.ts index 404b800a..87033523 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -11,7 +11,6 @@ import { TemplateModule } from "./template/template.module"; import { WorksheetModule } from "./worksheet/worksheet.module"; import { MulterModule } from "@nestjs/platform-express/multer"; import { QuestionModule } from "./Question/question.module"; -import { LessonPlanModule } from "./lessonPlan/lessonPlan.module"; import { LikeModule } from "./like/like.module"; import { CommentModule } from "./comment/comment.module"; import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; @@ -49,7 +48,6 @@ import { SwaggerModule } from "@nestjs/swagger"; TemplateModule, WorksheetModule, QuestionModule, - LessonPlanModule, LikeModule, CommentModule, TrackAssessmentModule, diff --git a/src/lessonPlan/dto/lessonPlan.dto.ts b/src/lessonPlan/dto/lessonPlan.dto.ts deleted file mode 100644 index 34eb5ff1..00000000 --- a/src/lessonPlan/dto/lessonPlan.dto.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class LessonPlanDto { - @Expose() - contentId: string; - - @ApiProperty({}) - @Expose() - name: string; - - @ApiProperty({}) - @Expose() - code: string; - - @ApiProperty({}) - @Expose() - status: string; - - @ApiProperty({}) - @Expose() - channel: string; - - @ApiProperty({}) - @Expose() - mediaType: string; - - @ApiProperty({}) - @Expose() - compatibilityLevel: string; - - @ApiProperty({}) - @Expose() - audience: [string]; - - @ApiProperty({}) - @Expose() - posterImage: string; - - @ApiProperty({}) - @Expose() - duration: string; - - @ApiProperty({}) - @Expose() - downloadUrl: string; - - @ApiProperty({}) - @Expose() - previewUrl: string; - - @ApiProperty({}) - @Expose() - author: string; - - @ApiProperty({}) - @Expose() - languageCode: [string]; - - @ApiProperty({}) - @Expose() - language: [string]; - - @ApiProperty({}) - @Expose() - ageGroup: [string]; - - @ApiProperty({}) - @Expose() - contentType: string; - - @ApiProperty({}) - @Expose() - category: [string]; - - @ApiProperty({}) - @Expose() - teachingMode: string; - - @ApiProperty({}) - @Expose() - skills: [string]; - - @ApiProperty({}) - @Expose() - keywords: [string]; - - @ApiProperty({}) - @Expose() - description: string; - - @ApiProperty({}) - @Expose() - instructions: string; - - @ApiProperty({}) - @Expose() - body: string; - - @ApiProperty({}) - @Expose() - learningObjective: [string]; - - @ApiProperty({}) - @Expose() - creator: string; - - @ApiProperty({}) - @Expose() - reviewer: string; - - @ApiProperty({}) - @Expose() - lastSubmittedBy: string; - - @ApiProperty({}) - @Expose() - lastSubmittedOn: string; - - @ApiProperty({}) - @Expose() - lastPublishedBy: string; - - @ApiProperty({}) - @Expose() - lastPublishedOn: string; - - @ApiProperty({}) - @Expose() - subject: [string]; - - @ApiProperty({}) - @Expose() - questionCategories: [string]; - - @ApiProperty({}) - @Expose() - medium: [string]; - - @ApiProperty({}) - @Expose() - gradeLevel: [string]; - - @ApiProperty({}) - @Expose() - topic: [string]; - - @ApiProperty({}) - @Expose() - subjectCodes: [string]; - - @ApiProperty({}) - @Expose() - difficultyLevel: string; - - @ApiProperty({}) - @Expose() - board: string; - - @ApiProperty({}) - @Expose() - primaryCategory: string; - - @ApiProperty({}) - @Expose() - accessibility: [string]; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/lessonPlan/dto/lessonPlan.search.dto.ts b/src/lessonPlan/dto/lessonPlan.search.dto.ts deleted file mode 100644 index 58ae35b2..00000000 --- a/src/lessonPlan/dto/lessonPlan.search.dto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class LessonPlanSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/lessonPlan/lessonPlan.controller.ts b/src/lessonPlan/lessonPlan.controller.ts deleted file mode 100644 index 792c9861..00000000 --- a/src/lessonPlan/lessonPlan.controller.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - CacheInterceptor, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, -} from "@nestjs/swagger"; -import { Request } from "@nestjs/common"; -import { LessonPlanDto } from "./dto/lessonPlan.dto"; -import { LessonPlanSearchDto } from "./dto/lessonPlan.search.dto"; -import { LessonPlanService } from "src/adapters/sunbirdrc/lessonPlan.adapter"; -@ApiTags("Lesson Plan") -@Controller("lessonPlan") -export class LessonPlanController { - constructor(private readonly service: LessonPlanService) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "LessonPlan detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getLessonPlans(@Param("id") lessonPlanId: string, @Req() request: Request) { - return this.service.getLessonPlan(lessonPlanId, request); - } - - @Post() - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "LessonPlan has been created successfully.", - }) - @ApiBody({ type: LessonPlanDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createLessonPlan( - @Req() request: Request, - @Body() lessonPlanDto: LessonPlanDto - ) { - return this.service.createLessonPlan(request, lessonPlanDto); - } - - @Put("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "LessonPlan has been updated successfully.", - }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateLessonPlan( - @Param("id") lessonPlanId: string, - @Req() request: Request, - @Body() lessonPlanDto: LessonPlanDto - ) { - return await this.service.updateLessonPlan( - lessonPlanId, - request, - lessonPlanDto - ); - } - - @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "LessonPlan list." }) - @ApiBody({ type: LessonPlanSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchLessonPlan( - @Req() request: Request, - @Body() lessonPlanSearchDto: LessonPlanSearchDto - ) { - return await this.service.searchLessonPlan(request, lessonPlanSearchDto); - } -} diff --git a/src/lessonPlan/lessonPlan.module.ts b/src/lessonPlan/lessonPlan.module.ts deleted file mode 100644 index 3b764661..00000000 --- a/src/lessonPlan/lessonPlan.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { CacheModule, Module } from "@nestjs/common"; -import { LessonPlanController } from "./lessonPlan.controller"; -import { LessonPlanService } from "src/adapters/sunbirdrc/lessonPlan.adapter"; -const ttl = process.env.TTL as never; -@Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], - controllers: [LessonPlanController], - providers: [LessonPlanService], -}) -export class LessonPlanModule {} From 020490971a0d8e3c46c34df3f2d5d377a1055353 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 17:02:30 +0530 Subject: [PATCH 172/408] chore : removed template module --- src/app.module.ts | 2 - src/template/dto/template-create.dto.ts | 37 ----------- src/template/dto/template-process.dto.ts | 18 ----- src/template/dto/template-search.dto.ts | 20 ------ src/template/template.controller.ts | 84 ------------------------ src/template/template.module.ts | 16 ----- 6 files changed, 177 deletions(-) delete mode 100644 src/template/dto/template-create.dto.ts delete mode 100644 src/template/dto/template-process.dto.ts delete mode 100644 src/template/dto/template-search.dto.ts delete mode 100644 src/template/template.controller.ts delete mode 100644 src/template/template.module.ts diff --git a/src/app.module.ts b/src/app.module.ts index 87033523..20242342 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AttendanceModule } from "./attendance/attendance.module"; import { HolidayModule } from "./holiday/holiday.module"; import { ConfigurationModule } from "./configs/configuration.module"; import { ConfigModule } from "@nestjs/config"; -import { TemplateModule } from "./template/template.module"; import { WorksheetModule } from "./worksheet/worksheet.module"; import { MulterModule } from "@nestjs/platform-express/multer"; import { QuestionModule } from "./Question/question.module"; @@ -45,7 +44,6 @@ import { SwaggerModule } from "@nestjs/swagger"; AttendanceModule, HolidayModule, ConfigurationModule, - TemplateModule, WorksheetModule, QuestionModule, LikeModule, diff --git a/src/template/dto/template-create.dto.ts b/src/template/dto/template-create.dto.ts deleted file mode 100644 index eabc620d..00000000 --- a/src/template/dto/template-create.dto.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ApiProperty } from "@nestjs/swagger"; -import { Expose } from "class-transformer"; - -export class TemplateCreateDto { - @ApiProperty({ - description: "Body of worksheet Template", - }) - @Expose() - body: string; - - @ApiProperty({ - description: "Type of the template", - }) - @Expose() - type: string; - - @ApiProperty({ - description: "tags for the template", - }) - @Expose() - tag: []; - - @ApiProperty({ - description: "User id", - }) - @Expose() - user: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/template/dto/template-process.dto.ts b/src/template/dto/template-process.dto.ts deleted file mode 100644 index 13298eb5..00000000 --- a/src/template/dto/template-process.dto.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class TemplateProcessDto { - @ApiProperty({ - description: "Id of created template", - }) - id: number; - - @ApiProperty({ - description: "Data to update", - }) - @ApiPropertyOptional() - data: object; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/template/dto/template-search.dto.ts b/src/template/dto/template-search.dto.ts deleted file mode 100644 index 0f5eaa08..00000000 --- a/src/template/dto/template-search.dto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class TemplateSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/template/template.controller.ts b/src/template/template.controller.ts deleted file mode 100644 index 3903c30b..00000000 --- a/src/template/template.controller.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { - ApiBasicAuth, - ApiBody, - ApiQuery, - ApiCreatedResponse, - ApiForbiddenResponse, - ApiOkResponse, - ApiTags, -} from "@nestjs/swagger"; -import { - Body, - CacheInterceptor, - ClassSerializerInterceptor, - Controller, - Get, - Query, - Param, - Post, - Req, - SerializeOptions, - UseInterceptors, - Request, -} from "@nestjs/common"; -import { TemplateService } from "src/adapters/sunbirdrc/template.adapter"; -import { TemplateProcessDto } from "./dto/template-process.dto"; -import { TemplateCreateDto } from "./dto/template-create.dto"; - -@ApiTags("Template") -@Controller("template") -export class TemplateController { - constructor(private service: TemplateService) {} - - @Post("create") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: " Template has been created successfully.", - }) - @ApiBody({ type: TemplateCreateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createTemplate( - @Req() request: Request, - @Body() TemplateCreateDto: TemplateCreateDto - ) { - return this.service.createTemplate(request, TemplateCreateDto); - } - - @Post("process") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: " template process." }) - @ApiBody({ type: TemplateProcessDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async processTemplate( - @Req() request: Request, - @Body() TemplateProcessDto: TemplateProcessDto - ) { - return await this.service.processTemplate(request, TemplateProcessDto); - } - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " template detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getTemplate(@Param("id") id: string, @Req() request: Request) { - return this.service.getTemplate(id, request); - } - @Get(":/searchByTag") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) - //@ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Get all Questions detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "tag", required: true }) - public async getTemplates( - @Query("tag") tag: string, - @Req() request: Request - ) { - return this.service.getTemplateByTag(tag, request); - } -} diff --git a/src/template/template.module.ts b/src/template/template.module.ts deleted file mode 100644 index f248e32d..00000000 --- a/src/template/template.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { CacheModule, Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { TemplateService } from "src/adapters/sunbirdrc/template.adapter"; -import { TemplateController } from "./template.controller"; -const ttl = process.env.TTL as never; -@Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], - controllers: [TemplateController], - providers: [TemplateService], -}) -export class TemplateModule {} From ccd2086d85aa307af83d73c1b114bf90d5fb6d3c Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 17:03:37 +0530 Subject: [PATCH 173/408] chore : removed template module --- src/adapters/hasura/worksheet.adapter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/adapters/hasura/worksheet.adapter.ts b/src/adapters/hasura/worksheet.adapter.ts index 4d9bad13..71757042 100644 --- a/src/adapters/hasura/worksheet.adapter.ts +++ b/src/adapters/hasura/worksheet.adapter.ts @@ -5,7 +5,6 @@ import { WorksheetDto } from "src/worksheet/dto/worksheet.dto"; import { WorksheetSearchDto } from "src/worksheet/dto/worksheet-search.dto"; import { StudentDto } from "src/student/dto/student.dto"; import { ErrorResponse } from "src/error-response"; -import { TemplateProcessDto } from "src/template/dto/template-process.dto"; @Injectable() export class WorksheetService { From a862cf7f73623d1e6e92c3e8ffdbf0b8999efa1a Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 3 Apr 2024 17:27:43 +0530 Subject: [PATCH 174/408] Fix[Matching response statusCode with postman response status] --- src/cohort/cohort.controller.ts | 52 +++++++++++++++----------- src/cohort/cohort.service.ts | 58 +++++++++++------------------ src/fields/fields.controller.ts | 38 ++++++++++++------- src/fields/fields.service.ts | 32 +++++++--------- src/user/user.controller.ts | 28 ++++++++------ src/user/user.service.ts | 65 ++++++++++++++------------------- 6 files changed, 135 insertions(+), 138 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 57d229c7..f26fea92 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -41,7 +41,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; // import { FieldsService } from "../fields/fields.service"; @ApiTags("Cohort") @Controller("cohort") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) export class CohortController { constructor( private cohortAdapter: CohortAdapter, @@ -63,7 +63,7 @@ export class CohortController { ) @ApiBody({ type: CohortCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -71,7 +71,8 @@ export class CohortController { @Headers() headers, @Req() request: Request, @Body() cohortCreateDto: CohortCreateDto, - @UploadedFile() image + @UploadedFile() image, + @Res() response: Response, ) { let tenantid = headers["tenantid"]; const payload = { @@ -79,12 +80,12 @@ export class CohortController { tenantId: tenantid, }; Object.assign(cohortCreateDto, payload); - - return this.cohortService.createCohort(request, cohortCreateDto); + const result = await this.cohortService.createCohort(request, cohortCreateDto); + return response.status(result.statusCode).json(result); } @Get("cohortList/:id") - @UseInterceptors(CacheInterceptor) + // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -101,12 +102,12 @@ export class CohortController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - console.log(request); - return this.cohortService.getCohortList(tenantid, id, request, response); + const result = await this.cohortService.getCohortList(tenantid, id, request, response); + return response.status(result.statusCode).json(result); } @Get("cohortDetails/:id") - @UseInterceptors(CacheInterceptor) + // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort details" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -132,7 +133,7 @@ export class CohortController { @ApiCreatedResponse({ description: "Cohort list." }) @ApiBody({ type: CohortSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) @@ -143,9 +144,11 @@ export class CohortController { @Headers() headers, @Req() request: Request, @Body() cohortSearchDto: CohortSearchDto, + @Res() response: Response, ) { let tenantid = headers["tenantid"]; - return this.cohortService.searchCohort(tenantid, request, cohortSearchDto); + const result = await this.cohortService.searchCohort(tenantid, request, cohortSearchDto); + return response.status(result.statusCode).json(result); } //update @@ -164,19 +167,21 @@ export class CohortController { ) @ApiBody({ type: CohortCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) public async updateCohort( @Param("id") cohortId: string, @Req() request: Request, @Body() cohortCreateDto: CohortCreateDto, - @UploadedFile() image + @UploadedFile() image, + @Res() response: Response ) { - const response = { + const imgresponse = { image: image?.filename, }; - Object.assign(cohortCreateDto, response); + Object.assign(cohortCreateDto, imgresponse); - return this.cohortService.updateCohort(cohortId, request, cohortCreateDto); + const result = await this.cohortService.updateCohort(cohortId, request, cohortCreateDto); + return response.status(result.statusCode).json(result); } @@ -187,19 +192,22 @@ export class CohortController { @ApiCreatedResponse({ description: "Cohort has been deleted successfully." }) @ApiBody({ type: CohortCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) public async updateCohortStatus( @Param("id") cohortId: string, @Req() request: Request, @Body() cohortCreateDto: CohortCreateDto, - @UploadedFile() image + @UploadedFile() image, + @Res() response: Response ) { - const response = { + const imgresponse = { image: image?.filename, - }; - Object.assign(cohortCreateDto, response); + } + Object.assign(cohortCreateDto, imgresponse); + const result = await this.cohortService.updateCohortStatus(cohortId); + return response.status(result.statusCode).json(result); + - return this.cohortService.updateCohortStatus(cohortId); } diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 0525834e..ecbec297 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -22,6 +22,7 @@ import APIResponse from "src/utils/response"; import { FieldValues } from "../fields/entities/fields-values.entity"; import { v4 as uuidv4 } from 'uuid'; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; +import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; @Injectable() export class CohortService { @@ -92,26 +93,16 @@ export class CohortService { result.cohortData.push(cohortData); } - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - result, - "OK" - ) - ); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: result, + }); } catch (error) { - return response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - "Something went wrong", - `Failure Retrieving Cohort Member. Error is: ${error}`, - "INTERNAL_SERVER_ERROR" - ) - ); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); } } @@ -177,15 +168,14 @@ export class CohortService { } return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.CREATED, message: "Ok.", data: response, }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "401", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -253,16 +243,15 @@ export class CohortService { } return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: "Ok.", data: { rowCount: response.affected, } }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "401", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -301,16 +290,15 @@ export class CohortService { const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: 'Ok.', totalCount, data: mappedResponse, }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "401", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -348,15 +336,13 @@ export class CohortService { SET "status" = false WHERE "cohortId" = $1`; const results = await this.cohortRepository.query(query, [cohortId]); - return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: "Cohort Deleted Successfully.", }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "401", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index f06e54dc..b9be4c06 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -24,13 +24,14 @@ import { UploadedFile, Headers, UseGuards, + Res, } from "@nestjs/common"; import { FieldsSearchDto } from "./dto/fields-search.dto"; import { Request } from "@nestjs/common"; import { FieldsDto } from "./dto/fields.dto"; import { FileInterceptor } from "@nestjs/platform-express"; import { diskStorage } from "multer"; - +import { Response } from "express"; import { FieldsAdapter } from "./fieldsadapter"; import { FieldValuesDto } from "./dto/field-values.dto"; import { FieldValuesSearchDto } from "./dto/field-values-search.dto"; @@ -53,22 +54,23 @@ export class FieldsController { @ApiCreatedResponse({ description: "Fields has been created successfully." }) @ApiBody({ type: FieldsDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) public async createFields( @Headers() headers, @Req() request: Request, - @Body() fieldsDto: FieldsDto + @Body() fieldsDto: FieldsDto, + @Res() response:Response, ) { let tenantid = headers["tenantid"]; const payload = { tenantId: tenantid, }; Object.assign(fieldsDto, payload); - - return this.fieldsService.createFields(request, fieldsDto); + const result = await this.fieldsService.createFields(request, fieldsDto); + return response.status(result.statusCode).json(result); } @@ -79,7 +81,7 @@ export class FieldsController { @ApiCreatedResponse({ description: "Fields list." }) @ApiBody({ type: FieldsSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) @@ -89,10 +91,12 @@ export class FieldsController { public async searchFields( @Headers() headers, @Req() request: Request, - @Body() fieldsSearchDto: FieldsSearchDto + @Body() fieldsSearchDto: FieldsSearchDto, + @Res() response:Response ) { let tenantid = headers["tenantid"]; - return this.fieldsService.searchFields(tenantid, request, fieldsSearchDto); + const result = await this.fieldsService.searchFields(tenantid, request, fieldsSearchDto); + return response.status(result.statusCode).json(result); } @@ -105,12 +109,15 @@ export class FieldsController { }) @ApiBody({ type: FieldValuesDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) public async createFieldValues( @Req() request: Request, - @Body() fieldValuesDto: FieldValuesDto + @Body() fieldValuesDto: FieldValuesDto, + @Res() response:Response ) { - return this.fieldsService.createFieldValues(request, fieldValuesDto); + + const result = await this.fieldsService.createFieldValues(request, fieldValuesDto); + return response.status(result.statusCode).json(result); } //search fields values @@ -119,15 +126,18 @@ export class FieldsController { @ApiCreatedResponse({ description: "Fields Values list." }) @ApiBody({ type: FieldValuesSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) public async searchFieldValues( @Req() request: Request, - @Body() fieldValuesSearchDto: FieldValuesSearchDto + @Body() fieldValuesSearchDto: FieldValuesSearchDto, + @Res()response:Response ) { - return this.fieldsService.searchFieldValues(request, fieldValuesSearchDto); + + const result = await this.fieldsService.searchFieldValues(request, fieldValuesSearchDto); + return response.status(result.statusCode).json(result); } diff --git a/src/fields/fields.service.ts b/src/fields/fields.service.ts index 3a0b9fc9..a170f465 100644 --- a/src/fields/fields.service.ts +++ b/src/fields/fields.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from "@nestjs/common"; +import { HttpStatus, Injectable } from "@nestjs/common"; import { FieldsDto } from "src/fields/dto/fields.dto"; import { FieldsSearchDto } from "src/fields/dto/fields-search.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; @@ -13,6 +13,7 @@ import { SuccessResponse } from "src/success-response"; import { off } from "process"; import APIResponse from "src/utils/response"; import { log } from "util"; +import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; @Injectable() export class FieldsService { @@ -43,15 +44,14 @@ export class FieldsService { let result = await this.fieldsRepository.save(fieldsData); return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.CREATED, message: "Ok.", data: result, }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -69,16 +69,15 @@ export class FieldsService { return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: 'Ok.', totalCount : getFieldValue.totalCount, data: getFieldValue.mappedResponse, }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -120,15 +119,14 @@ export class FieldsService { let result = await this.fieldsValuesRepository.save(fieldsData); return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.CREATED, message: "Ok.", data: result, }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", + return new ErrorResponseTypeOrm({ + statusCode:HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -144,16 +142,15 @@ export class FieldsService { const getFieldValue = await this.getSearchFieldValueData(offset, limit, whereClause) return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.OK, message: 'Ok.', totalCount: getFieldValue.totalCount, data: getFieldValue.mappedResponse, }); } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -203,7 +200,6 @@ export class FieldsService { return response; } catch (e) { - console.error(e); return new ErrorResponse({ errorCode: "400", errorMessage: e, diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 1326cbd8..7a17e93c 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -20,7 +20,7 @@ import { import { SunbirdUserToken, } from "../adapters/sunbirdrc/user.adapter"; -import { Request, Response } from "@nestjs/common"; +import { Request } from "@nestjs/common"; import { ApiTags, ApiBody, @@ -40,6 +40,7 @@ import { UserCreateDto } from "./dto/user-create.dto"; import { UserService } from "./user.service"; import { UserUpdateDTO } from "./dto/user-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { Response } from "express"; @ApiTags("User") @Controller("user") @UseGuards(JwtAuthGuard) @@ -61,7 +62,7 @@ export class UserController { * @since 1.6 */ @Get("/:userid/:role") - @UseInterceptors(CacheInterceptor) + // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -85,11 +86,13 @@ export class UserController { context:"USERS", contextType:role } - return this.userService.getUsersDetailsById(userData,response); + + const result = await this.userService.getUsersDetailsById(userData,response); + return response.status(result.statusCode).json(result); } @Get() - @UseInterceptors(CacheInterceptor) + // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -109,17 +112,19 @@ export class UserController { @ApiCreatedResponse({ description: "User has been created successfully." }) @ApiBody({ type: UserCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) async createUser( @Headers() headers, @Req() request: Request, - @Body() userCreateDto: UserCreateDto + @Body() userCreateDto: UserCreateDto, + @Res() response:Response ) { userCreateDto.tenantId = headers["tenantid"]; - return this.userService.createUser(request, userCreateDto); + const result = await this.userService.createUser(request, userCreateDto); + return response.status(result.statusCode).json(result); } @@ -139,15 +144,16 @@ export class UserController { ) { // userDto.tenantId = headers["tenantid"]; userUpdateDto.userId=userId; - return await this.userService.updateUser(userUpdateDto,response) + const result = await this.userService.updateUser(userUpdateDto,response) + return response.status(result.statusCode).json(result); } @Post("/search") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User list." }) - @ApiBody({ type: UserSearchDto }) + // @ApiBody({ type: UserSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) @@ -171,7 +177,7 @@ export class UserController { @ApiOkResponse({ description: "Password reset successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiBody({ type: Object }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) public async resetUserPassword( @Req() request: Request, @Body() diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 00e8943d..2bc432e0 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -22,6 +22,7 @@ import { v5 as uuidv5 } from 'uuid'; import { UUID } from 'typeorm/driver/mongodb/bson.typings'; import { AnyARecord } from 'dns'; import { CohortSearchDto } from 'src/cohort/dto/cohort-search.dto'; +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; @Injectable() @@ -65,20 +66,16 @@ export class UserService { customFieldsArray.push(customField); } result.userData['customFields'] = customFieldsArray; - return response - .status(HttpStatus.OK) - .send(APIResponse.success(apiId, result, 'OK')); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: result, + }); } catch (e) { - response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - 'Something went wrong In finding UserDetails', - e, - 'INTERNAL_SERVER_ERROR', - ), - ); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } } @@ -120,7 +117,6 @@ export class UserService { } if(userDto.customFields.length > 0){ for (let data of userDto.customFields) { - console.log(data); const result = await this.updateCustomFields(userDto.userId, data); if (result) { if (!updatedData['customFields']) @@ -129,20 +125,16 @@ export class UserService { } } } - return response - .status(HttpStatus.OK) - .send(APIResponse.success(apiId, updatedData, 'OK')); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok', + data: updatedData, + }); } catch (e) { - response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - 'Something went wrong In finding UserDetails', - e, - 'INTERNAL_SERVER_ERROR', - ), - ); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } } @@ -192,8 +184,8 @@ export class UserService { const token = keycloakResponse.data.access_token; let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) if(checkUserinKeyCloakandDb){ - return new ErrorResponse({ - errorCode: "400", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, errorMessage: "User Already Exists", }); } @@ -201,8 +193,8 @@ export class UserService { (error) => { errKeycloak = error.response?.data.errorMessage; - return new ErrorResponse({ - errorCode: "500", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: "Someting went wrong", }); } @@ -221,21 +213,21 @@ export class UserService { } let result = await this.updateCustomFields(userId,fieldData); if(!result) { - return new ErrorResponse({ - errorCode: "500", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: `Error is ${result}`, }); } } } return new SuccessResponse({ - statusCode: 200, + statusCode: HttpStatus.CREATED, message: "ok", data: result, }); } catch (e) { - return new ErrorResponse({ - errorCode: "500", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: `Error is ${e}`, }); } @@ -294,7 +286,6 @@ export class UserService { let result = await this.cohortMemberRepository.insert(cohortData); return result;; } catch (error) { - console.log(error); throw new Error(error) } } From 2157a389ee196c4c474d9d6fca9d86beff1f47cf Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 3 Apr 2024 17:28:21 +0530 Subject: [PATCH 175/408] Fix[uncommented auth guard] --- src/cohort/cohort.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index f26fea92..9e40eab4 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -41,7 +41,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; // import { FieldsService } from "../fields/fields.service"; @ApiTags("Cohort") @Controller("cohort") -// @UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard) export class CohortController { constructor( private cohortAdapter: CohortAdapter, From 63d43170facbe166bef71ff98631ae440b1dc4c5 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 17:28:37 +0530 Subject: [PATCH 176/408] chore : removed sunbird RC imports --- src/attendance/attendance.module.ts | 8 ++--- src/attendance/attendanceadapter.ts | 9 +----- src/comment/comment.module.ts | 2 -- src/comment/commentadapter.ts | 9 +----- src/configs/configsadapter.ts | 9 +----- src/configs/configuration.module.ts | 7 +---- src/group/group.module.ts | 3 +- src/group/groupadapter.ts | 9 +----- src/holiday/holiday.module.ts | 2 -- src/holiday/holidayadapter.ts | 9 +----- src/like/like.module.ts | 2 -- src/like/likeadapter.ts | 9 +----- src/school/school.module.ts | 3 +- src/school/schooladapter.ts | 9 +----- src/student/student.controller.ts | 7 ----- src/student/student.module.ts | 3 +- src/student/studentadapter.ts | 8 +---- src/user/user.controller.ts | 46 +++++++++++++---------------- src/user/user.module.ts | 11 ++----- src/user/useradapter.ts | 9 +----- src/worksheet/worksheet.module.ts | 4 +-- 21 files changed, 39 insertions(+), 139 deletions(-) diff --git a/src/attendance/attendance.module.ts b/src/attendance/attendance.module.ts index ee7ef942..02c3408a 100644 --- a/src/attendance/attendance.module.ts +++ b/src/attendance/attendance.module.ts @@ -3,7 +3,6 @@ import { AttendanceController } from "./attendance.controller"; import { ScheduleModule } from "@nestjs/schedule"; import { AttendaceAdapter } from "./attendanceadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { AttendanceService } from "./attendance.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { AttendanceEntity } from "./entities/attendance.entity"; @@ -12,10 +11,7 @@ import { Repository } from "typeorm"; const ttl = process.env.TTL as never; @Module({ imports: [ - TypeOrmModule.forFeature([ - AttendanceEntity - ]), - SunbirdModule, + TypeOrmModule.forFeature([AttendanceEntity]), HasuraModule, CacheModule.register({ ttl: ttl, @@ -23,6 +19,6 @@ const ttl = process.env.TTL as never; ScheduleModule.forRoot(), ], controllers: [AttendanceController], - providers: [AttendaceAdapter,AttendanceService,Repository], + providers: [AttendaceAdapter, AttendanceService, Repository], }) export class AttendanceModule {} diff --git a/src/attendance/attendanceadapter.ts b/src/attendance/attendanceadapter.ts index 1db4b36f..1927dbaf 100644 --- a/src/attendance/attendanceadapter.ts +++ b/src/attendance/attendanceadapter.ts @@ -1,14 +1,10 @@ import { Inject, Injectable } from "@nestjs/common"; import { IServicelocator } from "src/adapters/attendanceservicelocator"; import { AttendanceHasuraService } from "src/adapters/hasura/attendance.adapter"; -import { AttendanceService } from "src/adapters/sunbirdrc/attendance.adapter"; @Injectable() export class AttendaceAdapter { - constructor( - private hasuraProvider: AttendanceHasuraService, - private sunbirdProvider: AttendanceService - ) {} + constructor(private hasuraProvider: AttendanceHasuraService) {} buildAttenceAdapter(): IServicelocator { let adapter: IServicelocator; @@ -16,9 +12,6 @@ export class AttendaceAdapter { case "hasura": adapter = this.hasuraProvider; break; - case "sunbird": - adapter = this.sunbirdProvider; - break; } return adapter; } diff --git a/src/comment/comment.module.ts b/src/comment/comment.module.ts index 233e7666..2201998f 100644 --- a/src/comment/comment.module.ts +++ b/src/comment/comment.module.ts @@ -1,13 +1,11 @@ import { HttpModule } from "@nestjs/axios"; import { CacheModule, Module } from "@nestjs/common"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { CommentController } from "./comment.controller"; import { CommentAdapter } from "./commentadapter"; const ttl = process.env.TTL as never; @Module({ imports: [ - SunbirdModule, HasuraModule, HttpModule, CacheModule.register({ diff --git a/src/comment/commentadapter.ts b/src/comment/commentadapter.ts index c0f43a55..3a6953bd 100644 --- a/src/comment/commentadapter.ts +++ b/src/comment/commentadapter.ts @@ -1,21 +1,14 @@ import { Injectable } from "@nestjs/common"; import { IServicelocator } from "src/adapters/commentservicelocator"; import { HasuraCommentService } from "src/adapters/hasura/comment.adapter"; -import { SunbirdCommentService } from "src/adapters/sunbirdrc/comment.adapter"; @Injectable() export class CommentAdapter { - constructor( - private sunbirdProvider: SunbirdCommentService, - private hasuraProvider: HasuraCommentService - ) {} + constructor(private hasuraProvider: HasuraCommentService) {} buildCommentAdapter(): IServicelocator { let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; case "hasura": adapter = this.hasuraProvider; break; diff --git a/src/configs/configsadapter.ts b/src/configs/configsadapter.ts index 0fb6acc4..37f38ffd 100644 --- a/src/configs/configsadapter.ts +++ b/src/configs/configsadapter.ts @@ -1,21 +1,14 @@ import { Injectable } from "@nestjs/common"; import { IServicelocator } from "src/adapters/configservicelocator"; import { HasuraConfigService } from "src/adapters/hasura/config.adapter"; -import { SunbirdConfigService } from "src/adapters/sunbirdrc/config.adapter"; @Injectable() export class ConfigsAdapter { - constructor( - private sunbirdProvider: SunbirdConfigService, - private hasuraProvider: HasuraConfigService - ) {} + constructor(private hasuraProvider: HasuraConfigService) {} buildConfigsAdapter(): IServicelocator { let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; case "hasura": adapter = this.hasuraProvider; break; diff --git a/src/configs/configuration.module.ts b/src/configs/configuration.module.ts index a1736b24..06e5763c 100644 --- a/src/configs/configuration.module.ts +++ b/src/configs/configuration.module.ts @@ -1,9 +1,5 @@ import { CacheModule, Module } from "@nestjs/common"; import { ConfigController } from "./config.controller"; -import { - SunbirdConfigService, - SunbirdConfigToken, -} from "../adapters/sunbirdrc/config.adapter"; import { HttpModule } from "@nestjs/axios"; import { HasuraConfigService, @@ -11,11 +7,10 @@ import { } from "src/adapters/hasura/config.adapter"; import { ConfigsAdapter } from "./configsadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; + const ttl = process.env.TTL as never; @Module({ imports: [ - SunbirdModule, HasuraModule, HttpModule, CacheModule.register({ diff --git a/src/group/group.module.ts b/src/group/group.module.ts index e067b124..39c865d0 100644 --- a/src/group/group.module.ts +++ b/src/group/group.module.ts @@ -3,12 +3,11 @@ import { GroupController } from "./group.controller"; import { HttpModule } from "@nestjs/axios"; import { GroupAdapter } from "./groupadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; + const ttl = process.env.TTL as never; @Module({ imports: [ HttpModule, - SunbirdModule, HasuraModule, CacheModule.register({ ttl: ttl, diff --git a/src/group/groupadapter.ts b/src/group/groupadapter.ts index d1ca91b3..593aa6c6 100644 --- a/src/group/groupadapter.ts +++ b/src/group/groupadapter.ts @@ -1,21 +1,14 @@ import { Injectable } from "@nestjs/common"; import { IServicelocatorgroup } from "src/adapters/groupservicelocator"; import { HasuraGroupService } from "src/adapters/hasura/group.adapter"; -import { SunbirdGroupService } from "src/adapters/sunbirdrc/group.adapter"; @Injectable() export class GroupAdapter { - constructor( - private sunbirdProvider: SunbirdGroupService, - private hasuraProvider: HasuraGroupService - ) {} + constructor(private hasuraProvider: HasuraGroupService) {} buildGroupAdapter(): IServicelocatorgroup { let adapter: IServicelocatorgroup; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; case "hasura": adapter = this.hasuraProvider; break; diff --git a/src/holiday/holiday.module.ts b/src/holiday/holiday.module.ts index dd601931..03ed6a33 100644 --- a/src/holiday/holiday.module.ts +++ b/src/holiday/holiday.module.ts @@ -1,13 +1,11 @@ import { HttpModule } from "@nestjs/axios"; import { CacheModule, Module } from "@nestjs/common"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { HolidayController } from "./holiday.controller"; import { HolidayAdapter } from "./holidayadapter"; const ttl = process.env.TTL as never; @Module({ imports: [ - SunbirdModule, HasuraModule, HttpModule, CacheModule.register({ diff --git a/src/holiday/holidayadapter.ts b/src/holiday/holidayadapter.ts index 290603d4..c81f7cd8 100644 --- a/src/holiday/holidayadapter.ts +++ b/src/holiday/holidayadapter.ts @@ -1,21 +1,14 @@ import { Injectable } from "@nestjs/common"; import { HasuraHolidayService } from "src/adapters/hasura/holiday.adapter"; import { IServicelocator } from "src/adapters/holidayservicelocator"; -import { SunbirdHolidayService } from "src/adapters/sunbirdrc/holiday.adapter"; @Injectable() export class HolidayAdapter { - constructor( - private sunbirdProvider: SunbirdHolidayService, - private hasuraProvider: HasuraHolidayService - ) {} + constructor(private hasuraProvider: HasuraHolidayService) {} buildHolidayAdapter(): IServicelocator { let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; case "hasura": adapter = this.hasuraProvider; break; diff --git a/src/like/like.module.ts b/src/like/like.module.ts index 40b40103..caaffa0c 100644 --- a/src/like/like.module.ts +++ b/src/like/like.module.ts @@ -1,13 +1,11 @@ import { HttpModule } from "@nestjs/axios"; import { CacheModule, Module } from "@nestjs/common"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { LikeController } from "./like.controller"; import { LikeAdapter } from "./likeadapter"; const ttl = process.env.TTL as never; @Module({ imports: [ - SunbirdModule, HasuraModule, HttpModule, CacheModule.register({ diff --git a/src/like/likeadapter.ts b/src/like/likeadapter.ts index ace6540f..b6b9e02a 100644 --- a/src/like/likeadapter.ts +++ b/src/like/likeadapter.ts @@ -1,21 +1,14 @@ import { Injectable } from "@nestjs/common"; import { HasuraLikeService } from "src/adapters/hasura/like.adapter"; import { IServicelocator } from "src/adapters/likeservicelocator"; -import { SunbirdLikeService } from "src/adapters/sunbirdrc/like.adapter"; @Injectable() export class LikeAdapter { - constructor( - private sunbirdProvider: SunbirdLikeService, - private hasuraProvider: HasuraLikeService - ) {} + constructor(private hasuraProvider: HasuraLikeService) {} buildLikeAdapter(): IServicelocator { let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; case "hasura": adapter = this.hasuraProvider; break; diff --git a/src/school/school.module.ts b/src/school/school.module.ts index 0a8da4c8..ed268f2b 100644 --- a/src/school/school.module.ts +++ b/src/school/school.module.ts @@ -3,12 +3,11 @@ import { SchoolController } from "./school.controller"; import { HttpModule } from "@nestjs/axios"; import { SchoolAdapter } from "./schooladapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; + const ttl = process.env.TTL as never; @Module({ imports: [ HttpModule, - SunbirdModule, HasuraModule, CacheModule.register({ ttl: ttl, diff --git a/src/school/schooladapter.ts b/src/school/schooladapter.ts index 24e1cdcb..0dc24e95 100644 --- a/src/school/schooladapter.ts +++ b/src/school/schooladapter.ts @@ -1,21 +1,14 @@ import { Injectable } from "@nestjs/common"; import { SchoolHasuraService } from "src/adapters/hasura/school.adapter"; import { IServicelocator } from "src/adapters/schoolservicelocator"; -import { SchoolService } from "src/adapters/sunbirdrc/school.adapter"; @Injectable() export class SchoolAdapter { - constructor( - private sunbirdProvider: SchoolService, - private hasuraProvider: SchoolHasuraService - ) {} + constructor(private hasuraProvider: SchoolHasuraService) {} buildSchoolAdapter(): IServicelocator { let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; case "hasura": adapter = this.hasuraProvider; break; diff --git a/src/student/student.controller.ts b/src/student/student.controller.ts index 25deb27f..f03566b3 100644 --- a/src/student/student.controller.ts +++ b/src/student/student.controller.ts @@ -1,9 +1,3 @@ -import { StudentInterface } from "./interfaces/student.interface"; -import { - StudentService, - SunbirdStudentToken, -} from "../adapters/sunbirdrc/student.adapter"; - import { CacheInterceptor, CACHE_MANAGER, @@ -39,7 +33,6 @@ import { StudentAdapter } from "./studentadapter"; @Controller("student") export class StudentController { constructor( - private service: StudentService, @Inject(CACHE_MANAGER) private cacheManager, private studentAdapter: StudentAdapter diff --git a/src/student/student.module.ts b/src/student/student.module.ts index cd148368..12e8d839 100644 --- a/src/student/student.module.ts +++ b/src/student/student.module.ts @@ -2,12 +2,11 @@ import { CacheModule, Module } from "@nestjs/common"; import { StudentController } from "./student.controller"; import { HttpModule } from "@nestjs/axios"; import { StudentAdapter } from "./studentadapter"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; + const ttl = process.env.TTL as never; @Module({ imports: [ HttpModule, - SunbirdModule, CacheModule.register({ ttl: ttl, }), diff --git a/src/student/studentadapter.ts b/src/student/studentadapter.ts index b6879936..b72d5097 100644 --- a/src/student/studentadapter.ts +++ b/src/student/studentadapter.ts @@ -1,19 +1,13 @@ import { Injectable } from "@nestjs/common"; import { IServicelocator } from "src/adapters/studentservicelocator"; -import { StudentService } from "src/adapters/sunbirdrc/student.adapter"; @Injectable() export class StudentAdapter { - constructor( - private sunbirdProvider: StudentService - ) {} + constructor() {} buildStudentAdapter(): IServicelocator { let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; } return adapter; } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 1326cbd8..93b2bfb4 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -17,9 +17,7 @@ import { Patch, UseGuards, } from "@nestjs/common"; -import { - SunbirdUserToken, -} from "../adapters/sunbirdrc/user.adapter"; + import { Request, Response } from "@nestjs/common"; import { ApiTags, @@ -47,19 +45,18 @@ export class UserController { constructor( private readonly service: UserService, private userAdapter: UserAdapter, - private userService:UserService + private userService: UserService ) {} - /** - * Method to get The User Details and Custome Fields Data. - * - * @param userId $data User Id of User - * - * @return UserData Object containing all teh detals - * - * @since 1.6 - */ + * Method to get The User Details and Custome Fields Data. + * + * @param userId $data User Id of User + * + * @return UserData Object containing all teh detals + * + * @since 1.6 + */ @Get("/:userid/:role") @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @@ -74,18 +71,18 @@ export class UserController { public async getUser( @Headers() headers, @Param("userid") userId: string, - @Param("role") role:string, + @Param("role") role: string, @Req() request: Request, @Res() response: Response ) { // const tenantId = headers["tenantid"]; Can be Used In future // Context and ContextType can be taked from .env later - let userData = { - userId:userId, - context:"USERS", - contextType:role - } - return this.userService.getUsersDetailsById(userData,response); + let userData = { + userId: userId, + context: "USERS", + contextType: role, + }; + return this.userService.getUsersDetailsById(userData, response); } @Get() @@ -121,7 +118,6 @@ export class UserController { userCreateDto.tenantId = headers["tenantid"]; return this.userService.createUser(request, userCreateDto); } - @Patch("/:userid") @ApiBasicAuth("access-token") @@ -134,12 +130,12 @@ export class UserController { @Headers() headers, @Param("userid") userId: string, @Req() request: Request, - @Body() userUpdateDto:UserUpdateDTO, + @Body() userUpdateDto: UserUpdateDTO, @Res() response: Response ) { // userDto.tenantId = headers["tenantid"]; - userUpdateDto.userId=userId; - return await this.userService.updateUser(userUpdateDto,response) + userUpdateDto.userId = userId; + return await this.userService.updateUser(userUpdateDto, response); } @Post("/search") @@ -184,6 +180,4 @@ export class UserController { .buildUserAdapter() .resetUserPassword(request, reqBody.username, reqBody.newPassword); } - - } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index a5fa88ca..07bf2a8e 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -2,7 +2,6 @@ import { CacheModule, Module } from "@nestjs/common"; import { UserController } from "./user.controller"; import { HttpModule } from "@nestjs/axios"; import { UserAdapter } from "./useradapter"; -import { SunbirdModule } from "src/adapters/sunbirdrc/subnbird.module"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { TypeOrmModule } from "@nestjs/typeorm"; import { User } from "./entities/user-entity"; @@ -13,20 +12,14 @@ import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; const ttl = process.env.TTL as never; @Module({ imports: [ - TypeOrmModule.forFeature([ - User, - FieldValues, - Field, - CohortMembers - ]), + TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers]), HttpModule, - SunbirdModule, HasuraModule, CacheModule.register({ ttl: ttl, }), ], controllers: [UserController], - providers: [UserAdapter,UserService], + providers: [UserAdapter, UserService], }) export class UserModule {} diff --git a/src/user/useradapter.ts b/src/user/useradapter.ts index de7e88a8..774d7a6d 100644 --- a/src/user/useradapter.ts +++ b/src/user/useradapter.ts @@ -1,21 +1,14 @@ import { Injectable } from "@nestjs/common"; -import { UserService } from "src/adapters/sunbirdrc/user.adapter"; import { HasuraUserService } from "src/adapters/hasura/user.adapter"; import { IServicelocator } from "src/adapters/userservicelocator"; @Injectable() export class UserAdapter { - constructor( - private sunbirdProvider: UserService, - private hasuraProvider: HasuraUserService - ) {} + constructor(private hasuraProvider: HasuraUserService) {} buildUserAdapter(): IServicelocator { let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { - case "sunbird": - adapter = this.sunbirdProvider; - break; case "hasura": adapter = this.hasuraProvider; break; diff --git a/src/worksheet/worksheet.module.ts b/src/worksheet/worksheet.module.ts index 5d60fad4..8b2eb6d2 100644 --- a/src/worksheet/worksheet.module.ts +++ b/src/worksheet/worksheet.module.ts @@ -2,7 +2,7 @@ import { CacheModule, Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { WorksheetController } from "./worksheet.controller"; import { WorksheetService } from "src/adapters/hasura/worksheet.adapter"; -import { TemplateService } from "src/adapters/sunbirdrc/template.adapter"; + const ttl = process.env.TTL as never; @Module({ imports: [ @@ -12,6 +12,6 @@ const ttl = process.env.TTL as never; }), ], controllers: [WorksheetController], - providers: [WorksheetService, TemplateService], + providers: [WorksheetService], }) export class WorksheetModule {} From 74655d132ace5db32801edd4c8e2104861cff4ba Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 22:12:58 +0530 Subject: [PATCH 177/408] chore : removed old caching strategy --- src/announcements/announcements.module.ts | 11 ++--------- src/assessmentset/assessmentset.module.ts | 12 +++--------- src/attendance/attendance.module.ts | 6 +----- src/auth/auth.module.ts | 6 +----- src/cohort/cohort.module.ts | 15 +++------------ 5 files changed, 10 insertions(+), 40 deletions(-) diff --git a/src/announcements/announcements.module.ts b/src/announcements/announcements.module.ts index 8c052fcb..622c3c19 100644 --- a/src/announcements/announcements.module.ts +++ b/src/announcements/announcements.module.ts @@ -1,4 +1,4 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { ScheduleModule } from "@nestjs/schedule"; import { @@ -7,15 +7,8 @@ import { } from "../adapters/hasura/announcements.adapter"; import { AnnouncementsController } from "./announcements.controller"; -const ttl = process.env.TTL as never; @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ScheduleModule.forRoot(), - ], + imports: [HttpModule, ScheduleModule.forRoot()], providers: [ AnnouncementsService, { diff --git a/src/assessmentset/assessmentset.module.ts b/src/assessmentset/assessmentset.module.ts index 1e4f18af..f55d25f1 100644 --- a/src/assessmentset/assessmentset.module.ts +++ b/src/assessmentset/assessmentset.module.ts @@ -1,17 +1,11 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { ScheduleModule } from "@nestjs/schedule"; import { AssessmentsetController } from "./assessmentset.controller"; import { AssessmentsetService } from "src/adapters/hasura/assessmentset.adapter"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ScheduleModule.forRoot(), - ], + imports: [HttpModule, ScheduleModule.forRoot()], controllers: [AssessmentsetController], providers: [AssessmentsetService], }) diff --git a/src/attendance/attendance.module.ts b/src/attendance/attendance.module.ts index 02c3408a..150b67b3 100644 --- a/src/attendance/attendance.module.ts +++ b/src/attendance/attendance.module.ts @@ -1,4 +1,4 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { AttendanceController } from "./attendance.controller"; import { ScheduleModule } from "@nestjs/schedule"; import { AttendaceAdapter } from "./attendanceadapter"; @@ -8,14 +8,10 @@ import { TypeOrmModule } from "@nestjs/typeorm"; import { AttendanceEntity } from "./entities/attendance.entity"; import { Repository } from "typeorm"; -const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([AttendanceEntity]), HasuraModule, - CacheModule.register({ - ttl: ttl, - }), ScheduleModule.forRoot(), ], controllers: [AttendanceController], diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 36417ada..ef1d92e1 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,4 +1,4 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { AuthController } from "./auth.controller"; import { AuthService } from "./auth.service"; @@ -11,14 +11,10 @@ import { Field } from "src/user/entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { KeycloakService } from "src/common/utils/keycloak.service"; -const ttl = process.env.TTL as never; @Module({ imports: [ TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers]), HttpModule, - CacheModule.register({ - ttl: ttl, - }), ], controllers: [AuthController], providers: [AuthService, JwtStrategy, KeycloakService, UserService], diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 9e659949..5b88a555 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -1,4 +1,4 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { CohortController } from "./cohort.controller"; import { HttpModule } from "@nestjs/axios"; import { CohortAdapter } from "./cohortadapter"; @@ -10,23 +10,14 @@ import { FieldsService } from "../fields/fields.service"; import { Fields } from "../fields/entities/fields.entity"; import { FieldValues } from "../fields/entities/fields-values.entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; -const ttl = process.env.TTL as never; + @Module({ imports: [ - TypeOrmModule.forFeature([ - Cohort, - FieldValues, - Fields, - CohortMembers - ]), + TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers]), HttpModule, HasuraModule, - CacheModule.register({ - ttl: ttl, - }), ], controllers: [CohortController], providers: [CohortAdapter, CohortService, FieldsService], }) export class CohortModule {} - From 56477b166b94dd77fb43b605433d9451e8b5af19 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 3 Apr 2024 22:51:20 +0530 Subject: [PATCH 178/408] chore : removed old caching strategy and cache interceptors --- src/Question/question.controller.ts | 15 ++-- src/Question/question.module.ts | 11 +-- src/announcements/announcements.controller.ts | 9 +-- src/assessmentset/assessmentset.controller.ts | 4 +- src/attendance/attendance.controller.ts | 79 ++++++++++--------- src/cohort/cohort.controller.ts | 56 +++++++------ src/cohortMembers/cohortMembers.controller.ts | 11 +-- src/cohortMembers/cohortMembers.module.ts | 7 +- src/comment/comment.controller.ts | 3 +- src/comment/comment.module.ts | 10 +-- src/configs/configuration.module.ts | 9 +-- src/course/course.controller.ts | 11 ++- src/course/course.module.ts | 9 +-- .../courseTracking.controller.ts | 6 +- src/courseTracking/courseTracking.module.ts | 7 +- src/fields/fields.controller.ts | 56 ++++++------- src/fields/fields.module.ts | 5 +- src/group/group.controller.ts | 9 +-- src/group/group.module.ts | 11 +-- .../groupMembership.controller.ts | 3 +- src/groupMembership/groupMembership.module.ts | 12 +-- src/holiday/holiday.controller.ts | 5 +- src/holiday/holiday.module.ts | 10 +-- src/like/like.controller.ts | 7 +- src/like/like.module.ts | 10 +-- .../mentorTracking.controller.ts | 4 +- src/mentorTracking/mentorTracking.module.ts | 9 +-- .../monitorTracking.controller.ts | 3 +- src/monitorTracking/monitorTracking.module.ts | 9 +-- src/role/role.controller.ts | 3 +- src/role/role.module.ts | 11 +-- src/school/school.controller.ts | 3 +- src/school/school.module.ts | 9 +-- src/student/student.controller.ts | 15 +--- src/student/student.module.ts | 10 +-- .../trackassessment.controller.ts | 3 +- src/trackAssessment/trackassessment.module.ts | 10 +-- src/user/user.controller.ts | 35 ++++---- src/user/user.module.ts | 5 +- src/workHistory/workHistory.controller.ts | 3 +- src/workHistory/workHistory.module.ts | 10 +-- src/worksheet/worksheet.controller.ts | 3 +- src/worksheet/worksheet.module.ts | 8 +- 43 files changed, 192 insertions(+), 336 deletions(-) diff --git a/src/Question/question.controller.ts b/src/Question/question.controller.ts index 0dfa1f04..9b5990ea 100644 --- a/src/Question/question.controller.ts +++ b/src/Question/question.controller.ts @@ -8,7 +8,6 @@ import { ApiTags, } from "@nestjs/swagger"; import { - CacheInterceptor, ClassSerializerInterceptor, Controller, Get, @@ -42,7 +41,7 @@ export class QuestionController { ) {} @Get(":adapter/search") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) //@ApiBasicAuth("access-token") @ApiOkResponse({ description: "Get all Questions detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -82,7 +81,7 @@ export class QuestionController { } @Get(":adapter/questionIds") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) //@ApiBasicAuth("access-token") @ApiOkResponse({ description: "Get all Questions detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -101,7 +100,7 @@ export class QuestionController { } @Get(":adapter/subjectlist") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiOkResponse({ description: "Get all subject list" }) @ApiQuery({ name: "gradeLevel", required: true }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -115,7 +114,7 @@ export class QuestionController { } @Get(":adapter/topicslist") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiOkResponse({ description: "Get all subject list" }) @ApiQuery({ name: "subject", required: true }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -129,7 +128,7 @@ export class QuestionController { } @Get(":adapter/questionid") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) // @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Get Questions detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -145,7 +144,7 @@ export class QuestionController { } @Get(":adapter/competencieslist") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) //@ApiBasicAuth("access-token") @ApiOkResponse({ description: "Get all competencies list." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -163,7 +162,7 @@ export class QuestionController { } @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Question detail." }) @SerializeOptions({ diff --git a/src/Question/question.module.ts b/src/Question/question.module.ts index 2f725705..6c6a008d 100644 --- a/src/Question/question.module.ts +++ b/src/Question/question.module.ts @@ -1,4 +1,4 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { QuestionController } from "./question.controller"; import { @@ -9,14 +9,9 @@ import { HasuraQuestionToken, QuestionService, } from "src/adapters/hasura/question.adapter"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [QuestionController], providers: [ QumlQuestionService, diff --git a/src/announcements/announcements.controller.ts b/src/announcements/announcements.controller.ts index 05b3f4ad..8b53f7d4 100644 --- a/src/announcements/announcements.controller.ts +++ b/src/announcements/announcements.controller.ts @@ -1,6 +1,5 @@ import { Body, - CacheInterceptor, ClassSerializerInterceptor, Controller, Delete, @@ -12,10 +11,8 @@ import { Query, Req, Request, - SerializeOptions, UseInterceptors, } from "@nestjs/common"; -import { FileInterceptor } from "@nestjs/platform-express"; import { ApiBasicAuth, ApiBody, @@ -40,7 +37,7 @@ export class AnnouncementsController { ) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Get announcement detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -52,7 +49,7 @@ export class AnnouncementsController { } @Get("") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Get announcements" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -101,7 +98,7 @@ export class AnnouncementsController { } @Delete("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Deleted the announcement " }) public async deleteAnnouncement( diff --git a/src/assessmentset/assessmentset.controller.ts b/src/assessmentset/assessmentset.controller.ts index c6d91a9d..4ecfb8f1 100644 --- a/src/assessmentset/assessmentset.controller.ts +++ b/src/assessmentset/assessmentset.controller.ts @@ -15,12 +15,10 @@ import { SerializeOptions, Req, Request, - CacheInterceptor, Post, Body, Query, } from "@nestjs/common"; -import { AssessmentSetSearchDto } from "./dto/assessmentset-search-dto"; import { AssessmentsetDto } from "./dto/assessmentset.dto"; import { AssessmentsetService } from "src/adapters/hasura/assessmentset.adapter"; @@ -44,7 +42,7 @@ export class AssessmentsetController { return this.service.createAssessmentSet(request, assessmentsetDto); } @Get("assessmentset/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Assessment set detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 4c9a87fe..932ac702 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -1,4 +1,3 @@ -// import { AttendanceService } from 'src/adapters/sunbirdrc/attendance.adapter'; import { ApiTags, ApiBody, @@ -7,7 +6,6 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiConsumes, - ApiQuery, ApiHeader, } from "@nestjs/swagger"; import { @@ -23,8 +21,6 @@ import { Req, Request, UploadedFile, - CacheInterceptor, - Query, Headers, UsePipes, ValidationPipe, @@ -36,27 +32,24 @@ import { FileInterceptor } from "@nestjs/platform-express"; import { diskStorage } from "multer"; import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; import { AttendanceSearchDto } from "./dto/attendance-search.dto"; -import { AttendanceHasuraService } from "src/adapters/hasura/attendance.adapter"; import { AttendaceAdapter } from "./attendanceadapter"; import { AttendanceDateDto } from "./dto/attendance-date.dto"; -import { AttendanceService } from './attendance.service'; +import { AttendanceService } from "./attendance.service"; import { AttendanceStatsDto } from "./dto/attendance-stats.dto"; import { Response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; - @ApiTags("Attendance") @Controller("attendance") @UseGuards(JwtAuthGuard) export class AttendanceController { constructor( - private service: AttendanceHasuraService, private attendaceAdapter: AttendaceAdapter, private attendaceService: AttendanceService - ) { } + ) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Attendance detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -77,7 +70,6 @@ export class AttendanceController { .getAttendance(tenantid, attendanceId, request); } - @Post() @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @@ -104,13 +96,16 @@ export class AttendanceController { @Headers() headers, @Req() request: Request, @Body() attendanceDto: AttendanceDto, - @Res() response:Response, + @Res() response: Response, @UploadedFile() image ) { attendanceDto.tenantId = headers["tenantid"]; attendanceDto.image = image?.filename; - const result = await this.attendaceService.updateAttendanceRecord(request, attendanceDto); - return response.status(result.statusCode).json(result); + const result = await this.attendaceService.updateAttendanceRecord( + request, + attendanceDto + ); + return response.status(result.statusCode).json(result); } @Put("/:id") @@ -135,17 +130,19 @@ export class AttendanceController { @Param("id") attendanceId: string, @Req() request: Request, @Body() attendanceDto: AttendanceDto, - @Res() response:Response, + @Res() response: Response, @UploadedFile() image ) { const Imageresponse = { image: image?.filename, }; Object.assign(attendanceDto, response); - const result = await this.attendaceService - .updateAttendance(attendanceId, request, attendanceDto); - return response.status(result.statusCode).json(result); - + const result = await this.attendaceService.updateAttendance( + attendanceId, + request, + attendanceDto + ); + return response.status(result.statusCode).json(result); } @Post("/search") @ApiBasicAuth("access-token") @@ -164,13 +161,16 @@ export class AttendanceController { @Headers() headers, @Req() request: Request, @Body() studentSearchDto: AttendanceSearchDto, - @Res() response:Response + @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.attendaceService - .searchAttendance(tenantid, request, studentSearchDto); - return response.status(result.statusCode).json(result); + const result = await this.attendaceService.searchAttendance( + tenantid, + request, + studentSearchDto + ); + return response.status(result.statusCode).json(result); } @Post("/bydate") @@ -184,12 +184,16 @@ export class AttendanceController { public async attendanceFilter( @Headers() headers, @Req() request: Request, - @Res() response:Response, + @Res() response: Response, @Body() attendanceDateDto: AttendanceDateDto ) { const tenantId = headers["tenantid"]; - const result = await this.attendaceService.attendanceByDate(tenantId, request, attendanceDateDto); - return response.status(result.statusCode).json(result); + const result = await this.attendaceService.attendanceByDate( + tenantId, + request, + attendanceDateDto + ); + return response.status(result.statusCode).json(result); } @Post("bulkAttendance") @@ -206,13 +210,16 @@ export class AttendanceController { public async multipleAttendance( @Headers() headers, @Req() request: Request, - @Res() response:Response, + @Res() response: Response, @Body() attendanceDtos: BulkAttendanceDTO ) { let tenantId = headers["tenantid"]; - const result = await this.attendaceService - .multipleAttendance(tenantId, request, attendanceDtos); - return response.status(result.statusCode).json(result); + const result = await this.attendaceService.multipleAttendance( + tenantId, + request, + attendanceDtos + ); + return response.status(result.statusCode).json(result); } @Post("/report") @@ -227,20 +234,21 @@ export class AttendanceController { public async report( @Headers() headers, @Req() request: Request, - @Res() response:Response, + @Res() response: Response, @Body() attendanceStatsDto: AttendanceStatsDto ) { let tenantid = headers["tenantid"]; - const result = await this.attendaceService - .attendanceReport(attendanceStatsDto); - return response.status(result.statusCode).json(result); + const result = await this.attendaceService.attendanceReport( + attendanceStatsDto + ); + return response.status(result.statusCode).json(result); } /** No longer required in Shiksha 2.0 */ /* @Get("usersegment/:attendance") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) // @ApiBasicAuth("access-token") @ApiOkResponse({ description: " Ok." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -255,5 +263,4 @@ export class AttendanceController { return await this.service.userSegment(groupId, attendance, date, request); } */ - } diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index a6728723..e716a82f 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -1,7 +1,6 @@ import { ApiTags, ApiBody, - ApiOkResponse, ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, @@ -16,11 +15,8 @@ import { Put, Param, UseInterceptors, - ClassSerializerInterceptor, SerializeOptions, Req, - Query, - CacheInterceptor, UploadedFile, Res, Headers, @@ -31,7 +27,6 @@ import { } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; -import { CohortDto } from "./dto/cohort.dto"; import { FileInterceptor } from "@nestjs/platform-express"; import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; import { diskStorage } from "multer"; @@ -40,15 +35,12 @@ import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortService } from "./cohort.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; -// import { FieldsService } from "../fields/fields.service"; + @ApiTags("Cohort") @Controller("cohort") @UseGuards(JwtAuthGuard) export class CohortController { - constructor( - private cohortAdapter: CohortAdapter, - private readonly cohortService: CohortService - ) { } + constructor(private readonly cohortService: CohortService) {} //create cohort @Post() @ApiConsumes("multipart/form-data") @@ -74,7 +66,7 @@ export class CohortController { @Req() request: Request, @Body() cohortCreateDto: CohortCreateDto, @UploadedFile() image, - @Res() response: Response, + @Res() response: Response ) { let tenantid = headers["tenantid"]; const payload = { @@ -82,12 +74,14 @@ export class CohortController { tenantId: tenantid, }; Object.assign(cohortCreateDto, payload); - const result = await this.cohortService.createCohort(request, cohortCreateDto); + const result = await this.cohortService.createCohort( + request, + cohortCreateDto + ); return response.status(result.statusCode).json(result); } @Get("cohortList/:id") - // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -104,12 +98,16 @@ export class CohortController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.cohortService.getCohortList(tenantid, id, request, response); + const result = await this.cohortService.getCohortList( + tenantid, + id, + request, + response + ); return response.status(result.statusCode).json(result); } @Get("cohortDetails/:id") - // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort details" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -126,7 +124,12 @@ export class CohortController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - return this.cohortService.getCohortsDetails(tenantid, cohortId, request, response); + return this.cohortService.getCohortsDetails( + tenantid, + cohortId, + request, + response + ); } // search @@ -147,10 +150,14 @@ export class CohortController { @Headers() headers, @Req() request: Request, @Body() cohortSearchDto: CohortSearchDto, - @Res() response: Response, + @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.cohortService.searchCohort(tenantid, request, cohortSearchDto); + const result = await this.cohortService.searchCohort( + tenantid, + request, + cohortSearchDto + ); return response.status(result.statusCode).json(result); } @@ -183,9 +190,12 @@ export class CohortController { }; Object.assign(cohortCreateDto, imgresponse); - const result = await this.cohortService.updateCohort(cohortId, request, cohortCreateDto); + const result = await this.cohortService.updateCohort( + cohortId, + request, + cohortCreateDto + ); return response.status(result.statusCode).json(result); - } //delete cohort @@ -205,13 +215,9 @@ export class CohortController { ) { const imgresponse = { image: image?.filename, - } + }; Object.assign(cohortCreateDto, imgresponse); const result = await this.cohortService.updateCohortStatus(cohortId); return response.status(result.statusCode).json(result); - - - } - } diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 0dd5cad2..bf9e65d6 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -5,7 +5,6 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiHeader, - ApiConsumes, } from "@nestjs/swagger"; import { Controller, @@ -19,7 +18,6 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, Headers, Res, UseGuards, @@ -37,10 +35,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @Controller("cohortmembers") @UseGuards(JwtAuthGuard) export class CohortMembersController { - constructor( - private cohortMembersAdapter: CohortMembersAdapter, - private readonly cohortMembersService: CohortMembersService - ) {} + constructor(private readonly cohortMembersService: CohortMembersService) {} //create cohort members @Post() @@ -75,7 +70,7 @@ export class CohortMembersController { //get cohort members @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -100,7 +95,7 @@ export class CohortMembersController { ); } - search + search; @Post("/search") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members list." }) diff --git a/src/cohortMembers/cohortMembers.module.ts b/src/cohortMembers/cohortMembers.module.ts index 09252024..191c7389 100644 --- a/src/cohortMembers/cohortMembers.module.ts +++ b/src/cohortMembers/cohortMembers.module.ts @@ -1,4 +1,4 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { CohortMembersController } from "./cohortMembers.controller"; import { HttpModule } from "@nestjs/axios"; import { CohortMembersAdapter } from "./cohortMembersadapter"; @@ -6,15 +6,12 @@ import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { TypeOrmModule } from "@nestjs/typeorm"; import { CohortMembers } from "./entities/cohort-member.entity"; import { CohortMembersService } from "./cohortMember.service"; -const ttl = process.env.TTL as never; + @Module({ imports: [ TypeOrmModule.forFeature([CohortMembers]), HttpModule, HasuraModule, - CacheModule.register({ - ttl: ttl, - }), ], controllers: [CohortMembersController], providers: [CohortMembersAdapter, CohortMembersService], diff --git a/src/comment/comment.controller.ts b/src/comment/comment.controller.ts index e197a797..71c9cb5d 100644 --- a/src/comment/comment.controller.ts +++ b/src/comment/comment.controller.ts @@ -9,7 +9,6 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, } from "@nestjs/common"; import { ApiTags, @@ -30,7 +29,7 @@ export class CommentController implements IServicelocator { constructor(private commentAdapter: CommentAdapter) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Comment detail." }) @SerializeOptions({ diff --git a/src/comment/comment.module.ts b/src/comment/comment.module.ts index 2201998f..ec978896 100644 --- a/src/comment/comment.module.ts +++ b/src/comment/comment.module.ts @@ -3,15 +3,9 @@ import { CacheModule, Module } from "@nestjs/common"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { CommentController } from "./comment.controller"; import { CommentAdapter } from "./commentadapter"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HasuraModule, - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HasuraModule, HttpModule], controllers: [CommentController], providers: [CommentAdapter], }) diff --git a/src/configs/configuration.module.ts b/src/configs/configuration.module.ts index 06e5763c..b883bbd7 100644 --- a/src/configs/configuration.module.ts +++ b/src/configs/configuration.module.ts @@ -8,15 +8,8 @@ import { import { ConfigsAdapter } from "./configsadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -const ttl = process.env.TTL as never; @Module({ - imports: [ - HasuraModule, - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HasuraModule, HttpModule], controllers: [ConfigController], providers: [ConfigsAdapter], }) diff --git a/src/course/course.controller.ts b/src/course/course.controller.ts index 3e24859f..4709e83a 100644 --- a/src/course/course.controller.ts +++ b/src/course/course.controller.ts @@ -5,7 +5,6 @@ import { ApiTags, } from "@nestjs/swagger"; import { - CacheInterceptor, ClassSerializerInterceptor, Controller, Get, @@ -24,11 +23,11 @@ import { IServicelocator } from "src/adapters/courseservicelocator"; @Controller("course") export class CourseController { constructor( - @Inject(DikshaCourseToken) private dikshaProvider: IServicelocator, + @Inject(DikshaCourseToken) private dikshaProvider: IServicelocator ) {} @Get(":adapter/search") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiOkResponse({ description: "Get all Course detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiQuery({ name: "subject", required: false }) @@ -58,7 +57,7 @@ export class CourseController { } @Get(":adapter/courseIds") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiOkResponse({ description: "Get all Course detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiQuery({ name: "courseIds", required: false }) @@ -72,7 +71,7 @@ export class CourseController { } } @Get(":adapter/hierarchy/courseid") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiOkResponse({ description: "Get Course detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiQuery({ name: "courseId", required: false }) @@ -87,7 +86,7 @@ export class CourseController { } @Get(":adapter/content/courseid") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiOkResponse({ description: "Get Course detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiQuery({ name: "courseId", required: false }) diff --git a/src/course/course.module.ts b/src/course/course.module.ts index 67325a8a..64eb291c 100644 --- a/src/course/course.module.ts +++ b/src/course/course.module.ts @@ -6,14 +6,9 @@ import { DikshaCourseService, DikshaCourseToken, } from "src/adapters/diksha/dikshaCourse.adapter"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [CourseController], providers: [{ provide: DikshaCourseToken, useClass: DikshaCourseService }], }) diff --git a/src/courseTracking/courseTracking.controller.ts b/src/courseTracking/courseTracking.controller.ts index 0cc586bd..55b5f402 100644 --- a/src/courseTracking/courseTracking.controller.ts +++ b/src/courseTracking/courseTracking.controller.ts @@ -3,9 +3,7 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, - ApiBody, ApiQuery, - ApiOkResponse, } from "@nestjs/swagger"; import { Controller, @@ -16,9 +14,7 @@ import { SerializeOptions, Req, Request, - CacheInterceptor, Post, - Body, Query, Put, } from "@nestjs/common"; @@ -73,7 +69,7 @@ export class CourseTrackingController { } @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Course Tracking detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/courseTracking/courseTracking.module.ts b/src/courseTracking/courseTracking.module.ts index 0efb90cd..462d9712 100644 --- a/src/courseTracking/courseTracking.module.ts +++ b/src/courseTracking/courseTracking.module.ts @@ -1,15 +1,12 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { ScheduleModule } from "@nestjs/schedule"; import { CourseTrackingService } from "src/adapters/hasura/courseTracking.adapter"; import { CourseTrackingController } from "./courseTracking.controller"; -const ttl = process.env.TTL as never; + @Module({ imports: [ HttpModule, - CacheModule.register({ - ttl: ttl, - }), ScheduleModule.forRoot(), ], controllers: [CourseTrackingController], diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index b9be4c06..c9e7e1d8 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -1,27 +1,17 @@ import { ApiTags, ApiBody, - ApiOkResponse, ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, - ApiConsumes, ApiHeader, } from "@nestjs/swagger"; import { Controller, - Get, Post, Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, SerializeOptions, Req, - Query, - CacheInterceptor, - UploadedFile, Headers, UseGuards, Res, @@ -38,14 +28,14 @@ import { FieldValuesSearchDto } from "./dto/field-values-search.dto"; import { FieldsService } from "./fields.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; - @ApiTags("Fields") @Controller("fields") @UseGuards(JwtAuthGuard) export class FieldsController { - constructor(private fieldsAdapter: FieldsAdapter, + constructor( + private fieldsAdapter: FieldsAdapter, private readonly fieldsService: FieldsService - ) { } + ) {} //fields //create fields @@ -62,7 +52,7 @@ export class FieldsController { @Headers() headers, @Req() request: Request, @Body() fieldsDto: FieldsDto, - @Res() response:Response, + @Res() response: Response ) { let tenantid = headers["tenantid"]; const payload = { @@ -70,11 +60,9 @@ export class FieldsController { }; Object.assign(fieldsDto, payload); const result = await this.fieldsService.createFields(request, fieldsDto); - return response.status(result.statusCode).json(result); - + return response.status(result.statusCode).json(result); } - //search @Post("/search") @ApiBasicAuth("access-token") @@ -92,14 +80,17 @@ export class FieldsController { @Headers() headers, @Req() request: Request, @Body() fieldsSearchDto: FieldsSearchDto, - @Res() response:Response + @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.fieldsService.searchFields(tenantid, request, fieldsSearchDto); - return response.status(result.statusCode).json(result); + const result = await this.fieldsService.searchFields( + tenantid, + request, + fieldsSearchDto + ); + return response.status(result.statusCode).json(result); } - //field values //create fields values @Post("/values") @@ -113,11 +104,13 @@ export class FieldsController { public async createFieldValues( @Req() request: Request, @Body() fieldValuesDto: FieldValuesDto, - @Res() response:Response + @Res() response: Response ) { - - const result = await this.fieldsService.createFieldValues(request, fieldValuesDto); - return response.status(result.statusCode).json(result); + const result = await this.fieldsService.createFieldValues( + request, + fieldValuesDto + ); + return response.status(result.statusCode).json(result); } //search fields values @@ -133,13 +126,12 @@ export class FieldsController { public async searchFieldValues( @Req() request: Request, @Body() fieldValuesSearchDto: FieldValuesSearchDto, - @Res()response:Response + @Res() response: Response ) { - - const result = await this.fieldsService.searchFieldValues(request, fieldValuesSearchDto); - return response.status(result.statusCode).json(result); + const result = await this.fieldsService.searchFieldValues( + request, + fieldValuesSearchDto + ); + return response.status(result.statusCode).json(result); } - - - } diff --git a/src/fields/fields.module.ts b/src/fields/fields.module.ts index 219a6f29..d6d5e348 100644 --- a/src/fields/fields.module.ts +++ b/src/fields/fields.module.ts @@ -7,16 +7,13 @@ import { Fields } from "./entities/fields.entity"; import { FieldValues } from "./entities/fields-values.entity"; import { TypeOrmModule } from "@nestjs/typeorm"; import { FieldsService } from "./fields.service"; -const ttl = process.env.TTL as never; + @Module({ imports: [ TypeOrmModule.forFeature([Fields]), TypeOrmModule.forFeature([FieldValues]), HttpModule, HasuraModule, - CacheModule.register({ - ttl: ttl, - }), ], controllers: [FieldsController], providers: [FieldsAdapter, FieldsService], diff --git a/src/group/group.controller.ts b/src/group/group.controller.ts index 9257bdb8..08d23bbb 100644 --- a/src/group/group.controller.ts +++ b/src/group/group.controller.ts @@ -19,7 +19,6 @@ import { SerializeOptions, Req, Query, - CacheInterceptor, UploadedFile, } from "@nestjs/common"; import { GroupSearchDto } from "./dto/group-search.dto"; @@ -37,7 +36,7 @@ export class GroupController { constructor(private groupAdapter: GroupAdapter) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Group detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -128,7 +127,7 @@ export class GroupController { } @Get(":groupId/participants") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Group detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -143,7 +142,7 @@ export class GroupController { } @Get("participant/:userId") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Group detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -158,7 +157,7 @@ export class GroupController { } @Get(":groupId/child") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Group detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/group/group.module.ts b/src/group/group.module.ts index 39c865d0..f56c5845 100644 --- a/src/group/group.module.ts +++ b/src/group/group.module.ts @@ -1,18 +1,11 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { GroupController } from "./group.controller"; import { HttpModule } from "@nestjs/axios"; import { GroupAdapter } from "./groupadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -const ttl = process.env.TTL as never; @Module({ - imports: [ - HttpModule, - HasuraModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule, HasuraModule], controllers: [GroupController], providers: [GroupAdapter], }) diff --git a/src/groupMembership/groupMembership.controller.ts b/src/groupMembership/groupMembership.controller.ts index e0fe4ff2..dfa70aa9 100644 --- a/src/groupMembership/groupMembership.controller.ts +++ b/src/groupMembership/groupMembership.controller.ts @@ -16,7 +16,6 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, Request, } from "@nestjs/common"; @@ -30,7 +29,7 @@ export class GroupMembershipController { constructor(private service: GroupMembershipService) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Group Membership detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/groupMembership/groupMembership.module.ts b/src/groupMembership/groupMembership.module.ts index 2782aeb0..3ce449f6 100644 --- a/src/groupMembership/groupMembership.module.ts +++ b/src/groupMembership/groupMembership.module.ts @@ -1,16 +1,10 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; - import { GroupMembershipController } from "./groupMembership.controller"; import { GroupMembershipService } from "src/adapters/hasura/groupMembership.adapter"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [GroupMembershipController], providers: [GroupMembershipService], }) diff --git a/src/holiday/holiday.controller.ts b/src/holiday/holiday.controller.ts index 52fda8b4..170b9694 100644 --- a/src/holiday/holiday.controller.ts +++ b/src/holiday/holiday.controller.ts @@ -9,7 +9,6 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, Query, } from "@nestjs/common"; import { @@ -31,7 +30,7 @@ export class HolidayController { constructor(private holidayProvider: HolidayAdapter) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Holiday detail." }) @SerializeOptions({ @@ -92,7 +91,7 @@ export class HolidayController { } @Get("") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: " Ok." }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/holiday/holiday.module.ts b/src/holiday/holiday.module.ts index 03ed6a33..a6bb8b57 100644 --- a/src/holiday/holiday.module.ts +++ b/src/holiday/holiday.module.ts @@ -3,15 +3,9 @@ import { CacheModule, Module } from "@nestjs/common"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { HolidayController } from "./holiday.controller"; import { HolidayAdapter } from "./holidayadapter"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HasuraModule, - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HasuraModule, HttpModule], controllers: [HolidayController], providers: [HolidayAdapter], }) diff --git a/src/like/like.controller.ts b/src/like/like.controller.ts index 67f4a14a..68cb10c8 100644 --- a/src/like/like.controller.ts +++ b/src/like/like.controller.ts @@ -9,7 +9,6 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, Query, Delete, } from "@nestjs/common"; @@ -32,7 +31,7 @@ export class LikeController { constructor(private likeAdapter: LikeAdapter) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Like detail." }) @SerializeOptions({ @@ -90,7 +89,7 @@ export class LikeController { } @Post("/getAllLikes") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "All Like." }) @ApiQuery({ name: "contextId" }) @@ -106,7 +105,7 @@ export class LikeController { } @Delete("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Delete like. " }) public async deleteLike( diff --git a/src/like/like.module.ts b/src/like/like.module.ts index caaffa0c..72700db7 100644 --- a/src/like/like.module.ts +++ b/src/like/like.module.ts @@ -3,15 +3,9 @@ import { CacheModule, Module } from "@nestjs/common"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { LikeController } from "./like.controller"; import { LikeAdapter } from "./likeadapter"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HasuraModule, - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HasuraModule, HttpModule], controllers: [LikeController], providers: [LikeAdapter], }) diff --git a/src/mentorTracking/mentorTracking.controller.ts b/src/mentorTracking/mentorTracking.controller.ts index 7ffa394e..b8c15972 100644 --- a/src/mentorTracking/mentorTracking.controller.ts +++ b/src/mentorTracking/mentorTracking.controller.ts @@ -9,11 +9,9 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, Query, ValidationPipe, UsePipes, - Header, UploadedFile, } from "@nestjs/common"; import { @@ -39,7 +37,7 @@ export class MentorTrackingController { constructor(private readonly service: MentorTrackingService) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Mentor Tracking detail." }) @SerializeOptions({ diff --git a/src/mentorTracking/mentorTracking.module.ts b/src/mentorTracking/mentorTracking.module.ts index f6363b93..e0e6078c 100644 --- a/src/mentorTracking/mentorTracking.module.ts +++ b/src/mentorTracking/mentorTracking.module.ts @@ -2,14 +2,9 @@ import { HttpModule } from "@nestjs/axios"; import { CacheModule, Module } from "@nestjs/common"; import { MentorTrackingService } from "src/adapters/hasura/mentorTracking.adapter"; import { MentorTrackingController } from "./mentorTracking.controller"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [MentorTrackingController], providers: [MentorTrackingService], }) diff --git a/src/monitorTracking/monitorTracking.controller.ts b/src/monitorTracking/monitorTracking.controller.ts index cbb4dc59..055d2261 100644 --- a/src/monitorTracking/monitorTracking.controller.ts +++ b/src/monitorTracking/monitorTracking.controller.ts @@ -9,7 +9,6 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, Query, ValidationPipe, UsePipes, @@ -33,7 +32,7 @@ export class MonitorTrackingController { constructor(private readonly service: MonitorTrackingService) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Monitor Tracking detail." }) @SerializeOptions({ diff --git a/src/monitorTracking/monitorTracking.module.ts b/src/monitorTracking/monitorTracking.module.ts index 46378788..5dbdab04 100644 --- a/src/monitorTracking/monitorTracking.module.ts +++ b/src/monitorTracking/monitorTracking.module.ts @@ -3,14 +3,9 @@ import { CacheModule, Module } from "@nestjs/common"; import { MonitorTrackingService } from "src/adapters/hasura/monitorTracking.adapter"; import { MonitorTrackingController } from "./monitorTracking.controller"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [MonitorTrackingController], providers: [MonitorTrackingService], }) diff --git a/src/role/role.controller.ts b/src/role/role.controller.ts index c6832b8e..499c0eec 100644 --- a/src/role/role.controller.ts +++ b/src/role/role.controller.ts @@ -9,7 +9,6 @@ import { ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, Query, } from "@nestjs/common"; import { @@ -31,7 +30,7 @@ export class RoleController { constructor(private readonly service: RoleService) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "role detail." }) @SerializeOptions({ diff --git a/src/role/role.module.ts b/src/role/role.module.ts index 566a68db..1d14c10f 100644 --- a/src/role/role.module.ts +++ b/src/role/role.module.ts @@ -1,15 +1,10 @@ import { HttpModule } from "@nestjs/axios"; -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { RoleService } from "src/adapters/hasura/role.adapter"; import { RoleController } from "./role.controller"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [RoleController], providers: [RoleService], }) diff --git a/src/school/school.controller.ts b/src/school/school.controller.ts index e78633db..a92e50a1 100644 --- a/src/school/school.controller.ts +++ b/src/school/school.controller.ts @@ -10,7 +10,6 @@ import { SerializeOptions, Req, Request, - CacheInterceptor, } from "@nestjs/common"; import { SchoolDto } from "./dto/school.dto"; import { @@ -29,7 +28,7 @@ export class SchoolController { constructor(private schoolAdapter: SchoolAdapter) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "School detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/school/school.module.ts b/src/school/school.module.ts index ed268f2b..d17e243e 100644 --- a/src/school/school.module.ts +++ b/src/school/school.module.ts @@ -4,15 +4,8 @@ import { HttpModule } from "@nestjs/axios"; import { SchoolAdapter } from "./schooladapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -const ttl = process.env.TTL as never; @Module({ - imports: [ - HttpModule, - HasuraModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule, HasuraModule], controllers: [SchoolController], providers: [SchoolAdapter], }) diff --git a/src/student/student.controller.ts b/src/student/student.controller.ts index f03566b3..0df194c8 100644 --- a/src/student/student.controller.ts +++ b/src/student/student.controller.ts @@ -1,9 +1,4 @@ -import { - CacheInterceptor, - CACHE_MANAGER, - Inject, - Request, -} from "@nestjs/common"; +import { Request } from "@nestjs/common"; import { ApiTags, ApiBody, @@ -32,14 +27,10 @@ import { StudentAdapter } from "./studentadapter"; @ApiTags("Student") @Controller("student") export class StudentController { - constructor( - @Inject(CACHE_MANAGER) private cacheManager, - - private studentAdapter: StudentAdapter - ) {} + constructor(private studentAdapter: StudentAdapter) {} @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Student detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/student/student.module.ts b/src/student/student.module.ts index 12e8d839..23c37fbd 100644 --- a/src/student/student.module.ts +++ b/src/student/student.module.ts @@ -1,16 +1,10 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { StudentController } from "./student.controller"; import { HttpModule } from "@nestjs/axios"; import { StudentAdapter } from "./studentadapter"; -const ttl = process.env.TTL as never; @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [StudentController], providers: [StudentAdapter], }) diff --git a/src/trackAssessment/trackassessment.controller.ts b/src/trackAssessment/trackassessment.controller.ts index c5e3df3d..8d7abc64 100644 --- a/src/trackAssessment/trackassessment.controller.ts +++ b/src/trackAssessment/trackassessment.controller.ts @@ -16,7 +16,6 @@ import { SerializeOptions, Req, Request, - CacheInterceptor, Post, Body, Query, @@ -49,7 +48,7 @@ export class AssessmentController { } @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Track Assessment detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/trackAssessment/trackassessment.module.ts b/src/trackAssessment/trackassessment.module.ts index e24671f9..86b4ec29 100644 --- a/src/trackAssessment/trackassessment.module.ts +++ b/src/trackAssessment/trackassessment.module.ts @@ -3,15 +3,9 @@ import { HttpModule } from "@nestjs/axios"; import { ScheduleModule } from "@nestjs/schedule"; import { TrackAssessmentService } from "src/adapters/hasura/trackassessment.adapter"; import { AssessmentController } from "./trackassessment.controller"; -const ttl = process.env.TTL as never; + @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ScheduleModule.forRoot(), - ], + imports: [HttpModule, ScheduleModule.forRoot()], controllers: [AssessmentController], providers: [TrackAssessmentService], }) diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 965e81fc..f532fa35 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -3,15 +3,9 @@ import { Get, Post, Body, - Put, Param, - UseInterceptors, - ClassSerializerInterceptor, SerializeOptions, Req, - CacheInterceptor, - Inject, - Query, Headers, Res, Patch, @@ -59,7 +53,6 @@ export class UserController { * @since 1.6 */ @Get("/:userid/:role") - // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -78,18 +71,20 @@ export class UserController { ) { // const tenantId = headers["tenantid"]; Can be Used In future // Context and ContextType can be taked from .env later - let userData = { - userId:userId, - context:"USERS", - contextType:role - } + let userData = { + userId: userId, + context: "USERS", + contextType: role, + }; - const result = await this.userService.getUsersDetailsById(userData,response); - return response.status(result.statusCode).json(result); + const result = await this.userService.getUsersDetailsById( + userData, + response + ); + return response.status(result.statusCode).json(result); } @Get() - // @UseInterceptors(CacheInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -117,11 +112,11 @@ export class UserController { @Headers() headers, @Req() request: Request, @Body() userCreateDto: UserCreateDto, - @Res() response:Response + @Res() response: Response ) { userCreateDto.tenantId = headers["tenantid"]; const result = await this.userService.createUser(request, userCreateDto); - return response.status(result.statusCode).json(result); + return response.status(result.statusCode).json(result); } @Patch("/:userid") @@ -139,9 +134,9 @@ export class UserController { @Res() response: Response ) { // userDto.tenantId = headers["tenantid"]; - userUpdateDto.userId=userId; - const result = await this.userService.updateUser(userUpdateDto,response) - return response.status(result.statusCode).json(result); + userUpdateDto.userId = userId; + const result = await this.userService.updateUser(userUpdateDto, response); + return response.status(result.statusCode).json(result); } @Post("/search") diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 07bf2a8e..3e0f205b 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -9,15 +9,12 @@ import { UserService } from "./user.service"; import { FieldValues } from "./entities/field-value-entities"; import { Field } from "./entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; -const ttl = process.env.TTL as never; + @Module({ imports: [ TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers]), HttpModule, HasuraModule, - CacheModule.register({ - ttl: ttl, - }), ], controllers: [UserController], providers: [UserAdapter, UserService], diff --git a/src/workHistory/workHistory.controller.ts b/src/workHistory/workHistory.controller.ts index b82889c5..6c3892a8 100644 --- a/src/workHistory/workHistory.controller.ts +++ b/src/workHistory/workHistory.controller.ts @@ -9,7 +9,6 @@ import { } from "@nestjs/swagger"; import { Body, - CacheInterceptor, ClassSerializerInterceptor, Controller, Get, @@ -62,7 +61,7 @@ export class WorkHistoryController { } @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Work History detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/workHistory/workHistory.module.ts b/src/workHistory/workHistory.module.ts index c366bc42..6c8eeeaf 100644 --- a/src/workHistory/workHistory.module.ts +++ b/src/workHistory/workHistory.module.ts @@ -1,16 +1,10 @@ -import { CacheModule, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { WorkHistoryService } from "../adapters/hasura/workhistory.adapter"; import { WorkHistoryController } from "./workHistory.controller"; -const ttl = process.env.TTL as never; @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [WorkHistoryController], providers: [WorkHistoryService], }) diff --git a/src/worksheet/worksheet.controller.ts b/src/worksheet/worksheet.controller.ts index 95872038..6690a728 100644 --- a/src/worksheet/worksheet.controller.ts +++ b/src/worksheet/worksheet.controller.ts @@ -9,7 +9,6 @@ import { } from "@nestjs/swagger"; import { Body, - CacheInterceptor, ClassSerializerInterceptor, Controller, Get, @@ -62,7 +61,7 @@ export class WorksheetController { } @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor, CacheInterceptor) + @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Worksheet detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/worksheet/worksheet.module.ts b/src/worksheet/worksheet.module.ts index 8b2eb6d2..ee17258b 100644 --- a/src/worksheet/worksheet.module.ts +++ b/src/worksheet/worksheet.module.ts @@ -3,14 +3,8 @@ import { HttpModule } from "@nestjs/axios"; import { WorksheetController } from "./worksheet.controller"; import { WorksheetService } from "src/adapters/hasura/worksheet.adapter"; -const ttl = process.env.TTL as never; @Module({ - imports: [ - HttpModule, - CacheModule.register({ - ttl: ttl, - }), - ], + imports: [HttpModule], controllers: [WorksheetController], providers: [WorksheetService], }) From 6d6284a42647c0eb64882f69980eb8b2da123797 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 4 Apr 2024 17:29:20 +0530 Subject: [PATCH 179/408] Task #216811 : Added User Service to Postgres Adapter and Created Adapter. --- src/adapters/hasura/user.adapter.ts | 15 +- src/adapters/postgres/potsgres-module.ts | 30 +++ .../postgres/user-adapter.ts} | 210 ++++++++++++++---- src/adapters/userservicelocator.ts | 28 +-- src/auth/auth.module.ts | 13 +- src/auth/auth.service.ts | 14 +- src/common/utils/keycloak.service.ts | 4 +- src/user/user.controller.ts | 87 ++++---- src/user/user.module.ts | 5 +- src/user/useradapter.ts | 6 +- 10 files changed, 288 insertions(+), 124 deletions(-) create mode 100644 src/adapters/postgres/potsgres-module.ts rename src/{user/user.service.ts => adapters/postgres/user-adapter.ts} (64%) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 8905e363..6e5ae0da 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -25,13 +25,16 @@ export class HasuraUserService implements IServicelocator { private httpService: HttpService, private fieldsService: FieldsService ) {} - + public async findUserDetails(userID: any, username: String) { + + } public async getUser( - tenantId: string, - userId: string, - accessRole: string, - request: any, - res: any + userData?:Record, + res?: any, + tenantId?: string, + userId?: string, + accessRole?: string, + request?: any, ) { try { const decoded: any = jwt_decode(request.headers.authorization); diff --git a/src/adapters/postgres/potsgres-module.ts b/src/adapters/postgres/potsgres-module.ts new file mode 100644 index 00000000..237733e7 --- /dev/null +++ b/src/adapters/postgres/potsgres-module.ts @@ -0,0 +1,30 @@ +import { HttpModule } from "@nestjs/axios"; +import { Module } from "@nestjs/common"; +import { PostgresUserService } from "./user-adapter"; +import { FieldsService } from "src/fields/fields.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { User } from "src/user/entities/user-entity"; +import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; +import { Field } from "src/user/entities/field-entity"; +import { FieldValues } from "src/user/entities/field-value-entities"; + + + +@Module({ + imports: [HttpModule, + TypeOrmModule.forFeature([ + User, + Field, + FieldValues, + CohortMembers + ]) + ], + providers: [ + PostgresUserService, + ], + exports: [ + PostgresUserService, + ], + }) + export class PostgresModule {} + \ No newline at end of file diff --git a/src/user/user.service.ts b/src/adapters/postgres/user-adapter.ts similarity index 64% rename from src/user/user.service.ts rename to src/adapters/postgres/user-adapter.ts index 2bc432e0..63bc8017 100644 --- a/src/user/user.service.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -1,34 +1,28 @@ -import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; -import { User } from './entities/user-entity' -import { FieldValues } from './entities/field-value-entities'; -import ApiResponse from '../utils/response' +import {ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { User } from '../../user/entities/user-entity' +import { FieldValues } from '../../user/entities/field-value-entities'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { UserCreateDto } from './dto/user-create.dto'; +import { UserCreateDto } from '../../user/dto/user-create.dto'; import jwt_decode from "jwt-decode"; import { - getUserRole, getKeycloakAdminToken, createUserInKeyCloak, checkIfUsernameExistsInKeycloak, -} from "../common/utils/keycloak.adapter.util" -import { FieldValuesCreateDto } from 'src/fields/dto/field-values-create.dto'; +} from "../../common/utils/keycloak.adapter.util" import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; -import { Field } from './entities/field-entity'; -import APIResponse from '../utils/response'; +import { Field } from '../../user/entities/field-entity'; +import APIResponse from '../../utils/response'; import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; -import { v5 as uuidv5 } from 'uuid'; -import { UUID } from 'typeorm/driver/mongodb/bson.typings'; -import { AnyARecord } from 'dns'; -import { CohortSearchDto } from 'src/cohort/dto/cohort-search.dto'; -import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import axios,{AxiosInstance, AxiosRequestConfig} from "axios" @Injectable() -@Injectable() -export class UserService { +export class PostgresUserService { + axios = require("axios"); constructor( + // private axiosInstance: AxiosInstance, @InjectRepository(User) private usersRepository: Repository, @InjectRepository(FieldValues) @@ -39,7 +33,7 @@ export class UserService { private cohortMemberRepository: Repository ) {} - async getUsersDetailsById(userData:Record,response){ + async getUser(userData:Record,response){ let apiId='api.users.getUsersDetails' try { const result = { @@ -66,16 +60,20 @@ export class UserService { customFieldsArray.push(customField); } result.userData['customFields'] = customFieldsArray; - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: result, - }); + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, result, 'OK')); } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + 'Something went wrong In finding UserDetails', + e, + 'INTERNAL_SERVER_ERROR', + ), + ); } } @@ -125,16 +123,20 @@ export class UserService { } } } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok', - data: updatedData, - }); + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, updatedData, 'OK')); } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + 'Something went wrong In finding UserDetails', + e, + 'INTERNAL_SERVER_ERROR', + ), + ); } } @@ -184,8 +186,8 @@ export class UserService { const token = keycloakResponse.data.access_token; let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) if(checkUserinKeyCloakandDb){ - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, + return new ErrorResponse({ + errorCode: "400", errorMessage: "User Already Exists", }); } @@ -193,8 +195,8 @@ export class UserService { (error) => { errKeycloak = error.response?.data.errorMessage; - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + return new ErrorResponse({ + errorCode: "500", errorMessage: "Someting went wrong", }); } @@ -213,21 +215,21 @@ export class UserService { } let result = await this.updateCustomFields(userId,fieldData); if(!result) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + return new ErrorResponse({ + errorCode: "500", errorMessage: `Error is ${result}`, }); } } } return new SuccessResponse({ - statusCode: HttpStatus.CREATED, + statusCode: 200, message: "ok", data: result, }); } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + return new ErrorResponse({ + errorCode: "500", errorMessage: `Error is ${e}`, }); } @@ -286,9 +288,127 @@ export class UserService { let result = await this.cohortMemberRepository.insert(cohortData); return result;; } catch (error) { + console.log(error); throw new Error(error) } } + + public async resetUserPassword( + request: any, + username: string, + newPassword: string + ) { + try { + const userData: any = await this.findUserDetails(null, username); + let userId; + + if (userData?.userId) { + userId = userData?.userId; + } else { + return new ErrorResponse({ + errorCode: `404`, + errorMessage: "User with given username not found", + }); + } + + // const data = JSON.stringify({ + // temporary: "false", + // type: "password", + // value: newPassword, + // }); + + const keycloakResponse = await getKeycloakAdminToken(); + const resToken = keycloakResponse.data.access_token; + let apiResponse; + + try { + apiResponse = await this.resetKeycloakPassword( + request, + resToken, + newPassword, + userId + ); + } catch (e) { + return new ErrorResponse({ + errorCode: `${e.response.status}`, + errorMessage: e.response.data.error, + }); + } + + if (apiResponse.statusCode === 204) { + return new SuccessResponse({ + statusCode: apiResponse.statusCode, + message: apiResponse.message, + data: apiResponse.data, + }); + } else { + return new ErrorResponse({ + errorCode: "400", + errorMessage: apiResponse.errors, + }); + } + } catch (e) { + console.error(e); + return e; + } + } + public async resetKeycloakPassword( + request: any, + token: string, + newPassword: string, + userId: string + ) { + const data = JSON.stringify({ + temporary: "false", + type: "password", + value: newPassword, + }); + + if (!token) { + const response = await getKeycloakAdminToken(); + token = response.data.access_token; + } + + let apiResponse; + + const config = { + method: "put", + url: + process.env.KEYCLOAK + + process.env.KEYCLOAK_ADMIN + + "/" + + userId + + "/reset-password", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + data: data, + }; + + try { + apiResponse = await this.axios(config); + } catch (e) { + return new ErrorResponse({ + errorCode: `${e.response.status}`, + errorMessage: e.response.data.error, + }); + } + + if (apiResponse.status === 204) { + return new SuccessResponse({ + statusCode: apiResponse.status, + message: apiResponse.statusText, + data: { msg: "Password reset successful!" }, + }); + } else { + return new ErrorResponse({ + errorCode: "400", + errorMessage: apiResponse.errors, + }); + } + } + } diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index be916987..d0818c5a 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -4,21 +4,21 @@ import { UserDto } from "src/user/dto/user.dto"; export interface IServicelocator { getUser( - tenantId: string, - id: any, - accessRole: string, - request: any, - response: any + userId?:Record, + response?: any, + tenantId?: string, + id?: any, + accessRole?: string, + request?: any, ); - getUserByAuth(tenantId: string, request: any); - checkAndAddUser(request: any, userDto: UserCreateDto); + updateUser(id?: string, request?: any, userDto?: any,response?: any); createUser(request: any, userDto: UserCreateDto); - updateUser(id: string, request: any, userDto: UserCreateDto); - searchUser( - tenantId: string, - request: any, - response: any, - userSearchDto: UserSearchDto - ); + findUserDetails(userID:any,username:String) + // searchUser( + // tenantId: string, + // request: any, + // response: any, + // userSearchDto: UserSearchDto + // ); resetUserPassword(request: any, username: string, newPassword: string); } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index ef1d92e1..453c4aa2 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,22 +1,29 @@ -import { Module } from "@nestjs/common"; +import { HttpService, Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { AuthController } from "./auth.controller"; import { AuthService } from "./auth.service"; import { JwtStrategy } from "src/common/guards/keycloak.strategy"; -import { UserService } from "src/user/user.service"; +import { UserAdapter } from "../user/useradapter"; import { TypeOrmModule } from "@nestjs/typeorm"; import { User } from "../user/entities/user-entity"; import { FieldValues } from "../user/entities/field-value-entities"; import { Field } from "src/user/entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { KeycloakService } from "src/common/utils/keycloak.service"; +import { HasuraUserService } from "src/adapters/hasura/user.adapter"; +import { PostgresUserService } from "src/adapters/postgres/user-adapter"; +import { FieldsService } from "src/adapters/hasura/services/fields.service"; +import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; @Module({ imports: [ TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers]), HttpModule, + HasuraModule, + PostgresModule, ], controllers: [AuthController], - providers: [AuthService, JwtStrategy, KeycloakService, UserService], + providers: [AuthService, JwtStrategy, KeycloakService, UserAdapter], }) export class AuthModule {} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 7b1a411d..db784f4d 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,9 +1,10 @@ import { HttpStatus, Injectable, UnauthorizedException } from "@nestjs/common"; -import { UserService } from "../user/user.service"; +import { UserAdapter } from "src/user/useradapter"; import axios from "axios"; import jwt_decode from "jwt-decode"; import APIResponse from "src/utils/response"; import { KeycloakService } from "src/common/utils/keycloak.service"; +import { User } from "src/user/entities/user-entity"; type LoginResponse = { access_token: string; @@ -15,7 +16,7 @@ type LoginResponse = { export class AuthService { private axiosInstance; constructor( - private readonly userService: UserService, + private readonly useradapter: UserAdapter, private readonly keycloakService: KeycloakService ) { this.axiosInstance = axios.create(); @@ -29,10 +30,8 @@ export class AuthService { refresh_token, refresh_expires_in, token_type, - } = await this.keycloakService.login(username, password).catch(() => { - throw new UnauthorizedException(); - }); - + } = await this.keycloakService.login(username, password).catch(() => {throw new UnauthorizedException();}); + console.log(access_token); return { access_token, refresh_token, @@ -42,12 +41,13 @@ export class AuthService { }; } + public async getUserByAuth(request: any, response) { let apiId = "api.auth.getUserDetails"; try { const decoded: any = jwt_decode(request.headers.authorization); const username = decoded.preferred_username; - let data = await this.userService.findUserDetails(null, username); + let data = await this.useradapter.buildUserAdapter().findUserDetails(null, username); return response .status(HttpStatus.OK) .send(APIResponse.success(apiId, data, "OK")); diff --git a/src/common/utils/keycloak.service.ts b/src/common/utils/keycloak.service.ts index 9232c646..a72e205e 100644 --- a/src/common/utils/keycloak.service.ts +++ b/src/common/utils/keycloak.service.ts @@ -54,9 +54,9 @@ export class KeycloakService { }, data: data, }; - + console.log(axiosConfig); const res = await this.axios(axiosConfig); - + console.log(res); return res.data; } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index f532fa35..7bf22d07 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -29,18 +29,14 @@ import { UserDto } from "./dto/user.dto"; import { UserSearchDto } from "./dto/user-search.dto"; import { UserAdapter } from "./useradapter"; import { UserCreateDto } from "./dto/user-create.dto"; -import { UserService } from "./user.service"; import { UserUpdateDTO } from "./dto/user-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { Response } from "express"; @ApiTags("User") @Controller("user") -@UseGuards(JwtAuthGuard) export class UserController { constructor( - private readonly service: UserService, private userAdapter: UserAdapter, - private userService: UserService ) {} /** @@ -53,6 +49,7 @@ export class UserController { * @since 1.6 */ @Get("/:userid/:role") + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -77,29 +74,30 @@ export class UserController { contextType: role, }; - const result = await this.userService.getUsersDetailsById( + const result = await this.userAdapter.buildUserAdapter().getUser( userData, response ); return response.status(result.statusCode).json(result); } - @Get() - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "User detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async getUserByAuth(@Headers() headers, @Req() request: Request) { - const tenantId = headers["tenantid"]; - return this.userAdapter.buildUserAdapter().getUserByAuth(tenantId, request); - } + // @Get() + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "User detail." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async getUserByAuth(@Headers() headers, @Req() request: Request) { + // const tenantId = headers["tenantid"]; + // return this.userAdapter.buildUserAdapter().getUserByAuth(tenantId, request); + // } @Post() + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User has been created successfully." }) @ApiBody({ type: UserCreateDto }) @@ -115,11 +113,12 @@ export class UserController { @Res() response: Response ) { userCreateDto.tenantId = headers["tenantid"]; - const result = await this.userService.createUser(request, userCreateDto); + const result = await this.userAdapter.buildUserAdapter().createUser(request, userCreateDto); return response.status(result.statusCode).json(result); } @Patch("/:userid") + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User has been updated successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -135,40 +134,38 @@ export class UserController { ) { // userDto.tenantId = headers["tenantid"]; userUpdateDto.userId = userId; - const result = await this.userService.updateUser(userUpdateDto, response); + const result = await this.userAdapter.buildUserAdapter().updateUser(userId,request,userUpdateDto,response); return response.status(result.statusCode).json(result); } - @Post("/search") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "User list." }) + // @Post("/search") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "User list." }) // @ApiBody({ type: UserSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async searchUser( - @Headers() headers, - @Req() request: Request, - @Res() response: Response, - @Body() userSearchDto: UserSearchDto - ) { - const tenantId = headers["tenantid"]; - return await this.userAdapter - .buildUserAdapter() - .searchUser(tenantId, request, response, userSearchDto); - } + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async searchUser( + // @Headers() headers, + // @Req() request: Request, + // @Res() response: Response, + // @Body() userSearchDto: UserSearchDto + // ) { + // const tenantId = headers["tenantid"]; + // return await this.userAdapter + // .buildUserAdapter() + // .searchUser(tenantId, request, response, userSearchDto); + // } @Post("/reset-password") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Password reset successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiBody({ type: Object }) - // @UseInterceptors(ClassSerializerInterceptor) public async resetUserPassword( @Req() request: Request, @Body() @@ -181,4 +178,6 @@ export class UserController { .buildUserAdapter() .resetUserPassword(request, reqBody.username, reqBody.newPassword); } + + } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 3e0f205b..43abf0cb 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -3,9 +3,9 @@ import { UserController } from "./user.controller"; import { HttpModule } from "@nestjs/axios"; import { UserAdapter } from "./useradapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; import { TypeOrmModule } from "@nestjs/typeorm"; import { User } from "./entities/user-entity"; -import { UserService } from "./user.service"; import { FieldValues } from "./entities/field-value-entities"; import { Field } from "./entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; @@ -15,8 +15,9 @@ import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers]), HttpModule, HasuraModule, + PostgresModule, ], controllers: [UserController], - providers: [UserAdapter, UserService], + providers: [UserAdapter], }) export class UserModule {} diff --git a/src/user/useradapter.ts b/src/user/useradapter.ts index 774d7a6d..2cc4543f 100644 --- a/src/user/useradapter.ts +++ b/src/user/useradapter.ts @@ -1,10 +1,12 @@ import { Injectable } from "@nestjs/common"; import { HasuraUserService } from "src/adapters/hasura/user.adapter"; import { IServicelocator } from "src/adapters/userservicelocator"; +import { PostgresUserService } from "src/adapters/postgres/user-adapter"; @Injectable() export class UserAdapter { - constructor(private hasuraProvider: HasuraUserService) {} + constructor(private hasuraProvider: HasuraUserService, + private postgresProvider:PostgresUserService) {} buildUserAdapter(): IServicelocator { let adapter: IServicelocator; @@ -12,6 +14,8 @@ export class UserAdapter { case "hasura": adapter = this.hasuraProvider; break; + case "postgres": + adapter = this.postgresProvider; } return adapter; } From efcc487a48828f07d534741f1952a0d86f6479ec Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 5 Apr 2024 14:21:32 +0530 Subject: [PATCH 180/408] Task #216811: Created Adapter of Attendance, Cohort,field --- src/adapters/attendanceservicelocator.ts | 13 +- src/adapters/cohortservicelocator.ts | 8 +- src/adapters/fieldsservicelocator.ts | 6 +- src/adapters/hasura/attendance.adapter.ts | 7 +- src/adapters/hasura/cohort.adapter.ts | 2 + .../postgres/attendance-adapter.ts} | 14 +- src/adapters/postgres/cohort-adapter.ts | 348 ++++++++++++++++++ src/adapters/postgres/fields-adapter.ts | 272 ++++++++++++++ src/adapters/postgres/potsgres-module.ts | 14 +- src/attendance/attendance.controller.ts | 58 +-- src/attendance/attendance.module.ts | 5 +- src/attendance/attendanceadapter.ts | 6 +- src/auth/auth.service.ts | 3 +- src/cohort/cohort.controller.ts | 6 +- src/cohort/cohort.module.ts | 5 +- src/cohort/cohortadapter.ts | 6 +- src/fields/fields.controller.ts | 8 +- src/fields/fields.module.ts | 2 + src/fields/fieldsadapter.ts | 6 +- 19 files changed, 729 insertions(+), 60 deletions(-) rename src/{attendance/attendance.service.ts => adapters/postgres/attendance-adapter.ts} (97%) create mode 100644 src/adapters/postgres/cohort-adapter.ts create mode 100644 src/adapters/postgres/fields-adapter.ts diff --git a/src/adapters/attendanceservicelocator.ts b/src/adapters/attendanceservicelocator.ts index 6decbbe1..536dd6b2 100644 --- a/src/adapters/attendanceservicelocator.ts +++ b/src/adapters/attendanceservicelocator.ts @@ -3,8 +3,15 @@ import { AttendanceSearchDto } from "src/attendance/dto/attendance-search.dto"; import { AttendanceDto } from "src/attendance/dto/attendance.dto"; export interface IServicelocator { - checkAndAddAttendance(request: Request, attendanceDto: AttendanceDto): unknown; - getAttendance(tenantId: string, attendanceId: string, request: any); + // checkAndAddAttendance(request: Request, attendanceDto: AttendanceDto): unknown; + // getAttendance(tenantId: string, attendanceId: string, request: any); + attendanceReport( + attendanceStatsDto + ); + updateAttendanceRecord( + request, + attendanceDto + ); updateAttendance( attendanceId: string, request: any, @@ -14,7 +21,7 @@ export interface IServicelocator { multipleAttendance( tenantId: string, request: any, - attendanceData: [AttendanceDto] + attendanceData: any ); searchAttendance( tenantId: string, diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index a2a9d287..0e5130e8 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -4,7 +4,13 @@ import { CohortDto } from "src/cohort/dto/cohort.dto"; export interface IServicelocatorcohort { createCohort(request: any, cohortDto: CohortCreateDto); - getCohort(tenantId, cohortId, request, res); + // getCohort(tenantId, cohortId, request, res); searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto, res); updateCohort(cohortId: string, request: any, cohortDto: CohortCreateDto); + getCohortList( + tenantid, + id, + request, + response + ); } diff --git a/src/adapters/fieldsservicelocator.ts b/src/adapters/fieldsservicelocator.ts index 9f5e4c59..300a3918 100644 --- a/src/adapters/fieldsservicelocator.ts +++ b/src/adapters/fieldsservicelocator.ts @@ -6,12 +6,12 @@ import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; export interface IServicelocatorfields { //fields createFields(request: any, fieldsDto: FieldsDto); - getFields(tenantId, fieldsId, request); + // getFields(tenantId, fieldsId, request); searchFields(tenantid, request: any, fieldsSearchDto: FieldsSearchDto); - updateFields(fieldsId: string, request: any, fieldsDto: FieldsDto); + // updateFields(fieldsId: string, request: any, fieldsDto: FieldsDto); //field values createFieldValues(request: any, fieldValuesDto: FieldValuesDto); - getFieldValues(id, request); + // getFieldValues(id, request); searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto); updateFieldValues(id: string, request: any, fieldValuesDto: FieldValuesDto); } diff --git a/src/adapters/hasura/attendance.adapter.ts b/src/adapters/hasura/attendance.adapter.ts index 68c2b1b5..af209ac6 100644 --- a/src/adapters/hasura/attendance.adapter.ts +++ b/src/adapters/hasura/attendance.adapter.ts @@ -18,7 +18,12 @@ export class AttendanceHasuraService implements IServicelocator { axios = require("axios"); constructor(private httpService: HttpService) {} - + public async attendanceReport(attendanceStatsDto: any) { + + } + public async updateAttendanceRecord(request: any, attendanceDto: any) { + + } public async getAttendance( tenantId: string, attendanceId: string, diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index caca1e4e..dcc17a5a 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -22,6 +22,8 @@ export class HasuraCohortService implements IServicelocatorcohort { private httpService: HttpService, private fieldsService: FieldsService ) {} + public async getCohortList(tenantid: any, id: any, request: any, response: any) { + } public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try{ diff --git a/src/attendance/attendance.service.ts b/src/adapters/postgres/attendance-adapter.ts similarity index 97% rename from src/attendance/attendance.service.ts rename to src/adapters/postgres/attendance-adapter.ts index 0626af92..ab596eae 100644 --- a/src/attendance/attendance.service.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -1,24 +1,24 @@ -import { User } from './../user/entities/user-entity'; +import { User } from '../../user/entities/user-entity'; import { isAfter } from 'date-fns'; import { ConfigService } from '@nestjs/config'; import { Client } from 'pg'; import jwt_decode from "jwt-decode"; import { InjectRepository } from "@nestjs/typeorm"; -import { AttendanceEntity } from "./entities/attendance.entity"; +import { AttendanceEntity } from "../../attendance/entities/attendance.entity"; import { Repository } from "typeorm"; import { BadRequestException, HttpException, HttpStatus, Injectable } from "@nestjs/common"; -import { AttendanceSearchDto } from "./dto/attendance-search.dto"; +import { AttendanceSearchDto } from "../../attendance/dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; -import { AttendanceDto, BulkAttendanceDTO } from './dto/attendance.dto'; -import { AttendanceDateDto } from './dto/attendance-date.dto'; +import { AttendanceDto, BulkAttendanceDTO } from '../../attendance/dto/attendance.dto'; +import { AttendanceDateDto } from '../../attendance/dto/attendance-date.dto'; import { Between } from 'typeorm'; -import { AttendanceStatsDto } from './dto/attendance-stats.dto'; +import { AttendanceStatsDto } from '../../attendance/dto/attendance-stats.dto'; import { format } from 'date-fns' import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; const moment = require('moment'); @Injectable() -export class AttendanceService { +export class PostgresAttendanceService { constructor(private configService: ConfigService, @InjectRepository(AttendanceEntity) private readonly attendanceRepository: Repository, diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts new file mode 100644 index 00000000..2dda40c5 --- /dev/null +++ b/src/adapters/postgres/cohort-adapter.ts @@ -0,0 +1,348 @@ +import { ConsoleLogger, HttpStatus, Injectable } from "@nestjs/common"; +import { HttpService } from "@nestjs/axios"; +import { SuccessResponse } from "src/success-response"; +import { ErrorResponse } from "src/error-response"; +const resolvePath = require("object-resolve-path"); +import jwt_decode from "jwt-decode"; +import { CohortDto } from "src/cohort/dto/cohort.dto"; +import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; +import { UserDto } from "src/user/dto/user.dto"; +import { StudentDto } from "src/student/dto/student.dto"; +import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; +import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; +import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; +import { Cohort } from "src/cohort/entities/cohort.entity"; +import { InjectRepository } from "@nestjs/typeorm"; +import { PostgresFieldsService } from "./fields-adapter" +// import { FieldValues } from "src/fields/entities/field-values.entity"; +import { response } from "express"; +import APIResponse from "src/utils/response"; +import { FieldValues } from "../../fields/entities/fields-values.entity"; +import { v4 as uuidv4 } from 'uuid'; +import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; +import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; + +@Injectable() +export class PostgresCohortService { + + + constructor( + @InjectRepository(Cohort) + private cohortRepository: Repository, + @InjectRepository(CohortMembers) + private cohortMembersRepository: Repository, + private fieldsService: PostgresFieldsService, + ) { } + + public async getCohortsDetails(tenantId: string, + cohortId: string, + request: any, + response: any){ + const apiId = "api.concept.cohortDetails"; + let cohortName = await this.cohortRepository.findOne({ + where:{cohortId} + }) + // let result = { + // cohortData: [], + // }; + let cohortData = { + cohortId: cohortId, + name:cohortName.name, + parentId:cohortName.parentId, + customField:{} + }; + const getDetails = await this.getCohortListDetails(cohortId); + cohortData.customField=getDetails + // result.cohortData.push(cohortData); + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + cohortData, + "OK" + ) + ); + } + + public async getCohortList( + tenantId: string, + userId: string, + request: any, + response: any + ) { + const apiId = "api.concept.editminiScreeningAnswer"; + try { + let findCohortId = await this.findCohortName(userId); + let result = { + cohortData: [], + }; + + for (let data of findCohortId) { + let cohortData = { + cohortId: data.cohortId, + name:data.name, + parentId:data.parentId, + customField:{} + }; + const getDetails = await this.getCohortListDetails(data.cohortId); + cohortData.customField=getDetails + result.cohortData.push(cohortData); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: result, + }); + } catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + } + + public async findCohortName(userId: any) { + let query = `SELECT c."name",c."cohortId",c."parentId" + FROM public."CohortMembers" AS cm + LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" + WHERE cm."userId"=$1 AND c.status=true`; + let result = await this.cohortMembersRepository.query(query, [userId]); + return result; + } + + public async getCohortListDetails(userId) { + let query = `SELECT DISTINCT f."label", fv."value", f."type", f."fieldParams" + FROM public."CohortMembers" cm + LEFT JOIN ( + SELECT DISTINCT ON (fv."fieldId", fv."itemId") fv.* + FROM public."FieldValues" fv + ) fv ON fv."itemId" = cm."cohortId" + INNER JOIN public."Fields" f ON fv."fieldId" = f."fieldId" + WHERE cm."cohortId" = $1;`; + let result = await this.cohortMembersRepository.query(query, [ + userId + ]); + return result; + } + public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { + try { + const cohortData: any = {}; + cohortCreateDto.cohortId = uuidv4(); + Object.keys(cohortCreateDto).forEach((e) => { + if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { + if (Array.isArray(cohortCreateDto[e])) { + cohortData[e] = JSON.stringify(cohortCreateDto[e]); + } else { + cohortData[e] = cohortCreateDto[e]; + } + } + }); + const response = await this.cohortRepository.save(cohortData); + let cohortId = response?.cohortId; + + let field_value_array = cohortCreateDto.fieldValues.split("|"); + + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + + let fieldValues = field_value_array[i].split(":"); + let fieldValueDto: FieldValuesDto = { + fieldValuesId: "", // Provide a value for fieldValuesId + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortCreateDto?.createdBy, + updatedBy: cohortCreateDto?.updatedBy, + createdAt: new Date().toISOString(), // Provide appropriate values for createdAt and updatedAt + updatedAt: new Date().toISOString(), + }; + + await this.fieldsService.createFieldValues(request, fieldValueDto); + } + } + + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: response, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async updateCohort( + cohortId: string, + request: any, + cohortUpdateDto: CohortCreateDto + ) { + try { + const cohortUpdateData: any = {}; + + Object.keys(cohortUpdateDto).forEach((e) => { + if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" + ) { + if (Array.isArray(cohortUpdateDto[e])) { + cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + } else { + cohortUpdateData[e] = cohortUpdateDto[e]; + } + } + }); + + const response = await this.cohortRepository.update(cohortId, cohortUpdateData); + + + let field_value_array = cohortUpdateDto.fieldValues.split("|"); + + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + + let fieldValues = field_value_array[i].split(":"); + let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + try { + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + const rowid = fieldVauesRowId.fieldValuesId; + + let fieldValueDto: FieldValuesDto = { + fieldValuesId: rowid, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.updateFieldValues(rowid, fieldValueDto); + }catch{ + let fieldValueDto: FieldValuesDto = { + fieldValuesId: null, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.createFieldValues(request, fieldValueDto); + } + } + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async searchCohort( + tenantId: string, + request: any, + cohortSearchDto: CohortSearchDto, + ) { + try { + + let { limit, page, filters } = cohortSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + const [results, totalCount] = await this.cohortRepository.findAndCount({ + where: whereClause, + skip: offset, + take: parseInt(limit), + }); + + const mappedResponse = await this.mappedResponse(results); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + totalCount, + data: mappedResponse, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async mappedResponse(result: any) { + const cohortValueResponse = result.map((item: any) => { + const cohortMapping = { + tenantId: item?.tenantId ? `${item.tenantId}` : "", + programId: item?.programId ? `${item.programId}` : "", + cohortId: item?.cohortId ? `${item.cohortId}` : "", + parentId: item?.parentId ? `${item.parentId}` : "", + name: item?.name ? `${item.name}` : "", + type: item?.type ? `${item.type}` : "", + status: item?.status ? `${item.status}` : "", + image: item?.image ? `${item.image}` : "", + createdAt: item?.createdAt ? `${item.createdAt}` : "", + updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", + createdBy: item?.createdBy ? `${item.createdBy}` : "", + updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + referenceId: item?.referenceId ? `${item.referenceId}` : "", + metadata: item?.metadata ? `${item.metadata}` : "", + }; + return new CohortDto(cohortMapping); + }) + return cohortValueResponse; + + } + + public async updateCohortStatus( + cohortId: string + ) { + try { + let query = `UPDATE public."Cohort" + SET "status" = false + WHERE "cohortId" = $1`; + const results = await this.cohortRepository.query(query, [cohortId]); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Cohort Deleted Successfully.", + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } +} diff --git a/src/adapters/postgres/fields-adapter.ts b/src/adapters/postgres/fields-adapter.ts new file mode 100644 index 00000000..3f9b23d4 --- /dev/null +++ b/src/adapters/postgres/fields-adapter.ts @@ -0,0 +1,272 @@ +import { HttpStatus, Injectable } from "@nestjs/common"; +import { FieldsDto } from "src/fields/dto/fields.dto"; +import { FieldsSearchDto } from "src/fields/dto/fields-search.dto"; +import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; +import { ErrorResponse } from "src/error-response"; +import { Fields } from "../../fields/entities/fields.entity"; +import { FieldValues } from "../../fields/entities/fields-values.entity"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository} from "typeorm"; +import { SuccessResponse } from "src/success-response"; +import APIResponse from "src/utils/response"; +import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; + +@Injectable() +export class PostgresFieldsService { + constructor( + @InjectRepository(Fields) + private fieldsRepository: Repository, + @InjectRepository(FieldValues) + private fieldsValuesRepository: Repository, + ) { } + + //fields + async createFields(request: any, fieldsDto: FieldsDto) { + try { + + const fieldsData: any = {}; // Define an empty object to store field data + + Object.keys(fieldsDto).forEach((e) => { + if (fieldsDto[e] && fieldsDto[e] !== "") { + if (e === "render") { + fieldsData[e] = fieldsDto[e]; + } else if (Array.isArray(fieldsDto[e])) { + fieldsData[e] = JSON.stringify(fieldsDto[e]); + } else { + fieldsData[e] = fieldsDto[e]; + } + } + }); + + let result = await this.fieldsRepository.save(fieldsData); + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: result, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async searchFields(tenantId: string, request: any, fieldsSearchDto: FieldsSearchDto) { + try { + + const getConditionalData = APIResponse.search(fieldsSearchDto) + const offset = getConditionalData.offset ; + const limit = getConditionalData.limit ; + const whereClause = getConditionalData.whereClause ; + + const getFieldValue = await this.searchFieldData(offset, limit, whereClause) + + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + totalCount : getFieldValue.totalCount, + data: getFieldValue.mappedResponse, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async searchFieldData(offset: number, limit: string, searchData:any){ + let queryOptions: any = { + where: searchData, + }; + + if (offset !== undefined) { + queryOptions.skip = offset; + } + + if (limit !== undefined) { + queryOptions.take = parseInt(limit); + } + + + const [results, totalCount] = await this.fieldsRepository.findAndCount(queryOptions); + + const mappedResponse = await this.mappedResponseField(results); + return {mappedResponse, totalCount}; + } + + async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { + try { + + const fieldsData: any = {}; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + fieldsData[e] = JSON.stringify(fieldValuesDto[e]); + } else { + fieldsData[e] = fieldValuesDto[e]; + } + } + }); + + let result = await this.fieldsValuesRepository.save(fieldsData); + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: result, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode:HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { + try { + const getConditionalData = APIResponse.search(fieldValuesSearchDto) + const offset = getConditionalData.offset ; + const limit = getConditionalData.limit ; + const whereClause = getConditionalData.whereClause ; + + const getFieldValue = await this.getSearchFieldValueData(offset, limit, whereClause) + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + totalCount: getFieldValue.totalCount, + data: getFieldValue.mappedResponse, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async getSearchFieldValueData(offset: number, limit: string, searchData:any){ + let queryOptions: any = { + where: searchData, + }; + + if (offset !== undefined) { + queryOptions.skip = offset; + } + + if (limit !== undefined) { + queryOptions.take = parseInt(limit); + } + + const [results, totalCount] = await this.fieldsValuesRepository.findAndCount(queryOptions); + const mappedResponse = await this.mappedResponse(results); + + return {mappedResponse, totalCount}; + + } + + async searchFieldValueId(cohortId: string, fieldId: string){ + const response = await this.fieldsValuesRepository.findOne({ + where: { itemId: cohortId, fieldId: fieldId }, + }); + return response; + } + + async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { + + try { + const fieldsData: any = {}; + Object.keys(fieldValuesDto).forEach((e) => { + if (fieldValuesDto[e] && fieldValuesDto[e] != "") { + if (Array.isArray(fieldValuesDto[e])) { + fieldsData[e] = JSON.stringify(fieldValuesDto[e]); + } else { + fieldsData[e] = fieldValuesDto[e]; + } + } + }); + const response = await this.fieldsValuesRepository.update(id, fieldValuesDto); + + return response; + } catch (e) { + return new ErrorResponse({ + errorCode: "400", + errorMessage: e, + }); + } + } + + public async getFieldsAndFieldsValues(cohortId:string){ + let query = `SELECT FV."value",FV."itemId", FV."fieldId", F."name" AS fieldname, F."label", F."context",F."type", F."state", F."contextType", F."fieldParams" FROM public."FieldValues" FV + LEFT JOIN public."Fields" F + ON FV."fieldId" = F."fieldId" where FV."itemId" =$1`; + const results = await this.fieldsValuesRepository.query(query, [cohortId]); + return results; + } + + + public async mappedResponse(result: any) { + const fieldValueResponse = result.map((item: any) => { + const fieldValueMapping = { + value: item?.value ? `${item.value}` : "", + fieldValuesId: item?.fieldValuesId ? `${item.fieldValuesId}` : "", + itemId: item?.itemId ? `${item.itemId}` : "", + fieldId: item?.fieldId ? `${item.fieldId}` : "", + createdAt: item?.createdAt ? `${item.createdAt}` : "", + updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", + createdBy: item?.createdBy ? `${item.createdBy}` : "", + updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + }; + + return new FieldValuesDto(fieldValueMapping); + }); + + return fieldValueResponse; + } + + public async mappedResponseField(result: any) { + const fieldResponse = result.map((item: any) => { + + const fieldMapping = { + fieldId: item?.fieldId ? `${item.fieldId}` : "", + assetId: item?.assetId ? `${item.assetId}` : "", + context: item?.context ? `${item.context}` : "", + groupId: item?.groupId ? `${item.groupId}` : "", + name: item?.name ? `${item.name}` : "", + label: item?.label ? `${item.label}` : "", + defaultValue: item?.defaultValue ? `${item.defaultValue}` : "", + type: item?.type ? `${item.type}` : "", + note: item?.note ? `${item.note}` : "", + description: item?.description ? `${item.description}` : "", + state: item?.state ? `${item.state}` : "", + required: item?.required ? `${item.required}` : "", + ordering: item?.ordering ? `${item.ordering}` : "", + metadata: item?.metadata ? `${item.metadata}` : "", + access: item?.access ? `${item.access}` : "", + onlyUseInSubform: item?.onlyUseInSubform ? `${item.onlyUseInSubform}` : "", + tenantId: item?.tenantId ? `${item.tenantId}` : "", + createdAt: item?.createdAt ? `${item.createdAt}` : "", + updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", + createdBy: item?.createdBy ? `${item.createdBy}` : "", + updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + contextId: item?.contextId ? `${item.contextId}` : "", + render: item?.render ? `${item.render}` : "", + contextType: item?.contextType ? `${item.contextType}` : "", + fieldParams: item?.fieldParams ? JSON.stringify(item.fieldParams) : "" + }; + + return new FieldsDto(fieldMapping); + }); + + return fieldResponse; + } + +} diff --git a/src/adapters/postgres/potsgres-module.ts b/src/adapters/postgres/potsgres-module.ts index 237733e7..89daa617 100644 --- a/src/adapters/postgres/potsgres-module.ts +++ b/src/adapters/postgres/potsgres-module.ts @@ -6,7 +6,12 @@ import { TypeOrmModule } from "@nestjs/typeorm"; import { User } from "src/user/entities/user-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { Field } from "src/user/entities/field-entity"; +import { Fields } from "src/fields/entities/fields.entity"; import { FieldValues } from "src/user/entities/field-value-entities"; +import { AttendanceEntity } from "src/attendance/entities/attendance.entity"; +import { PostgresAttendanceService } from "./attendance-adapter"; +import { PostgresFieldsService } from "./fields-adapter"; +import { Cohort } from "src/cohort/entities/cohort.entity"; @@ -16,14 +21,21 @@ import { FieldValues } from "src/user/entities/field-value-entities"; User, Field, FieldValues, - CohortMembers + CohortMembers, + AttendanceEntity, + Fields, + Cohort ]) ], providers: [ PostgresUserService, + PostgresAttendanceService, + PostgresFieldsService ], exports: [ PostgresUserService, + PostgresAttendanceService, + PostgresFieldsService ], }) export class PostgresModule {} diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 932ac702..bef92c09 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -34,7 +34,6 @@ import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; import { AttendanceSearchDto } from "./dto/attendance-search.dto"; import { AttendaceAdapter } from "./attendanceadapter"; import { AttendanceDateDto } from "./dto/attendance-date.dto"; -import { AttendanceService } from "./attendance.service"; import { AttendanceStatsDto } from "./dto/attendance-stats.dto"; import { Response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @@ -45,30 +44,29 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; export class AttendanceController { constructor( private attendaceAdapter: AttendaceAdapter, - private attendaceService: AttendanceService ) {} - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Attendance detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async getAttendance( - @Headers() headers, - @Param("id") attendanceId: string, - @Req() request: Request - ) { - let tenantid = headers["tenantid"]; - return await this.attendaceAdapter - .buildAttenceAdapter() - .getAttendance(tenantid, attendanceId, request); - } + // @Get("/:id") + // @UseInterceptors(ClassSerializerInterceptor) + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Attendance detail" }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @SerializeOptions({ + // strategy: "excludeAll", + // }) + // @ApiHeader({ + // name: "tenantid", + // }) + // public async getAttendance( + // @Headers() headers, + // @Param("id") attendanceId: string, + // @Req() request: Request + // ) { + // let tenantid = headers["tenantid"]; + // return await this.attendaceAdapter + // .buildAttenceAdapter() + // .getAttendance(tenantid, attendanceId, request); + // } @Post() @ApiConsumes("multipart/form-data") @@ -101,7 +99,7 @@ export class AttendanceController { ) { attendanceDto.tenantId = headers["tenantid"]; attendanceDto.image = image?.filename; - const result = await this.attendaceService.updateAttendanceRecord( + const result = await this.attendaceAdapter.buildAttenceAdapter().updateAttendanceRecord( request, attendanceDto ); @@ -137,13 +135,15 @@ export class AttendanceController { image: image?.filename, }; Object.assign(attendanceDto, response); - const result = await this.attendaceService.updateAttendance( + const result = this.attendaceAdapter.buildAttenceAdapter().updateAttendance( attendanceId, request, attendanceDto ); return response.status(result.statusCode).json(result); } + + @Post("/search") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Attendance list." }) @@ -165,7 +165,7 @@ export class AttendanceController { ) { let tenantid = headers["tenantid"]; - const result = await this.attendaceService.searchAttendance( + const result = this.attendaceAdapter.buildAttenceAdapter().searchAttendance( tenantid, request, studentSearchDto @@ -188,7 +188,7 @@ export class AttendanceController { @Body() attendanceDateDto: AttendanceDateDto ) { const tenantId = headers["tenantid"]; - const result = await this.attendaceService.attendanceByDate( + const result = await this.attendaceAdapter.buildAttenceAdapter().attendanceByDate( tenantId, request, attendanceDateDto @@ -214,7 +214,7 @@ export class AttendanceController { @Body() attendanceDtos: BulkAttendanceDTO ) { let tenantId = headers["tenantid"]; - const result = await this.attendaceService.multipleAttendance( + const result = await this.attendaceAdapter.buildAttenceAdapter().multipleAttendance( tenantId, request, attendanceDtos @@ -239,7 +239,7 @@ export class AttendanceController { ) { let tenantid = headers["tenantid"]; - const result = await this.attendaceService.attendanceReport( + const result = await this.attendaceAdapter.buildAttenceAdapter().attendanceReport( attendanceStatsDto ); return response.status(result.statusCode).json(result); diff --git a/src/attendance/attendance.module.ts b/src/attendance/attendance.module.ts index 150b67b3..323c84e3 100644 --- a/src/attendance/attendance.module.ts +++ b/src/attendance/attendance.module.ts @@ -3,18 +3,19 @@ import { AttendanceController } from "./attendance.controller"; import { ScheduleModule } from "@nestjs/schedule"; import { AttendaceAdapter } from "./attendanceadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { AttendanceService } from "./attendance.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { AttendanceEntity } from "./entities/attendance.entity"; import { Repository } from "typeorm"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; @Module({ imports: [ TypeOrmModule.forFeature([AttendanceEntity]), HasuraModule, + PostgresModule, ScheduleModule.forRoot(), ], controllers: [AttendanceController], - providers: [AttendaceAdapter, AttendanceService, Repository], + providers: [AttendaceAdapter, Repository], }) export class AttendanceModule {} diff --git a/src/attendance/attendanceadapter.ts b/src/attendance/attendanceadapter.ts index 1927dbaf..29f3a6e6 100644 --- a/src/attendance/attendanceadapter.ts +++ b/src/attendance/attendanceadapter.ts @@ -1,10 +1,11 @@ import { Inject, Injectable } from "@nestjs/common"; import { IServicelocator } from "src/adapters/attendanceservicelocator"; import { AttendanceHasuraService } from "src/adapters/hasura/attendance.adapter"; +import { PostgresAttendanceService } from "src/adapters/postgres/attendance-adapter"; @Injectable() export class AttendaceAdapter { - constructor(private hasuraProvider: AttendanceHasuraService) {} + constructor(private hasuraProvider: AttendanceHasuraService,private postgresProvider:PostgresAttendanceService) {} buildAttenceAdapter(): IServicelocator { let adapter: IServicelocator; @@ -12,6 +13,9 @@ export class AttendaceAdapter { case "hasura": adapter = this.hasuraProvider; break; + case "postgres": + adapter = this.postgresProvider; + break; } return adapter; } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index db784f4d..6fd7ea10 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -4,7 +4,7 @@ import axios from "axios"; import jwt_decode from "jwt-decode"; import APIResponse from "src/utils/response"; import { KeycloakService } from "src/common/utils/keycloak.service"; -import { User } from "src/user/entities/user-entity"; + type LoginResponse = { access_token: string; @@ -31,7 +31,6 @@ export class AuthService { refresh_expires_in, token_type, } = await this.keycloakService.login(username, password).catch(() => {throw new UnauthorizedException();}); - console.log(access_token); return { access_token, refresh_token, diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index e716a82f..d7c3101b 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -40,7 +40,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @Controller("cohort") @UseGuards(JwtAuthGuard) export class CohortController { - constructor(private readonly cohortService: CohortService) {} + constructor(private readonly cohortService: CohortService,private readonly cohortAdapter:CohortAdapter) {} //create cohort @Post() @ApiConsumes("multipart/form-data") @@ -74,7 +74,7 @@ export class CohortController { tenantId: tenantid, }; Object.assign(cohortCreateDto, payload); - const result = await this.cohortService.createCohort( + const result = await this.cohortAdapter.buildCohortAdapter().createCohort( request, cohortCreateDto ); @@ -98,7 +98,7 @@ export class CohortController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.cohortService.getCohortList( + const result = await this.cohortAdapter.buildCohortAdapter().getCohortList( tenantid, id, request, diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 5b88a555..1779fe4c 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -10,14 +10,17 @@ import { FieldsService } from "../fields/fields.service"; import { Fields } from "../fields/entities/fields.entity"; import { FieldValues } from "../fields/entities/fields-values.entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; +import { PostgresCohortService } from "src/adapters/postgres/cohort-adapter"; @Module({ imports: [ TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers]), HttpModule, HasuraModule, + PostgresModule ], controllers: [CohortController], - providers: [CohortAdapter, CohortService, FieldsService], + providers: [CohortAdapter, CohortService, FieldsService,PostgresCohortService], }) export class CohortModule {} diff --git a/src/cohort/cohortadapter.ts b/src/cohort/cohortadapter.ts index 62988ddb..fbfd2b71 100644 --- a/src/cohort/cohortadapter.ts +++ b/src/cohort/cohortadapter.ts @@ -1,10 +1,11 @@ import { Injectable } from "@nestjs/common"; import { IServicelocatorcohort } from "src/adapters/cohortservicelocator"; import { HasuraCohortService } from "src/adapters/hasura/cohort.adapter"; +import { PostgresCohortService } from "src/adapters/postgres/cohort-adapter"; @Injectable() export class CohortAdapter { - constructor(private hasuraProvider: HasuraCohortService) {} + constructor(private hasuraProvider: HasuraCohortService,private postgresProvider:PostgresCohortService) {} buildCohortAdapter(): IServicelocatorcohort { let adapter: IServicelocatorcohort; @@ -12,6 +13,9 @@ export class CohortAdapter { case "hasura": adapter = this.hasuraProvider; break; + case "hasura": + adapter = this.postgresProvider; + break; } return adapter; } diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index c9e7e1d8..06037aa8 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -59,7 +59,7 @@ export class FieldsController { tenantId: tenantid, }; Object.assign(fieldsDto, payload); - const result = await this.fieldsService.createFields(request, fieldsDto); + const result = await this.fieldsAdapter.buildFieldsAdapter().createFields(request, fieldsDto); return response.status(result.statusCode).json(result); } @@ -83,7 +83,7 @@ export class FieldsController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.fieldsService.searchFields( + const result = await this.fieldsAdapter.buildFieldsAdapter().searchFields( tenantid, request, fieldsSearchDto @@ -106,7 +106,7 @@ export class FieldsController { @Body() fieldValuesDto: FieldValuesDto, @Res() response: Response ) { - const result = await this.fieldsService.createFieldValues( + const result = await this.fieldsAdapter.buildFieldsAdapter().createFieldValues( request, fieldValuesDto ); @@ -128,7 +128,7 @@ export class FieldsController { @Body() fieldValuesSearchDto: FieldValuesSearchDto, @Res() response: Response ) { - const result = await this.fieldsService.searchFieldValues( + const result = await this.fieldsAdapter.buildFieldsAdapter().searchFieldValues( request, fieldValuesSearchDto ); diff --git a/src/fields/fields.module.ts b/src/fields/fields.module.ts index d6d5e348..dd16fe2c 100644 --- a/src/fields/fields.module.ts +++ b/src/fields/fields.module.ts @@ -7,6 +7,7 @@ import { Fields } from "./entities/fields.entity"; import { FieldValues } from "./entities/fields-values.entity"; import { TypeOrmModule } from "@nestjs/typeorm"; import { FieldsService } from "./fields.service"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; @Module({ imports: [ @@ -14,6 +15,7 @@ import { FieldsService } from "./fields.service"; TypeOrmModule.forFeature([FieldValues]), HttpModule, HasuraModule, + PostgresModule ], controllers: [FieldsController], providers: [FieldsAdapter, FieldsService], diff --git a/src/fields/fieldsadapter.ts b/src/fields/fieldsadapter.ts index bd99ac12..b02836b9 100644 --- a/src/fields/fieldsadapter.ts +++ b/src/fields/fieldsadapter.ts @@ -1,10 +1,11 @@ import { Injectable } from "@nestjs/common"; import { IServicelocatorfields } from "src/adapters/fieldsservicelocator"; import { HasuraFieldsService } from "src/adapters/hasura/fields.adapter"; +import { PostgresFieldsService } from "src/adapters/postgres/fields-adapter"; @Injectable() export class FieldsAdapter { - constructor(private hasuraProvider: HasuraFieldsService) {} + constructor(private hasuraProvider: HasuraFieldsService,private postgresProvider:PostgresFieldsService) {} buildFieldsAdapter(): IServicelocatorfields { let adapter: IServicelocatorfields; @@ -12,6 +13,9 @@ export class FieldsAdapter { case "hasura": adapter = this.hasuraProvider; break; + case "postgres": + adapter = this.postgresProvider; + break; } return adapter; } From 006a031b4f8cb6c90729ce1b486107f50307c5aa Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 5 Apr 2024 15:06:10 +0530 Subject: [PATCH 181/408] chore : Removed Group and Group Membership Modules --- src/adapters/groupservicelocator.ts | 12 - src/adapters/hasura/group.adapter.ts | 649 ------------------ .../hasura/groupMembership.adapter.ts | 240 ------- src/adapters/hasura/hasura.module.ts | 7 +- src/app.module.ts | 2 - src/group/dto/group-response.dto.ts | 6 - src/group/dto/group-search.dto.ts | 26 - src/group/dto/group.dto.ts | 105 --- src/group/dto/studentGroupMembership.dto.ts | 293 -------- src/group/group.controller.spec.ts | 18 - src/group/group.controller.ts | 175 ----- src/group/group.module.ts | 12 - src/group/groupadapter.ts | 18 - src/group/interfaces/group.interface.ts | 6 - src/group/utils/file-upload.utils.ts | 18 - .../dto/groupMembership-search.dto.ts | 26 - .../dto/groupMembership.dto.ts | 36 - .../groupMembership.controller.spec.ts | 22 - .../groupMembership.controller.ts | 101 --- src/groupMembership/groupMembership.module.ts | 11 - 20 files changed, 2 insertions(+), 1781 deletions(-) delete mode 100644 src/adapters/groupservicelocator.ts delete mode 100644 src/adapters/hasura/group.adapter.ts delete mode 100644 src/adapters/hasura/groupMembership.adapter.ts delete mode 100644 src/group/dto/group-response.dto.ts delete mode 100644 src/group/dto/group-search.dto.ts delete mode 100644 src/group/dto/group.dto.ts delete mode 100644 src/group/dto/studentGroupMembership.dto.ts delete mode 100644 src/group/group.controller.spec.ts delete mode 100644 src/group/group.controller.ts delete mode 100644 src/group/group.module.ts delete mode 100644 src/group/groupadapter.ts delete mode 100644 src/group/interfaces/group.interface.ts delete mode 100644 src/group/utils/file-upload.utils.ts delete mode 100644 src/groupMembership/dto/groupMembership-search.dto.ts delete mode 100644 src/groupMembership/dto/groupMembership.dto.ts delete mode 100644 src/groupMembership/groupMembership.controller.spec.ts delete mode 100644 src/groupMembership/groupMembership.controller.ts delete mode 100644 src/groupMembership/groupMembership.module.ts diff --git a/src/adapters/groupservicelocator.ts b/src/adapters/groupservicelocator.ts deleted file mode 100644 index 1b57627e..00000000 --- a/src/adapters/groupservicelocator.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { GroupSearchDto } from "src/group/dto/group-search.dto"; -import { GroupDto } from "src/group/dto/group.dto"; - -export interface IServicelocatorgroup { - getGroup(groupId, request); - createGroup(request: any, groupDto: GroupDto); - updateGroup(groupId: string, request: any, groupDto: GroupDto); - searchGroup(request: any, groupSearchDto: GroupSearchDto); - findMembersOfGroup(id, role, request); - findGroupsByUserId(id, role, request); - findMembersOfChildGroup(groupId: string, role: string, request: any); -} diff --git a/src/adapters/hasura/group.adapter.ts b/src/adapters/hasura/group.adapter.ts deleted file mode 100644 index 408d4eb5..00000000 --- a/src/adapters/hasura/group.adapter.ts +++ /dev/null @@ -1,649 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { GroupInterface } from "../../group/interfaces/group.interface"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -const resolvePath = require("object-resolve-path"); -import { GroupDto } from "src/group/dto/group.dto"; -import { GroupSearchDto } from "src/group/dto/group-search.dto"; -import { IServicelocatorgroup } from "../groupservicelocator"; -import { UserDto } from "src/user/dto/user.dto"; -import { StudentDto } from "src/student/dto/student.dto"; -export const HasuraGroupToken = "HasuraGroup"; -@Injectable() -export class HasuraGroupService implements IServicelocatorgroup { - private group: GroupInterface; - - constructor(private httpService: HttpService) {} - - url = `${process.env.BASEAPIURL}`; - - public async getGroup(groupId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetGroup($groupId:uuid!) { - group_by_pk(groupId: $groupId) { - groupId - deactivationReason - created_at - image - mediumOfInstruction - metaData - name - option - schoolId - section - teacherId - gradeLevel - status - type - updated_at - parentId - } - }`, - variables: { - groupId: groupId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = [response?.data?.data?.group_by_pk]; - const groupResponse = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: groupResponse[0], - }); - } - - public async createGroup(request: any, groupDto: GroupDto) { - var axios = require("axios"); - - let query = ""; - Object.keys(groupDto).forEach((e) => { - if (groupDto[e] && groupDto[e] != "") { - if (Array.isArray(groupDto[e])) { - query += `${e}: ${JSON.stringify(groupDto[e])}, `; - } else { - query += `${e}: "${groupDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateGroup { - insert_group_one(object: {${query}}) { - groupId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_group_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateGroup(groupId: string, request: any, groupDto: GroupDto) { - var axios = require("axios"); - - let query = ""; - Object.keys(groupDto).forEach((e) => { - if (groupDto[e] && groupDto[e] != "") { - if (Array.isArray(groupDto[e])) { - query += `${e}: ${JSON.stringify(groupDto[e])}, `; - } else { - query += `${e}: ${groupDto[e]}, `; - } - } - }); - - var data = { - query: `mutation UpdateGroup($groupId:uuid) { - update_group(where: {groupId: {_eq: $groupId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - groupId: groupId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async searchGroup(request: any, groupSearchDto: GroupSearchDto) { - var axios = require("axios"); - - let offset = 0; - if (groupSearchDto.page > 1) { - offset = parseInt(groupSearchDto.limit) * (groupSearchDto.page - 1); - } - - let filters = groupSearchDto.filters; - - Object.keys(groupSearchDto.filters).forEach((item) => { - Object.keys(groupSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchGroup($filters:group_bool_exp,$limit:Int, $offset:Int) { - group_aggregate { - aggregate { - count - } - } - group(where:$filters, limit: $limit, offset: $offset,) { - groupId - deactivationReason - created_at - image - mediumOfInstruction - metaData - name - option - schoolId - section - status - teacherId - gradeLevel - type - updated_at - parentId - } - }`, - variables: { - limit: parseInt(groupSearchDto.limit), - offset: offset, - filters: groupSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.group; - const groupResponse = await this.mappedResponse(result); - const count = response?.data?.data?.group_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: groupResponse, - }); - } - - public async findMembersOfGroup(groupId: string, role: string, request: any) { - let axios = require("axios"); - let userData = []; - var findMember = { - query: `query GetGroupMembership($groupId:uuid,$role:String) { - groupmembership(where: {groupId: {_eq: $groupId}, role: {_eq: $role}}) { - userId - role - } - }`, - variables: { - groupId: groupId, - role: role, - }, - }; - - var getMemberData = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: findMember, - }; - - const response = await axios(getMemberData); - let result = response.data.data.groupmembership; - if (Array.isArray(result)) { - let userIds = result.map((e: any) => { - return e.userId; - }); - if (result[0].role == "Student") { - for (let value of userIds) { - let studentSearch = { - method: "get", - url: `${this.url}/Student/${value}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const response = await axios(studentSearch); - let responseData = await this.StudentMappedResponse([response.data]); - let studentData = responseData[0]; - - userData.push(studentData); - } - } else { - for (let value of userIds) { - let classFinal = { - method: "get", - url: `${this.url}/User/${value}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const responseData = await axios(classFinal); - - let response = await this.userMappedResponse([responseData.data]); - let teacherDetailDto = response[0]; - userData.push(teacherDetailDto); - } - } - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: userData, - }); - } else { - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: { msg: "Unable to get data !!" }, - }); - } - } - - public async findGroupsByUserId(userId: string, role: string, request: any) { - let axios = require("axios"); - var findMember = { - query: `query GetGroup($userId:String,$role:String) { - groupmembership(where: {userId: {_eq: $userId}, role: {_eq: $role}}) { - group { - created_at - deactivationReason - gradeLevel - groupId - image - mediumOfInstruction - metaData - name - option - schoolId - section - status - teacherId - type - updated_at - parentId - } - } - } - `, - variables: { - userId: userId, - role: role, - }, - }; - - var getMemberData = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: findMember, - }; - const response = await axios(getMemberData); - let groupData = response.data.data.groupmembership; - const groupList = groupData.map((e: any) => { - return e.group; - }); - - const groupResponse = await this.mappedResponse(groupList); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: groupResponse, - }); - } - - public async findMembersOfChildGroup( - parentId: string, - role: string, - request: any - ) { - let axios = require("axios"); - let userData = []; - let userIds = []; - var findParentId = { - query: `query GetGroupParentId($parentId:String) { - group(where: {parentId: {_eq: $parentId}}) { - groupId - } - }`, - variables: { - parentId: parentId, - }, - }; - - var getParentId = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: findParentId, - }; - - const groupResponse = await axios(getParentId); - let groupIds = groupResponse.data.data.group.map((e: any) => { - return e.groupId; - }); - - var findMember = { - query: `query GetGroupMembership($groupIds:[uuid!],$role:String) { - groupmembership(where: {groupId: {_in:$groupIds},role: {_eq:$role }}) { - userId - role - } - }`, - variables: { - groupIds, - role: role, - }, - }; - - var getMemberData = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: findMember, - }; - - const response = await axios(getMemberData); - let result = await response.data.data.groupmembership; - - result.map((e: any) => { - return userIds.push(e.userId); - }); - for (let userId of userIds) { - if (role == "Student") { - let studentSearch = { - method: "get", - url: `${this.url}/Student/${userId}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const response = await axios(studentSearch); - - let responseData = await this.StudentMappedResponse([response.data]); - let studentData = responseData[0]; - - userData.push(studentData); - } else { - let classFinal = { - method: "get", - url: `${this.url}/User/${userId}`, - headers: { - Authorization: request.headers.authorization, - }, - }; - - const responseData = await axios(classFinal); - - let response = await this.userMappedResponse([responseData.data]); - let teacherDetailDto = response[0]; - userData.push(teacherDetailDto); - } - } - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: userData, - }); - } - - public async mappedResponse(result: any) { - const groupResponse = result.map((item: any) => { - const groupMapping = { - id: item?.groupId ? `${item.groupId}` : "", - groupId: item?.groupId ? `${item.groupId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - name: item?.name ? `${item.name}` : "", - type: item?.type ? `${item.type}` : "", - section: item?.section ? `${item.section}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - mediumOfInstruction: item?.mediumOfInstruction - ? `${item.mediumOfInstruction}` - : "", - teacherId: item?.teacherId ? `${item.teacherId}` : "", - parentId: item?.parentId ? `${item.parentId}` : "", - image: item?.image ? `${item.image}` : "", - metaData: item?.metaData ? item.metaData : [], - option: item?.option ? item.option : [], - gradeLevel: item?.gradeLevel ? `${item.gradeLevel}` : "", - createdAt: item?.created_at ? `${item.created_at}` : "", - updatedAt: item?.updated_at ? `${item.updated_at}` : "", - }; - return new GroupDto(groupMapping); - }); - - return groupResponse; - } - public async StudentMappedResponse(result: any) { - const studentResponse = result.map((item: any) => { - const studentMapping = { - studentId: item?.osid ? `${item.osid}` : "", - refId1: item?.admissionNo ? `${item.admissionNo}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - groupId: item?.groupId ? `${item.groupId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - studentEmail: item?.studentEmail ? `${item.studentEmail}` : "", - studentPhoneNumber: item?.studentPhoneNumber - ? item.studentPhoneNumber - : "", - iscwsn: item?.iscwsn ? `${item.iscwsn}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - religion: item?.religion ? `${item.religion}` : "", - singleGirl: item?.singleGirl ? item.singleGirl : "", - weight: item?.weight ? `${item.weight}` : "", - height: item?.height ? `${item.height}` : "", - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - homeless: item?.homeless ? item.homeless : "", - bpl: item?.bpl ? item.bpl : "", - migrant: item?.migrant ? item.migrant : "", - status: item?.status ? `${item.status}` : "", - - fatherFirstName: item?.fatherFirstName ? `${item.fatherFirstName}` : "", - - fatherMiddleName: item?.fatherMiddleName - ? `${item.fatherMiddleName}` - : "", - - fatherLastName: item?.fatherLastName ? `${item.fatherLastName}` : "", - fatherPhoneNumber: item?.fatherPhoneNumber - ? item.fatherPhoneNumber - : "", - fatherEmail: item?.fatherEmail ? `${item.fatherEmail}` : "", - - motherFirstName: item?.motherFirstName ? `${item.motherFirstName}` : "", - motherMiddleName: item?.motherMiddleName - ? `${item.motherMiddleName}` - : "", - motherLastName: item?.motherLastName ? `${item.motherLastName}` : "", - motherPhoneNumber: item?.motherPhoneNumber - ? item.motherPhoneNumber - : "", - motherEmail: item?.motherEmail ? `${item.motherEmail}` : "", - - guardianFirstName: item?.guardianFirstName - ? `${item.guardianFirstName}` - : "", - guardianMiddleName: item?.guardianMiddleName - ? `${item.guardianMiddleName}` - : "", - guardianLastName: item?.guardianLastName - ? `${item.guardianLastName}` - : "", - guardianPhoneNumber: item?.guardianPhoneNumber - ? item.guardianPhoneNumber - : "", - guardianEmail: item?.guardianEmail ? `${item.guardianEmail}` : "", - image: item?.image ? `${item.image}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - studentAddress: item?.studentAddress ? `${item.studentAddress}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new StudentDto(studentMapping); - }); - - return studentResponse; - } - - public async userMappedResponse(result: any) { - const userResponse = result.map((item: any) => { - const userMapping = { - userId: item?.osid ? `${item.osid}` : "", - refId1: item?.refId1 ? `${item.refId1}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - refId3: item?.refId3 ? `${item.refId3}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - phoneNumber: item?.phoneNumber ? `${item.phoneNumber}` : "", - email: item?.email ? `${item.email}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - designation: item?.designation ? `${item.designation}` : "", - cadre: item?.cadre ? `${item.cadre}` : "", - profQualification: item?.profQualification - ? `${item.profQualification}` - : "", - joiningDate: item?.joiningDate ? `${item.joiningDate}` : "", - subjectIds: item.subjectIds ? item.subjectIds : [], - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - maritalStatus: item?.maritalStatus ? `${item.maritalStatus}` : "", - compSkills: item?.compSkills ? `${item.compSkills}` : "", - disability: item?.disability ? `${item.disability}` : "", - religion: item?.religion ? `${item.religion}` : "", - homeDistance: item?.homeDistance ? `${item.homeDistance}` : "", - employmentType: item?.employmentType ? `${item.employmentType}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - address: item?.address ? `${item.address}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - image: item?.image ? `${item.image}` : "", - status: item?.status ? `${item.status}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - reportsTo: item?.reportsTo ? `${item.reportsTo}` : "", - retirementDate: item?.retirementDate ? `${item.retirementDate}` : "", - workingStatus: item?.workingStatus ? `${item.workingStatus}` : "", - fcmToken: item?.fcmToken ? `${item.fcmToken}` : "", - role: item?.role ? `${item.role}` : "", - employeeCode: item?.employeeCode ? `${item.employeeCode}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return new UserDto(userMapping); - }); - - return userResponse; - } -} diff --git a/src/adapters/hasura/groupMembership.adapter.ts b/src/adapters/hasura/groupMembership.adapter.ts deleted file mode 100644 index 5f8fd84b..00000000 --- a/src/adapters/hasura/groupMembership.adapter.ts +++ /dev/null @@ -1,240 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -const resolvePath = require("object-resolve-path"); -import { GroupMembershipDto } from "src/groupMembership/dto/groupMembership.dto"; -import { GroupMembershipSearchDto } from "src/groupMembership/dto/groupMembership-search.dto"; - -@Injectable() -export class GroupMembershipService { - constructor(private httpService: HttpService) {} - - public async getGroupMembership(groupMembershipId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetGroupMembership($groupMembershipId:uuid!) { - groupmembership_by_pk(groupMembershipId: $groupMembershipId) { - created_at - groupId - groupMembershipId - schoolId - role - updated_at - userId - } - }`, - variables: { - groupMembershipId: groupMembershipId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = [response?.data?.data?.groupmembership_by_pk]; - let groupMembershipResponse = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: groupMembershipResponse[0], - }); - } - - public async createGroupMembership( - request: any, - groupMembership: GroupMembershipDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(groupMembership).forEach((e) => { - if (groupMembership[e] && groupMembership[e] != "") { - if (Array.isArray(groupMembership[e])) { - query += `${e}: ${JSON.stringify(groupMembership[e])}, `; - } else { - query += `${e}: "${groupMembership[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateGroupMembership { - insert_groupmembership_one(object: {${query}}) { - groupMembershipId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_groupmembership_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateGroupMembership( - groupMembershipId: string, - request: any, - groupMembershipDto: GroupMembershipDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(groupMembershipDto).forEach((e) => { - if (groupMembershipDto[e] && groupMembershipDto[e] != "") { - if (Array.isArray(groupMembershipDto[e])) { - query += `${e}: ${JSON.stringify(groupMembershipDto[e])}, `; - } else { - query += `${e}: ${groupMembershipDto[e]}, `; - } - } - }); - - var data = { - query: `mutation UpdateGroupMembership($groupMembershipId:uuid) { - update_groupmembership(where: { groupMembershipId: {_eq: $ groupMembershipId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - groupMembershipId: groupMembershipId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async searchGroupMembership( - request: any, - groupMembershipSearchDto: GroupMembershipSearchDto - ) { - var axios = require("axios"); - - let offset = 0; - if (groupMembershipSearchDto.page > 1) { - offset = - parseInt(groupMembershipSearchDto.limit) * - (groupMembershipSearchDto.page - 1); - } - - let filters = groupMembershipSearchDto.filters; - - Object.keys(groupMembershipSearchDto.filters).forEach((item) => { - Object.keys(groupMembershipSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchGroupMembership($filters:groupmembership_bool_exp,$limit:Int, $offset:Int) { - groupmembership_aggregate { - aggregate { - count - } - } - groupmembership(where:$filters, limit: $limit, offset: $offset,) { - created_at - groupId - groupMembershipId - schoolId - role - updated_at - userId - } - }`, - variables: { - limit: parseInt(groupMembershipSearchDto.limit), - offset: offset, - filters: groupMembershipSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.groupmembership; - let groupMembershipResponse = await this.mappedResponse(result); - const count = - response?.data?.data?.groupmembership_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: groupMembershipResponse, - }); - } - - public async mappedResponse(result: any) { - const groupMembershipResponse = result.map((obj: any) => { - const groupMembershipMapping = { - id: obj?.groupMembershipId ? `${obj.groupMembershipId}` : "", - groupMembershipId: obj?.groupMembershipId - ? `${obj.groupMembershipId}` - : "", - groupId: obj?.groupId ? `${obj.groupId}` : "", - schoolId: obj?.schoolId ? `${obj.schoolId}` : "", - userId: obj?.userId ? `${obj.userId}` : "", - role: obj?.role ? `${obj.role}` : "", - created_at: obj?.created_at ? `${obj.created_at}` : "", - updated_at: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new GroupMembershipDto(groupMembershipMapping); - }); - - return groupMembershipResponse; - } -} diff --git a/src/adapters/hasura/hasura.module.ts b/src/adapters/hasura/hasura.module.ts index b050363e..67643280 100644 --- a/src/adapters/hasura/hasura.module.ts +++ b/src/adapters/hasura/hasura.module.ts @@ -3,7 +3,6 @@ import { Module } from "@nestjs/common"; import { AttendanceHasuraService } from "./attendance.adapter"; import { HasuraCommentService } from "./comment.adapter"; import { HasuraConfigService } from "./config.adapter"; -import { HasuraGroupService } from "./group.adapter"; import { HasuraHolidayService } from "./holiday.adapter"; import { HasuraLikeService } from "./like.adapter"; import { SchoolHasuraService } from "./school.adapter"; @@ -18,7 +17,6 @@ import { HasuraUserService } from "./user.adapter"; providers: [ AttendanceHasuraService, SchoolHasuraService, - HasuraGroupService, HasuraCohortService, HasuraCohortMembersService, HasuraCommentService, @@ -27,12 +25,11 @@ import { HasuraUserService } from "./user.adapter"; HasuraHolidayService, HasuraFieldsService, FieldsService, - HasuraUserService + HasuraUserService, ], exports: [ AttendanceHasuraService, SchoolHasuraService, - HasuraGroupService, HasuraCohortService, HasuraCohortMembersService, HasuraCommentService, @@ -40,7 +37,7 @@ import { HasuraUserService } from "./user.adapter"; HasuraLikeService, HasuraHolidayService, HasuraFieldsService, - HasuraUserService + HasuraUserService, ], }) export class HasuraModule {} diff --git a/src/app.module.ts b/src/app.module.ts index 20242342..5820640e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -28,8 +28,6 @@ import { AuthModule } from "./auth/auth.module"; import { DatabaseModule } from "./common/database.module"; import { SwaggerModule } from "@nestjs/swagger"; // Below modules no longer required in Shiksha 2.0 -// import { GroupModule } from "./group/group.module"; -// import { GroupMembershipModule } from "./groupMembership/groupMembership.module"; // import { StudentModule } from "./student/student.module"; @Module({ diff --git a/src/group/dto/group-response.dto.ts b/src/group/dto/group-response.dto.ts deleted file mode 100644 index dd7f5688..00000000 --- a/src/group/dto/group-response.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface GroupResponseDto { - groupId: string; - name: string; - type: string; - status: string; -} diff --git a/src/group/dto/group-search.dto.ts b/src/group/dto/group-search.dto.ts deleted file mode 100644 index a9e10f69..00000000 --- a/src/group/dto/group-search.dto.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class GroupSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Number, - description: "number", - }) - page: number; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/group/dto/group.dto.ts b/src/group/dto/group.dto.ts deleted file mode 100644 index c56d28d9..00000000 --- a/src/group/dto/group.dto.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Exclude, Expose } from "class-transformer"; -import { - MaxLength, - IsNotEmpty, - IsEmail, - IsString, - IsNumber, -} from "class-validator"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class GroupDto { - @Expose() - id: string; - - @Expose() - groupId: string; - - @ApiPropertyOptional({ - type: String, - description: "The schoolId of the group", - }) - @Expose() - schoolId: string; - - @ApiPropertyOptional({ - type: String, - description: "The name of the group", - }) - @Expose() - name: string; - - @ApiPropertyOptional({ - type: String, - description: "The type of the group", - }) - @Expose() - type: string; - - @ApiPropertyOptional({ - type: String, - description: "The section of the group", - }) - @Expose() - section: string; - - @ApiPropertyOptional({ - type: String, - description: "The status of the group", - }) - @Expose() - status: string; - - @ApiPropertyOptional({ - type: String, - description: "Teacher Id of Group", - }) - @Expose() - teacherId: string; - - @ApiPropertyOptional({ - type: String, - description: "Parent Id of Group", - }) - @Expose() - parentId: string; - - @ApiPropertyOptional() - @Expose() - deactivationReason: string; - - @ApiPropertyOptional({ - type: String, - description: "The mediumOfInstruction of the group", - }) - @Expose() - mediumOfInstruction: string; - - @ApiPropertyOptional({ type: "string", format: "binary" }) - @Expose() - image: string; - - @ApiPropertyOptional() - @Expose() - metaData: [string]; - - @ApiPropertyOptional() - @Expose() - option: [string]; - - @ApiPropertyOptional({ - description: "Grade against group", - }) - @Expose() - gradeLevel: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/group/dto/studentGroupMembership.dto.ts b/src/group/dto/studentGroupMembership.dto.ts deleted file mode 100644 index 9611aecc..00000000 --- a/src/group/dto/studentGroupMembership.dto.ts +++ /dev/null @@ -1,293 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { Exclude, Expose } from "class-transformer"; - -export class StudentGroupMembershipDto { - @Expose() - studentId: string; - - @ApiProperty() - @Expose() - refId1: string; - - @ApiProperty() - @Expose() - refId2: string; - - @ApiPropertyOptional() - @Expose() - aadhaar: string; - - @ApiProperty() - @Expose() - firstName: string; - - @ApiProperty() - @Expose() - middleName: string; - - @ApiProperty() - @Expose() - lastName: string; - - @ApiProperty() - @Expose() - schoolId: string; - - @ApiProperty() - @Expose() - studentPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - studentEmail: string; - - @ApiProperty() - @Expose() - gender: string; - - @ApiProperty() - @Expose() - groupId: string; - - @ApiPropertyOptional() - @Expose() - socialCategory: string; - - @ApiPropertyOptional() - @Expose() - iscwsn: string; - - @ApiPropertyOptional() - @Expose() - religion: string; - - @ApiPropertyOptional() - @Expose() - singleGirl: Boolean; - - @ApiPropertyOptional() - @Expose() - weight: string; - - @ApiPropertyOptional() - @Expose() - height: string; - - @ApiPropertyOptional() - @Expose() - bloodGroup: string; - - @ApiProperty() - @Expose() - birthDate: string; - - @ApiPropertyOptional() - @Expose() - homeless: Boolean; - - @ApiProperty() - @Expose() - bpl: Boolean; - - @ApiProperty() - @Expose() - migrant: Boolean; - - @ApiProperty() - @Expose() - status: string; - - @ApiPropertyOptional() - @Expose() - fatherFirstName: string; - - @ApiPropertyOptional() - @Expose() - fatherMiddleName: string; - - @ApiPropertyOptional() - @Expose() - fatherLastName: string; - - @ApiPropertyOptional() - @Expose() - fatherPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - fatherEmail: string; - - @ApiPropertyOptional() - @Expose() - motherFirstName: string; - - @ApiPropertyOptional() - @Expose() - motherMiddleName: string; - - @ApiPropertyOptional() - @Expose() - motherLastName: string; - - @ApiPropertyOptional() - @Expose() - motherPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - motherEmail: string; - - @ApiPropertyOptional() - @Expose() - guardianFirstName: string; - - @ApiPropertyOptional() - @Expose() - guardianMiddleName: string; - - @ApiPropertyOptional() - @Expose() - guardianLastName: string; - - @ApiPropertyOptional() - @Expose() - guardianPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - guardianEmail: string; - - @ApiPropertyOptional({ - type: "string", - format: "binary", - }) - @Expose() - image: string; - - @ApiPropertyOptional() - @Expose() - studentAddress: string; - - @ApiProperty() - @Expose() - village: string; - - @ApiProperty() - @Expose() - block: string; - - @ApiProperty() - @Expose() - district: string; - - @ApiProperty() - @Expose() - stateId: string; - - @ApiProperty() - @Expose() - pincode: Number; - - @ApiProperty() - @Expose() - locationId: string; - - @ApiPropertyOptional() - @Expose() - deactivationReason: string; - - @ApiPropertyOptional() - @Expose() - metaData: [string]; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: any) { - this.studentId = obj?.id ? `${obj.id}` : ""; - this.refId1 = obj?.admission_number ? `${obj.admission_number}` : ""; - this.refId2 = obj?.ref_student_id ? `${obj.ref_student_id}` : ""; - this.aadhaar = obj?.aadhaar ? `${obj.aadhaar}` : ""; - this.firstName = obj?.name ? `${obj.name}` : ""; - this.middleName = obj?.middleName ? `${obj.middleName}` : ""; - this.lastName = obj?.lastName ? `${obj.lastName}` : ""; - this.groupId = obj?.grade_number ? `${obj.grade_number}` : ""; - this.schoolId = obj?.school_id ? `${obj.school_id}` : ""; - this.studentEmail = obj?.studentEmail ? `${obj.studentEmail}` : ""; - this.studentPhoneNumber = obj?.phone ? obj.phone : ""; - this.iscwsn = obj?.is_cwsn ? `${obj.is_cwsn}` : ""; - this.gender = obj?.gender ? `${obj.gender}` : ""; - this.socialCategory = obj?.socialCategory ? `${obj.socialCategory}` : ""; - this.religion = obj?.religion ? `${obj.religion}` : ""; - this.singleGirl = obj?.singleGirl ? obj.singleGirl : ""; - this.weight = obj?.weight ? `${obj.weight}` : ""; - this.height = obj?.height ? `${obj.height}` : ""; - this.bloodGroup = obj?.bloodGroup ? `${obj.bloodGroup}` : ""; - this.birthDate = obj?.dob ? `${obj.dob}` : ""; - this.homeless = obj?.homeless ? obj.homeless : ""; - this.bpl = obj?.is_bpl ? obj.is_bpl : ""; - this.migrant = obj?.is_migrant ? obj.is_migrant : ""; - this.status = obj?.status ? `${obj.status}` : ""; - - this.fatherFirstName = obj?.fatherFirstName ? `${obj.fatherFirstName}` : ""; - - this.fatherMiddleName = obj?.fatherMiddleName - ? `${obj.fatherMiddleName}` - : ""; - - this.fatherLastName = obj?.father_name ? `${obj.father_name}` : ""; - this.fatherPhoneNumber = obj?.fatherPhoneNumber - ? obj.fatherPhoneNumber - : ""; - this.fatherEmail = obj?.fatherEmail ? `${obj.fatherEmail}` : ""; - - this.motherFirstName = obj?.mother_name ? `${obj.mother_name}` : ""; - this.motherMiddleName = obj?.motherMiddleName - ? `${obj.motherMiddleName}` - : ""; - this.motherLastName = obj?.motherLastName ? `${obj.motherLastName}` : ""; - this.motherPhoneNumber = obj?.motherPhoneNumber - ? obj.motherPhoneNumber - : ""; - this.motherEmail = obj?.motherEmail ? `${obj.motherEmail}` : ""; - - this.guardianFirstName = obj?.guardianFirstName - ? `${obj.guardianFirstName}` - : ""; - this.guardianMiddleName = obj?.guardianMiddleName - ? `${obj.guardianMiddleName}` - : ""; - this.guardianLastName = obj?.guardianLastName - ? `${obj.guardianLastName}` - : ""; - this.guardianPhoneNumber = obj?.guardianPhoneNumber - ? obj.guardianPhoneNumber - : ""; - this.guardianEmail = obj?.guardianEmail ? `${obj.guardianEmail}` : ""; - this.image = obj?.image ? `${obj.image}` : ""; - this.deactivationReason = obj?.deactivationReason - ? `${obj.deactivationReason}` - : ""; - this.studentAddress = obj?.studentAddress ? `${obj.studentAddress}` : ""; - this.village = obj?.village ? `${obj.village}` : ""; - this.block = obj?.block ? `${obj.block}` : ""; - this.district = obj?.district ? `${obj.district}` : ""; - this.stateId = obj?.stateId ? `${obj.stateId}` : ""; - this.pincode = obj?.pincode ? obj.pincode : ""; - this.locationId = obj?.locationId ? `${obj.locationId}` : ""; - this.metaData = obj?.metaData ? obj.metaData : []; - this.createdAt = obj?.created ? `${obj.created}` : ""; - this.updatedAt = obj?.updated ? `${obj.updated}` : ""; - this.createdBy = obj?.osCreatedBy ? `${obj.osCreatedBy}` : ""; - this.updatedBy = obj?.osUpdatedBy ? `${obj.osUpdatedBy}` : ""; - } -} diff --git a/src/group/group.controller.spec.ts b/src/group/group.controller.spec.ts deleted file mode 100644 index 511d14dd..00000000 --- a/src/group/group.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from "@nestjs/testing"; -import { GroupController } from "./group.controller"; - -describe("GroupController", () => { - let controller: GroupController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [GroupController], - }).compile(); - - controller = module.get(GroupController); - }); - - it("should be defined", () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/group/group.controller.ts b/src/group/group.controller.ts deleted file mode 100644 index 9890d581..00000000 --- a/src/group/group.controller.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiConsumes, - ApiExcludeController, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Query, - UploadedFile, -} from "@nestjs/common"; -import { GroupSearchDto } from "./dto/group-search.dto"; -import { Request } from "@nestjs/common"; -import { GroupDto } from "./dto/group.dto"; -import { FileInterceptor } from "@nestjs/platform-express"; -import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; -import { diskStorage } from "multer"; - -import { GroupAdapter } from "./groupadapter"; - -// @ApiTags("Group") -@ApiExcludeController() -@Controller("group") -export class GroupController { - constructor(private groupAdapter: GroupAdapter) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getGroup(@Param("id") groupId: string, @Req() request: Request) { - return this.groupAdapter.buildGroupAdapter().getGroup(groupId, request); - } - - @Post() - // @ApiConsumes("multipart/form-data") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Group has been created successfully." }) - @UseInterceptors( - FileInterceptor("image", { - storage: diskStorage({ - destination: process.env.IMAGEPATH, - filename: editFileName, - }), - fileFilter: imageFileFilter, - }) - ) - // @ApiBody({ type: GroupDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createGroup( - @Req() request: Request, - @Body() groupDto: GroupDto, - @UploadedFile() image - ) { - const response = { - image: image?.filename, - }; - Object.assign(groupDto, response); - - return this.groupAdapter.buildGroupAdapter().createGroup(request, groupDto); - } - - @Put("/:id") - // @ApiConsumes("multipart/form-data") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Group has been updated successfully." }) - @UseInterceptors( - FileInterceptor("image", { - storage: diskStorage({ - destination: process.env.IMAGEPATH, - filename: editFileName, - }), - fileFilter: imageFileFilter, - }) - ) - // @ApiBody({ type: GroupDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateGroup( - @Param("id") groupId: string, - @Req() request: Request, - @Body() groupDto: GroupDto, - @UploadedFile() image - ) { - const response = { - image: image?.filename, - }; - Object.assign(groupDto, response); - - return this.groupAdapter - .buildGroupAdapter() - .updateGroup(groupId, request, groupDto); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Group list." }) - // @ApiBody({ type: GroupSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchGroup( - @Req() request: Request, - @Body() groupSearchDto: GroupSearchDto - ) { - return this.groupAdapter - .buildGroupAdapter() - .searchGroup(request, groupSearchDto); - } - - @Get(":groupId/participants") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Group detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - public async findMembersOfGroup( - @Param("groupId") id: string, - @Query("role") role: string, - @Req() request: Request - ) { - return this.groupAdapter - .buildGroupAdapter() - .findMembersOfGroup(id, role, request); - } - - @Get("participant/:userId") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Group detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - public async getGroupsByUserId( - @Param("userId") id: string, - @Query("role") role: string, - @Req() request: Request - ) { - return this.groupAdapter - .buildGroupAdapter() - .findGroupsByUserId(id, role, request); - } - - @Get(":groupId/child") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Group detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - public async findMembersOfChildGroup( - @Param("groupId") id: string, - @Query("role") role: string, - @Req() request: Request - ) { - return this.groupAdapter - .buildGroupAdapter() - .findMembersOfChildGroup(id, role, request); - } -} diff --git a/src/group/group.module.ts b/src/group/group.module.ts deleted file mode 100644 index f56c5845..00000000 --- a/src/group/group.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from "@nestjs/common"; -import { GroupController } from "./group.controller"; -import { HttpModule } from "@nestjs/axios"; -import { GroupAdapter } from "./groupadapter"; -import { HasuraModule } from "src/adapters/hasura/hasura.module"; - -@Module({ - imports: [HttpModule, HasuraModule], - controllers: [GroupController], - providers: [GroupAdapter], -}) -export class GroupModule {} diff --git a/src/group/groupadapter.ts b/src/group/groupadapter.ts deleted file mode 100644 index 593aa6c6..00000000 --- a/src/group/groupadapter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { IServicelocatorgroup } from "src/adapters/groupservicelocator"; -import { HasuraGroupService } from "src/adapters/hasura/group.adapter"; - -@Injectable() -export class GroupAdapter { - constructor(private hasuraProvider: HasuraGroupService) {} - buildGroupAdapter(): IServicelocatorgroup { - let adapter: IServicelocatorgroup; - - switch (process.env.ADAPTERSOURCE) { - case "hasura": - adapter = this.hasuraProvider; - break; - } - return adapter; - } -} diff --git a/src/group/interfaces/group.interface.ts b/src/group/interfaces/group.interface.ts deleted file mode 100644 index 328b6f2a..00000000 --- a/src/group/interfaces/group.interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface GroupInterface { - groupId?: string; - name?: string; - type?: string; - status?: string; -} diff --git a/src/group/utils/file-upload.utils.ts b/src/group/utils/file-upload.utils.ts deleted file mode 100644 index a6ccb3cb..00000000 --- a/src/group/utils/file-upload.utils.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { extname } from "path"; - -export const imageFileFilter = (req, file, callback) => { - if (!file.originalname.match(/.(jpg|jpeg|png|gif)$/)) { - return callback(new Error("Only image files are allowed!"), false); - } - callback(null, true); -}; - -export const editFileName = (req, file, callback) => { - const name = file.originalname.split(".")[0]; - const fileExtName = extname(file.originalname); - const randomName = Array(4) - .fill(null) - .map(() => Math.round(Math.random() * 16).toString(16)) - .join(""); - callback(null, `${name}-${randomName}${fileExtName}`); -}; diff --git a/src/groupMembership/dto/groupMembership-search.dto.ts b/src/groupMembership/dto/groupMembership-search.dto.ts deleted file mode 100644 index 9c0b1557..00000000 --- a/src/groupMembership/dto/groupMembership-search.dto.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class GroupMembershipSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Number, - description: "Page", - }) - page: number; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/groupMembership/dto/groupMembership.dto.ts b/src/groupMembership/dto/groupMembership.dto.ts deleted file mode 100644 index 1148f3bf..00000000 --- a/src/groupMembership/dto/groupMembership.dto.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Exclude, Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class GroupMembershipDto { - @Expose() - id: string; - - @Expose() - groupMembershipId: string; - - @ApiProperty() - @Expose() - groupId: string; - - @ApiProperty() - @Expose() - schoolId: string; - - @ApiProperty() - @Expose() - userId: string; - - @ApiProperty() - @Expose() - role: string; - - @Expose() - created_at: string; - - @Expose() - updated_at: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/groupMembership/groupMembership.controller.spec.ts b/src/groupMembership/groupMembership.controller.spec.ts deleted file mode 100644 index 6690fc44..00000000 --- a/src/groupMembership/groupMembership.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from "@nestjs/testing"; -import { GroupMembershipService } from "src/adapters/hasura/groupMembership.adapter"; -import { GroupMembershipController } from "./groupMembership.controller"; - -describe("GroupMembershipController", () => { - let controller: GroupMembershipController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [GroupMembershipController], - providers: [GroupMembershipService], - }).compile(); - - controller = module.get( - GroupMembershipController - ); - }); - - it("should be defined", () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/groupMembership/groupMembership.controller.ts b/src/groupMembership/groupMembership.controller.ts deleted file mode 100644 index 94f943e8..00000000 --- a/src/groupMembership/groupMembership.controller.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { - ApiTags, - ApiBody, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiExcludeController, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Request, -} from "@nestjs/common"; - -import { GroupMembershipDto } from "./dto/groupMembership.dto"; -import { GroupMembershipSearchDto } from "./dto/groupMembership-search.dto"; -import { GroupMembershipService } from "src/adapters/hasura/groupMembership.adapter"; - -// @ApiTags("Group Membership") -@ApiExcludeController() -@Controller("groupmembership") -export class GroupMembershipController { - constructor(private service: GroupMembershipService) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Group Membership detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getGroupMembership( - @Param("id") groupMembershipId: string, - @Req() request: Request - ) { - return this.service.getGroupMembership(groupMembershipId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Group Membership has been created successfully.", - // }) - // @ApiBody({ type: GroupMembershipDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createGroupMembership( - @Req() request: Request, - @Body() groupMembershipDto: GroupMembershipDto - ) { - return this.service.createGroupMembership(request, groupMembershipDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Group Membership has been updated successfully.", - // }) - // @ApiBody({ type: GroupMembershipDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateGroupMembership( - @Param("id") groupMembershipId: string, - @Req() request: Request, - @Body() groupMembersipDto: GroupMembershipDto - ) { - return this.service.updateGroupMembership( - groupMembershipId, - request, - groupMembersipDto - ); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Group Membership list." }) - // @ApiBody({ type: GroupMembershipSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchGroupMembership( - @Req() request: Request, - @Body() groupMembershipSearchDto: GroupMembershipSearchDto - ) { - return this.service.searchGroupMembership( - request, - groupMembershipSearchDto - ); - } -} diff --git a/src/groupMembership/groupMembership.module.ts b/src/groupMembership/groupMembership.module.ts deleted file mode 100644 index 3ce449f6..00000000 --- a/src/groupMembership/groupMembership.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { GroupMembershipController } from "./groupMembership.controller"; -import { GroupMembershipService } from "src/adapters/hasura/groupMembership.adapter"; - -@Module({ - imports: [HttpModule], - controllers: [GroupMembershipController], - providers: [GroupMembershipService], -}) -export class GroupMembershipModule {} From 44413bc241c3cb7f59b6da942340e733b55dbc21 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 5 Apr 2024 15:34:20 +0530 Subject: [PATCH 182/408] chore : commented modules that are not in use --- src/app.module.ts | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/src/app.module.ts b/src/app.module.ts index 5820640e..9968fb8a 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,14 +1,15 @@ import { Module } from "@nestjs/common"; +import { ConfigModule } from "@nestjs/config"; import { AppController } from "./app.controller"; import { AppService } from "./app.service"; -import { UserModule } from "./user/user.module"; +import { MulterModule } from "@nestjs/platform-express/multer"; +/* +// Below modules not in use for Shiksha 2.0 +import { StudentModule } from "./student/student.module"; import { SchoolModule } from "./school/school.module"; -import { AttendanceModule } from "./attendance/attendance.module"; import { HolidayModule } from "./holiday/holiday.module"; import { ConfigurationModule } from "./configs/configuration.module"; -import { ConfigModule } from "@nestjs/config"; import { WorksheetModule } from "./worksheet/worksheet.module"; -import { MulterModule } from "@nestjs/platform-express/multer"; import { QuestionModule } from "./Question/question.module"; import { LikeModule } from "./like/like.module"; import { CommentModule } from "./comment/comment.module"; @@ -16,19 +17,18 @@ import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module" import { AssessmentSetModule } from "./assessmentset/assessmentset.module"; import { MentorTrackingModule } from "./mentorTracking/mentorTracking.module"; import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module"; -import { CourseModule } from "./course/course.module"; -import { CourseTrackingModule } from "./courseTracking/courseTracking.module"; import { AnnouncementsModule } from "./announcements/announcements.module"; -import { RoleModule } from "./role/role.module"; import { WorkHistoryModule } from "./workHistory/workHistory.module"; +*/ +// In use for Shiksha 2.0 +import { DatabaseModule } from "./common/database.module"; +import { AuthModule } from "./auth/auth.module"; import { CohortModule } from "./cohort/cohort.module"; import { CohortMembersModule } from "./cohortMembers/cohortMembers.module"; import { FieldsModule } from "./fields/fields.module"; -import { AuthModule } from "./auth/auth.module"; -import { DatabaseModule } from "./common/database.module"; -import { SwaggerModule } from "@nestjs/swagger"; -// Below modules no longer required in Shiksha 2.0 -// import { StudentModule } from "./student/student.module"; +import { RoleModule } from "./role/role.module"; +import { AttendanceModule } from "./attendance/attendance.module"; +import { UserModule } from "./user/user.module"; @Module({ imports: [ @@ -36,29 +36,14 @@ import { SwaggerModule } from "@nestjs/swagger"; MulterModule.register({ dest: "./uploads", }), - SchoolModule, UserModule, RoleModule, AttendanceModule, - HolidayModule, - ConfigurationModule, - WorksheetModule, - QuestionModule, - LikeModule, - CommentModule, - TrackAssessmentModule, - AssessmentSetModule, - MentorTrackingModule, - MonitorTrackingModule, - CourseModule, - CourseTrackingModule, - AnnouncementsModule, - WorkHistoryModule, CohortModule, CohortMembersModule, FieldsModule, AuthModule, - DatabaseModule + DatabaseModule, ], controllers: [AppController], providers: [AppService], From a3072084a7346def6b04330fe36129bc9f956ab8 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 5 Apr 2024 15:39:38 +0530 Subject: [PATCH 183/408] Role: Create, Update, Search, Delete role data --- src/app.module.ts | 2 +- src/rbac/dto/rbac-search.dto.ts | 29 +++++++ src/rbac/dto/rbac.dto.ts | 19 +++++ src/rbac/entities/rbac.entity.ts | 10 +++ src/rbac/rbac.controller.ts | 138 +++++++++++++++++++++++++++++++ src/rbac/rbac.module.ts | 17 ++++ src/rbac/rbac.service.spec.ts | 18 ++++ src/rbac/rbac.service.ts | 135 ++++++++++++++++++++++++++++++ src/role/role.controller.ts | 99 ---------------------- src/role/role.module.ts | 11 --- 10 files changed, 367 insertions(+), 111 deletions(-) create mode 100644 src/rbac/dto/rbac-search.dto.ts create mode 100644 src/rbac/dto/rbac.dto.ts create mode 100644 src/rbac/entities/rbac.entity.ts create mode 100644 src/rbac/rbac.controller.ts create mode 100644 src/rbac/rbac.module.ts create mode 100644 src/rbac/rbac.service.spec.ts create mode 100644 src/rbac/rbac.service.ts delete mode 100644 src/role/role.controller.ts delete mode 100644 src/role/role.module.ts diff --git a/src/app.module.ts b/src/app.module.ts index 20242342..f39f6df2 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -19,7 +19,7 @@ import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module" import { CourseModule } from "./course/course.module"; import { CourseTrackingModule } from "./courseTracking/courseTracking.module"; import { AnnouncementsModule } from "./announcements/announcements.module"; -import { RoleModule } from "./role/role.module"; +import { RoleModule } from "./rbac/rbac.module"; import { WorkHistoryModule } from "./workHistory/workHistory.module"; import { CohortModule } from "./cohort/cohort.module"; import { CohortMembersModule } from "./cohortMembers/cohortMembers.module"; diff --git a/src/rbac/dto/rbac-search.dto.ts b/src/rbac/dto/rbac-search.dto.ts new file mode 100644 index 00000000..41ee1a8d --- /dev/null +++ b/src/rbac/dto/rbac-search.dto.ts @@ -0,0 +1,29 @@ +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { IsNumberString } from "class-validator"; + + +export class RoleSearchDto { + @ApiProperty({ + type: String, + description: "Limit", + }) + @IsNumberString() + limit: string; + + @ApiProperty({ + type: Number, + description: "number", + }) + page: number; + + @ApiProperty({ + type: Object, + description: "Filters", + }) + @ApiPropertyOptional() + filters: object; + + constructor(partial: Partial) { + Object.assign(this, partial); + } +} diff --git a/src/rbac/dto/rbac.dto.ts b/src/rbac/dto/rbac.dto.ts new file mode 100644 index 00000000..703c467d --- /dev/null +++ b/src/rbac/dto/rbac.dto.ts @@ -0,0 +1,19 @@ +import { Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; + +export class RoleDto { + @Expose() + roleId: string; + + @ApiProperty({ + type: String, + description: "The name of the role", + default: "", + }) + @Expose() + roleName: string; + + constructor(obj: any) { + Object.assign(this, obj); + } +} diff --git a/src/rbac/entities/rbac.entity.ts b/src/rbac/entities/rbac.entity.ts new file mode 100644 index 00000000..67064749 --- /dev/null +++ b/src/rbac/entities/rbac.entity.ts @@ -0,0 +1,10 @@ +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + +@Entity({ name: "Role" }) +export class Role { + @PrimaryGeneratedColumn('uuid') + roleId: string; + + @Column() + roleName: string; +} diff --git a/src/rbac/rbac.controller.ts b/src/rbac/rbac.controller.ts new file mode 100644 index 00000000..514bdc04 --- /dev/null +++ b/src/rbac/rbac.controller.ts @@ -0,0 +1,138 @@ +import { + Controller, + Get, + Post, + Body, + Put, + Param, + UseInterceptors, + ClassSerializerInterceptor, + SerializeOptions, + Req, + Query, + UsePipes, + ValidationPipe, + Res, + Headers, + Delete, + UseGuards, +} from "@nestjs/common"; +import { + ApiTags, + ApiBody, + ApiOkResponse, + ApiForbiddenResponse, + ApiCreatedResponse, + ApiBasicAuth, + ApiQuery, + ApiExcludeController, + ApiConsumes, + ApiHeader, +} from "@nestjs/swagger"; +import { Request } from "@nestjs/common"; +import { RoleDto } from "./dto/rbac.dto"; +import { RoleSearchDto } from "./dto/rbac-search.dto"; +// import { RoleService } from "src/adapters/hasura/role.adapter"; +import { RoleService } from "./rbac.service"; +import { Response, response } from "express"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; + + +@ApiTags("rbac") +@Controller("rbac") +@UseGuards(JwtAuthGuard) +export class RoleController { + constructor(private readonly roleService: RoleService) { } + + //Get role + @Get("/:id") + @UseInterceptors(ClassSerializerInterceptor) + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Role detail." }) + @ApiHeader({ name: "tenantid" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({strategy: "excludeAll",}) + public async getRole( + @Param("id") roleId: string, + @Req() request: Request, + @Res() response: Response + ) { + const result = await this.roleService.getRole(roleId, request); + return response.status(result.statusCode).json(result); + } + + //Create role + @Post() + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Role has been created successfully." }) + @ApiBody({ type: RoleDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid" }) + @UseInterceptors(ClassSerializerInterceptor) + public async createRole( + @Req() request: Request, + @Body() roleDto: RoleDto, + @Res() response: Response + ) { + const result = await this.roleService.createRole(request, roleDto); + return response.status(result.statusCode).json(result); + } + + //Update Role + @Put("/:id") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Role updated successfully." }) + @ApiBody({ type: RoleDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid", }) + @UseInterceptors(ClassSerializerInterceptor) + public async updateRole( + @Param("id") roleId: string, + @Req() request: Request, + @Body() roleDto: RoleDto, + @Res() response: Response + ) { + const result = await this.roleService.updateRole(roleId, request, roleDto); + return response.status(result.statusCode).json(result); + } + + // search Role + @Post("/search") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Role list." }) + @ApiBody({ type: RoleSearchDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UsePipes(ValidationPipe) + @SerializeOptions({ strategy: "excludeAll", }) + @ApiHeader({ name: "tenantid" }) + @UseInterceptors(ClassSerializerInterceptor) + public async searchRole( + @Headers() headers, + @Req() request: Request, + @Body() roleSearchDto: RoleSearchDto, + @Res() response: Response + ) { + let tenantid = headers["tenantid"]; + const result = await this.roleService.searchRole( + tenantid, + request, + roleSearchDto + ); + return response.status(result.statusCode).json(result); + } + + //delete cohort + @Delete("/:id") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Role deleted successfully." }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @UseInterceptors(ClassSerializerInterceptor) + public async deleteRole( + @Param("id") roleId: string, + @Res() response: Response + ) { + const result = await this.roleService.deleteRole(roleId); + return response.status(result.statusCode).json(result); + } + +} diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts new file mode 100644 index 00000000..38de9a11 --- /dev/null +++ b/src/rbac/rbac.module.ts @@ -0,0 +1,17 @@ +import { HttpModule } from "@nestjs/axios"; +import { Module } from "@nestjs/common"; +// import { RoleService } from "src/adapters/hasura/role.adapter"; +import { RoleController } from "./rbac.controller"; +import { Role } from "./entities/rbac.entity"; +import { RoleService } from "./rbac.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Role]), + HttpModule + ], + controllers: [RoleController], + providers: [RoleService], +}) +export class RoleModule {} diff --git a/src/rbac/rbac.service.spec.ts b/src/rbac/rbac.service.spec.ts new file mode 100644 index 00000000..22d86b42 --- /dev/null +++ b/src/rbac/rbac.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { RoleService } from './rbac.service'; + +describe('RoleService', () => { + let service: RoleService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [RoleService], + }).compile(); + + service = module.get(RoleService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/rbac/rbac.service.ts b/src/rbac/rbac.service.ts new file mode 100644 index 00000000..dc14f292 --- /dev/null +++ b/src/rbac/rbac.service.ts @@ -0,0 +1,135 @@ +import { HttpStatus, Injectable } from '@nestjs/common'; +import { Role } from "./entities/rbac.entity"; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { RoleDto } from "./dto/rbac.dto"; +import { SuccessResponse } from 'src/success-response'; +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { v4 as uuidv4 } from 'uuid'; +import { RoleSearchDto } from "./dto/rbac-search.dto"; + +@Injectable() +export class RoleService { + constructor( + @InjectRepository(Role) + private roleRepository: Repository + ) { } + public async createRole(request: any, roleDto: RoleDto) { + try { + const response = await this.roleRepository.save(roleDto); + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: response, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async getRole(roleId: string, request: any) { + + try { + const [results, totalCount] = await this.roleRepository.findAndCount({ + where: { roleId } + }) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + totalCount, + data: results, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + + + + } + + public async updateRole(roleId: string, request: any, roleDto: RoleDto) { + try { + const response = await this.roleRepository.update(roleId,roleDto) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) { + try { + + let { limit, page, filters } = roleSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + + const [results, totalCount] = await this.roleRepository.findAndCount({ + where: whereClause, + skip: offset, + take: parseInt(limit), + }); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + totalCount, + data: results, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async deleteRole(roleId: string) { + try { + let response = await this.roleRepository.delete(roleId) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Role deleted successfully.', + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } +} + + diff --git a/src/role/role.controller.ts b/src/role/role.controller.ts deleted file mode 100644 index 61d51efb..00000000 --- a/src/role/role.controller.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Query, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, - ApiExcludeController, -} from "@nestjs/swagger"; -import { Request } from "@nestjs/common"; -import { RoleDto } from "./dto/role.dto"; -import { RoleService } from "src/adapters/hasura/role.adapter"; - -// @ApiTags("Role") -@ApiExcludeController() -@Controller("role") -export class RoleController { - constructor(private readonly service: RoleService) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "role detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getRole(@Param("id") roleId: string, @Req() request: Request) { - return this.service.getRole(roleId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Role has been created successfully.", - // }) - // @ApiBody({ type: RoleDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async creatRole(@Req() request: Request, @Body() roleDto: RoleDto) { - return this.service.createRole(request, roleDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Role has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateRole( - @Param("id") roleId: string, - @Req() request: Request, - @Body() roleDto: RoleDto - ) { - return await this.service.updateRole(roleId, request, roleDto); - } - - @Post("/search") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: " Ok." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "limit", required: false }) - // @ApiQuery({ name: "roleId", required: false }) - // @ApiQuery({ name: "title", required: false }) - // @ApiQuery({ name: "parentId", required: false }) - // @ApiQuery({ name: "status", required: false }) - public async searchRole( - @Query("limit") limit: string, - @Query("roleId") roleId: string, - @Query("title") title: string, - @Query("parentId") parentId: string, - @Query("status") status: string, - @Req() request: Request - ) { - return this.service.searchRole( - limit, - roleId, - title, - parentId, - status, - request - ); - } -} diff --git a/src/role/role.module.ts b/src/role/role.module.ts deleted file mode 100644 index 1d14c10f..00000000 --- a/src/role/role.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { Module } from "@nestjs/common"; -import { RoleService } from "src/adapters/hasura/role.adapter"; -import { RoleController } from "./role.controller"; - -@Module({ - imports: [HttpModule], - controllers: [RoleController], - providers: [RoleService], -}) -export class RoleModule {} From 8d0b90e275caebccdf7f70caff4b13042bc9b69a Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 5 Apr 2024 19:17:32 +0530 Subject: [PATCH 184/408] add --- src/adapters/hasura/role.adapter.ts | 2 +- src/adapters/postgres/rbac-adapter.ts | 134 ++++++++++++++++++++++++++ src/adapters/rbacservicelocator.ts | 12 +++ src/rbac/rbac.controller.ts | 7 +- src/rbac/rbac.module.ts | 9 +- src/rbac/rbacadapter.ts | 25 +++++ 6 files changed, 184 insertions(+), 5 deletions(-) create mode 100644 src/adapters/postgres/rbac-adapter.ts create mode 100644 src/adapters/rbacservicelocator.ts create mode 100644 src/rbac/rbacadapter.ts diff --git a/src/adapters/hasura/role.adapter.ts b/src/adapters/hasura/role.adapter.ts index 0c4a2b21..4488755a 100644 --- a/src/adapters/hasura/role.adapter.ts +++ b/src/adapters/hasura/role.adapter.ts @@ -3,7 +3,7 @@ import { Injectable } from "@nestjs/common"; import { SuccessResponse } from "src/success-response"; import { RoleDto } from "src/role/dto/role.dto"; @Injectable() -export class RoleService { +export class HasuraRoleService { constructor(private httpService: HttpService) {} public async getRole(title: string, request: any) { diff --git a/src/adapters/postgres/rbac-adapter.ts b/src/adapters/postgres/rbac-adapter.ts new file mode 100644 index 00000000..bb7c0ee5 --- /dev/null +++ b/src/adapters/postgres/rbac-adapter.ts @@ -0,0 +1,134 @@ +import { HttpStatus, Injectable } from '@nestjs/common'; +import { Role } from "../../rbac/entities/rbac.entity"; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { RoleDto } from "../../rbac/dto/rbac.dto"; +import { SuccessResponse } from '../../../src/success-response'; +import { ErrorResponseTypeOrm } from '../../../src/error-response-typeorm'; +import { RoleSearchDto } from "../../rbac/dto/rbac-search.dto"; + +@Injectable() +export class PostgresRbacService { + constructor( + @InjectRepository(Role) + private roleRepository: Repository + ) { } + public async createRole(request: any, roleDto: RoleDto) { + try { + const response = await this.roleRepository.save(roleDto); + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: response, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async getRole(roleId: string, request: any) { + + try { + const [results, totalCount] = await this.roleRepository.findAndCount({ + where: { roleId } + }) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + totalCount, + data: results, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + + + + } + + public async updateRole(roleId: string, request: any, roleDto: RoleDto) { + try { + const response = await this.roleRepository.update(roleId,roleDto) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) { + try { + + let { limit, page, filters } = roleSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + + const [results, totalCount] = await this.roleRepository.findAndCount({ + where: whereClause, + skip: offset, + take: parseInt(limit), + }); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + totalCount, + data: results, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async deleteRole(roleId: string) { + try { + let response = await this.roleRepository.delete(roleId) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Role deleted successfully.', + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } +} + + diff --git a/src/adapters/rbacservicelocator.ts b/src/adapters/rbacservicelocator.ts new file mode 100644 index 00000000..62e76433 --- /dev/null +++ b/src/adapters/rbacservicelocator.ts @@ -0,0 +1,12 @@ +import { RoleSearchDto } from "../rbac/dto/rbac-search.dto"; +import { RoleDto } from "../rbac/dto/rbac.dto"; + +export interface IServicelocatorRbac { + getRole( + roleId?: Record, + request?: any, + ); + updateRole(id?: string, request?: any, userDto?: any); + createRole(request: any, roleDto: RoleDto); + searchRole(tenantid, request: any, roleSearchDto: RoleSearchDto) +} diff --git a/src/rbac/rbac.controller.ts b/src/rbac/rbac.controller.ts index 514bdc04..2f5e10cb 100644 --- a/src/rbac/rbac.controller.ts +++ b/src/rbac/rbac.controller.ts @@ -36,13 +36,16 @@ import { RoleSearchDto } from "./dto/rbac-search.dto"; import { RoleService } from "./rbac.service"; import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { RbacAdapter } from "./rbacadapter"; @ApiTags("rbac") @Controller("rbac") @UseGuards(JwtAuthGuard) export class RoleController { - constructor(private readonly roleService: RoleService) { } + constructor(private readonly roleService: RoleService,private readonly rbacAdapter:RbacAdapter) { } + // constructor(private readonly cohortService: CohortService,private readonly cohortAdapter:CohortAdapter) {} + //Get role @Get("/:id") @@ -74,7 +77,7 @@ export class RoleController { @Body() roleDto: RoleDto, @Res() response: Response ) { - const result = await this.roleService.createRole(request, roleDto); + const result = await this.rbacAdapter.buildRbacAdapter().createRole(request, roleDto); return response.status(result.statusCode).json(result); } diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index 38de9a11..a73b28c6 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -6,12 +6,17 @@ import { Role } from "./entities/rbac.entity"; import { RoleService } from "./rbac.service"; import { TypeOrmModule } from "@nestjs/typeorm"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; +import { PostgresRbacService } from "src/adapters/postgres/rbac-adapter"; + @Module({ imports: [ TypeOrmModule.forFeature([Role]), - HttpModule + HttpModule, + PostgresModule + ], controllers: [RoleController], - providers: [RoleService], + providers: [RoleService,PostgresRbacService], }) export class RoleModule {} diff --git a/src/rbac/rbacadapter.ts b/src/rbac/rbacadapter.ts new file mode 100644 index 00000000..75b60664 --- /dev/null +++ b/src/rbac/rbacadapter.ts @@ -0,0 +1,25 @@ +import { Injectable } from "@nestjs/common"; +import { IServicelocatorRbac } from "../adapters/rbacservicelocator"; +import { HasuraRoleService } from "../adapters/hasura/role.adapter"; +import { PostgresRbacService } from "../adapters/postgres/rbac-adapter"; + + + + +@Injectable() +export class RbacAdapter { + constructor(private hasuraProvider: HasuraRoleService, + private postgresProvider:PostgresRbacService) {} + buildRbacAdapter(): IServicelocatorRbac { + let adapter: IServicelocatorRbac; + + switch (process.env.ADAPTERSOURCE) { + case "hasura": + adapter = this.hasuraProvider; + break; + case "postgres": + adapter = this.postgresProvider; + } + return adapter; + } +} From d765261a84fdbe3b897f75ddf23a1e61232a3e4b Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 8 Apr 2024 11:06:16 +0530 Subject: [PATCH 185/408] Task #216655 : Created Cohrot Details API with User and Cohort ID Support --- src/cohort/cohort.controller.ts | 61 +++++++---------- src/cohort/cohort.service.ts | 103 +++++++++++++++-------------- src/cohort/dto/query-params.dto.ts | 11 +++ 3 files changed, 88 insertions(+), 87 deletions(-) create mode 100644 src/cohort/dto/query-params.dto.ts diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index d7c3101b..02fc7003 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -24,6 +24,7 @@ import { UseGuards, ValidationPipe, UsePipes, + Query, } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -35,6 +36,7 @@ import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortService } from "./cohort.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") @Controller("cohort") @@ -80,34 +82,8 @@ export class CohortController { ); return response.status(result.statusCode).json(result); } - - @Get("cohortList/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async getCohortList( - @Headers() headers, - @Param("id") id: string, - @Req() request: Request, - @Res() response: Response - ) { - let tenantid = headers["tenantid"]; - const result = await this.cohortAdapter.buildCohortAdapter().getCohortList( - tenantid, - id, - request, - response - ); - return response.status(result.statusCode).json(result); - } - - @Get("cohortDetails/:id") + + @Get("cohortDetails?") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort details" }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -119,17 +95,30 @@ export class CohortController { }) public async getCohortDetails( @Headers() headers, - @Param("id") cohortId: string, + @Query() queryParams: QueryParamsDto, @Req() request: Request, @Res() response: Response ) { - let tenantid = headers["tenantid"]; - return this.cohortService.getCohortsDetails( - tenantid, - cohortId, - request, - response - ); + if(!Object.keys(queryParams).length){ + return response.status(400).json({ + message:"Please enter Query Params" + }) + } + queryParams.name = queryParams.name.toLocaleLowerCase(); + let data; + let tenantId = request.headers['tenantId'] + if (queryParams?.name=== 'user') { + data=queryParams + return this.cohortService.getCohortsDetails(data,request,response) + } else if (queryParams?.name === 'cohort') { + data=queryParams + return this.cohortService.getCohortsDetails(data,request,response) + } else { + return response.status(400).json({ + message:"Invaid Parameters.", + data:`Valid format should be name="cohortoruser" and id=value` + }) + } } // search diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index ecbec297..717f67ad 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -37,72 +37,70 @@ export class CohortService { private fieldsService: FieldsService, ) { } - public async getCohortsDetails(tenantId: string, - cohortId: string, + public async getCohortsDetails(userData, request: any, response: any){ - const apiId = "api.concept.cohortDetails"; - let cohortName = await this.cohortRepository.findOne({ - where:{cohortId} - }) - // let result = { - // cohortData: [], - // }; - let cohortData = { - cohortId: cohortId, - name:cohortName.name, - parentId:cohortName.parentId, - customField:{} - }; - const getDetails = await this.getCohortListDetails(cohortId); - cohortData.customField=getDetails - // result.cohortData.push(cohortData); - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - cohortData, - "OK" - ) - ); - } - - public async getCohortList( - tenantId: string, - userId: string, - request: any, - response: any - ) { - const apiId = "api.concept.editminiScreeningAnswer"; + let apiId = 'api.concept.getCohortDetails' try { - let findCohortId = await this.findCohortName(userId); + if(userData.name==='user'){ + let findCohortId = await this.findCohortName(userData?.id); let result = { cohortData: [], }; - for (let data of findCohortId) { let cohortData = { - cohortId: data.cohortId, + cohortId: data?.cohortId, name:data.name, - parentId:data.parentId, + parentId:data?.parentId, customField:{} }; - const getDetails = await this.getCohortListDetails(data.cohortId); + const getDetails = await this.getCohortListDetails(data?.cohortId); cohortData.customField=getDetails result.cohortData.push(cohortData); } - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: result, - }); + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + result, + "OK" + ) + ); + }else{ + let cohortName = await this.cohortRepository.findOne({ + where:{cohortId:userData?.id}, + select:['name','parentId'] + }) + let cohortData = { + cohortId: userData?.id, + name:cohortName?.name, + parentId:cohortName?.parentId, + customField:{} + }; + const getDetails = await this.getCohortListDetails(userData?.id); + cohortData.customField=getDetails + return response + .status(HttpStatus.OK) + .send( + APIResponse.success( + apiId, + cohortData, + "OK" + ) + ); + } } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); + return response + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .send( + APIResponse.error( + apiId, + "Something went wrong", + `Failure Retrieving Cohort Member. Error is: ${error}`, + "INTERNAL_SERVER_ERROR" + ) + ); } } @@ -112,6 +110,9 @@ export class CohortService { LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" WHERE cm."userId"=$1 AND c.status=true`; let result = await this.cohortMembersRepository.query(query, [userId]); + // if(!result.length){ + // return null; + // } return result; } diff --git a/src/cohort/dto/query-params.dto.ts b/src/cohort/dto/query-params.dto.ts new file mode 100644 index 00000000..072d97ba --- /dev/null +++ b/src/cohort/dto/query-params.dto.ts @@ -0,0 +1,11 @@ +import { IsNotEmpty, IsString, IsInt } from 'class-validator'; + +export class QueryParamsDto { + @IsNotEmpty() + @IsString() + name: string; + + @IsNotEmpty() + @IsString() + id: string; +} \ No newline at end of file From 23f825bbcd2c2524477c798634a37751a798b36f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 8 Apr 2024 11:40:05 +0530 Subject: [PATCH 186/408] add --- src/adapters/hasura/rbac.adapter.ts | 217 ++++++++++++++++++++++++++ src/adapters/hasura/role.adapter.ts | 2 +- src/adapters/postgres/rbac-adapter.ts | 4 +- src/adapters/rbacservicelocator.ts | 2 +- src/app.module.ts | 4 +- src/rbac/rbac.module.ts | 9 +- src/rbac/rbacadapter.ts | 2 +- 7 files changed, 230 insertions(+), 10 deletions(-) create mode 100644 src/adapters/hasura/rbac.adapter.ts diff --git a/src/adapters/hasura/rbac.adapter.ts b/src/adapters/hasura/rbac.adapter.ts new file mode 100644 index 00000000..23df00e6 --- /dev/null +++ b/src/adapters/hasura/rbac.adapter.ts @@ -0,0 +1,217 @@ +import { HttpService } from "@nestjs/axios"; +import { Injectable } from "@nestjs/common"; +import { SuccessResponse } from "src/success-response"; +import { RoleDto } from "../../rbac/dto/rbac.dto"; +import { RoleSearchDto } from "../../rbac/dto/rbac-search.dto"; + +@Injectable() +export class HasuraRoleService { + constructor(private httpService: HttpService) {} + + public async getRole(roleId: string, request: any) {} + public async createRole(request: any, roleDto: RoleDto) {} + public async deleteRole(roleId: string) {} + public async updateRole(roleId: string, request: any, roleDto: RoleDto) {} + public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) {} + // public async getRole(title: string, request: any) { + // var axios = require("axios"); + // var data = { + // query: `query getRole($title: String) { + // role(where: {title: {_eq: $title}}) { + // title + // roleId, + // status, + // parentId + // created_at + // updated_at + // } + // }`, + // variables: { title: title }, + // }; + + // var config = { + // method: "post", + // url: process.env.REGISTRYHASURA, + // headers: { + // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + // "Content-Type": "application/json", + // }, + // data: data, + // }; + + // const response = await axios(config); + + // let result = response.data.data.role; + // const roleData = await this.mappedResponse(result); + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: roleData, + // }); + // } + + // public async createRole(request: any, roleDto: RoleDto) { + // var axios = require("axios"); + // var data = { + // query: `mutation createRole($title: String, $parentId: String, $status: String) { + // insert_role_one(object: {title: $title, parentId: $parentId, status: $status}) { + // roleId + // } + // }`, + // variables: { + // title: roleDto.title, + // parentId: roleDto.parentId, + // status: roleDto.status, + // }, + // }; + + // var config = { + // method: "post", + // url: process.env.REGISTRYHASURA, + // headers: { + // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + // "Content-Type": "application/json", + // }, + // data: data, + // }; + + // const response = await axios(config); + + // const result = response.data.data.insert_role_one; + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } + + // public async updateRole(roleId: string, request: any, roleDto: RoleDto) { + // var axios = require("axios"); + + // const updateRoleData = { + // title: roleDto.title, + // parentId: roleDto.parentId, + // status: roleDto.status, + // }; + + // let query = ""; + // Object.keys(updateRoleData).forEach((e) => { + // if (updateRoleData[e] && updateRoleData[e] != "") { + // query += `${e}:${updateRoleData[e]} `; + // } + // }); + + // var data = { + // query: `mutation updateRole($roleId: uuid, $title: String, $parentId: String, $status: String) { + // update_role(where: {roleId: {_eq: $roleId}}, _set: {${query}}) { + // affected_rows + // } + // }`, + // variables: { + // roleId: roleId, + // }, + // }; + + // var config = { + // method: "post", + // url: process.env.REGISTRYHASURA, + // headers: { + // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + // "Content-Type": "application/json", + // }, + // data: data, + // }; + + // const response = await axios(config); + // const result = response.data.data; + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } + +// public async searchRole( +// limit: string, +// roleId: string, +// title: string, +// parentId: string, +// status: string, +// request: any +// ) { +// var axios = require("axios"); + +// const searchData = { +// roleId, +// title, +// parentId, +// status, +// }; + +// let query = ""; +// Object.keys(searchData).forEach((e) => { +// if (searchData[e] && searchData[e] != "") { +// query += `${e}:{_eq:"${searchData[e]}"}`; +// } +// }); +// var data = { +// query: `query searchRole($limit:Int) { +// role_aggregate { +// aggregate { +// count +// } +// } +// role(limit: $limit, where: {${query}}) { +// title +// roleId, +// status, +// parentId +// created_at +// updated_at +// } +// }`, +// variables: { +// limit: parseInt(limit), +// }, +// }; + +// var config = { +// method: "post", +// url: process.env.REGISTRYHASURA, +// headers: { +// "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, +// "Content-Type": "application/json", +// }, +// data: data, +// }; + +// const response = await axios(config); + +// let result = response.data.data.role; +// const roleData = await this.mappedResponse(result); +// const count = response?.data?.data?.role_aggregate?.aggregate?.count; +// return new SuccessResponse({ +// statusCode: 200, +// message: "Ok.", +// totalCount: count, +// data: roleData, +// }); +// } + + // public async mappedResponse(result: any) { + // const roleResponse = result.map((item: any) => { + // const roleMapping = { + // id: item?.roleId ? `${item.roleId}` : "", + // roleId: item?.roleId ? `${item.roleId}` : "", + // title: item?.title ? `${item.title}` : "", + // parentId: item?.parentId ? `${item.parentId}` : "", + // status: item?.status ? `${item.status}` : "", + // createdAt: item?.created_at ? `${item.created_at}` : "", + // updatedAt: item?.updated_at ? `${item.updated_at}` : "", + // }; + // return new RoleDto(roleMapping); + // }); + + // return roleResponse; + // } +} diff --git a/src/adapters/hasura/role.adapter.ts b/src/adapters/hasura/role.adapter.ts index 4488755a..0c4a2b21 100644 --- a/src/adapters/hasura/role.adapter.ts +++ b/src/adapters/hasura/role.adapter.ts @@ -3,7 +3,7 @@ import { Injectable } from "@nestjs/common"; import { SuccessResponse } from "src/success-response"; import { RoleDto } from "src/role/dto/role.dto"; @Injectable() -export class HasuraRoleService { +export class RoleService { constructor(private httpService: HttpService) {} public async getRole(title: string, request: any) { diff --git a/src/adapters/postgres/rbac-adapter.ts b/src/adapters/postgres/rbac-adapter.ts index bb7c0ee5..f06281c7 100644 --- a/src/adapters/postgres/rbac-adapter.ts +++ b/src/adapters/postgres/rbac-adapter.ts @@ -3,8 +3,8 @@ import { Role } from "../../rbac/entities/rbac.entity"; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { RoleDto } from "../../rbac/dto/rbac.dto"; -import { SuccessResponse } from '../../../src/success-response'; -import { ErrorResponseTypeOrm } from '../../../src/error-response-typeorm'; +import { SuccessResponse } from 'src/success-response'; +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { RoleSearchDto } from "../../rbac/dto/rbac-search.dto"; @Injectable() diff --git a/src/adapters/rbacservicelocator.ts b/src/adapters/rbacservicelocator.ts index 62e76433..2128914b 100644 --- a/src/adapters/rbacservicelocator.ts +++ b/src/adapters/rbacservicelocator.ts @@ -3,7 +3,7 @@ import { RoleDto } from "../rbac/dto/rbac.dto"; export interface IServicelocatorRbac { getRole( - roleId?: Record, + roleId?: string, request?: any, ); updateRole(id?: string, request?: any, userDto?: any); diff --git a/src/app.module.ts b/src/app.module.ts index f39f6df2..71bf1b90 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -19,7 +19,7 @@ import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module" import { CourseModule } from "./course/course.module"; import { CourseTrackingModule } from "./courseTracking/courseTracking.module"; import { AnnouncementsModule } from "./announcements/announcements.module"; -import { RoleModule } from "./rbac/rbac.module"; +// import { RoleModule } from "./role/rbac.module"; import { WorkHistoryModule } from "./workHistory/workHistory.module"; import { CohortModule } from "./cohort/cohort.module"; import { CohortMembersModule } from "./cohortMembers/cohortMembers.module"; @@ -40,7 +40,7 @@ import { SwaggerModule } from "@nestjs/swagger"; }), SchoolModule, UserModule, - RoleModule, + // RoleModule, AttendanceModule, HolidayModule, ConfigurationModule, diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index a73b28c6..69f050ce 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -8,15 +8,18 @@ import { TypeOrmModule } from "@nestjs/typeorm"; import { PostgresModule } from "src/adapters/postgres/potsgres-module"; import { PostgresRbacService } from "src/adapters/postgres/rbac-adapter"; +// import { RbacAdapter } from "./rbacadapter"; +import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { HasuraRoleService } from "src/adapters/hasura/rbac.adapter"; @Module({ imports: [ TypeOrmModule.forFeature([Role]), HttpModule, - PostgresModule - + PostgresModule, + HasuraModule ], controllers: [RoleController], - providers: [RoleService,PostgresRbacService], + providers: [RoleService,PostgresRbacService,HasuraRoleService], }) export class RoleModule {} diff --git a/src/rbac/rbacadapter.ts b/src/rbac/rbacadapter.ts index 75b60664..58c7fd7f 100644 --- a/src/rbac/rbacadapter.ts +++ b/src/rbac/rbacadapter.ts @@ -1,6 +1,6 @@ import { Injectable } from "@nestjs/common"; import { IServicelocatorRbac } from "../adapters/rbacservicelocator"; -import { HasuraRoleService } from "../adapters/hasura/role.adapter"; +import { HasuraRoleService } from "../adapters/hasura/rbac.adapter"; import { PostgresRbacService } from "../adapters/postgres/rbac-adapter"; From 623209e9e5bc75891bff8f2d01faf3359c521e48 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 8 Apr 2024 13:19:57 +0530 Subject: [PATCH 187/408] rbac module minor changes --- src/adapters/hasura/rbac.adapter.ts | 203 ---------------------------- src/adapters/rbacservicelocator.ts | 3 +- src/rbac/rbac.controller.ts | 33 +---- src/rbac/rbac.module.ts | 3 - src/rbac/rbac.service.ts | 1 - src/rbac/rbacadapter.ts | 3 - 6 files changed, 9 insertions(+), 237 deletions(-) diff --git a/src/adapters/hasura/rbac.adapter.ts b/src/adapters/hasura/rbac.adapter.ts index 23df00e6..628183a0 100644 --- a/src/adapters/hasura/rbac.adapter.ts +++ b/src/adapters/hasura/rbac.adapter.ts @@ -1,217 +1,14 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; -import { SuccessResponse } from "src/success-response"; import { RoleDto } from "../../rbac/dto/rbac.dto"; import { RoleSearchDto } from "../../rbac/dto/rbac-search.dto"; @Injectable() export class HasuraRoleService { constructor(private httpService: HttpService) {} - public async getRole(roleId: string, request: any) {} public async createRole(request: any, roleDto: RoleDto) {} public async deleteRole(roleId: string) {} public async updateRole(roleId: string, request: any, roleDto: RoleDto) {} public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) {} - // public async getRole(title: string, request: any) { - // var axios = require("axios"); - // var data = { - // query: `query getRole($title: String) { - // role(where: {title: {_eq: $title}}) { - // title - // roleId, - // status, - // parentId - // created_at - // updated_at - // } - // }`, - // variables: { title: title }, - // }; - - // var config = { - // method: "post", - // url: process.env.REGISTRYHASURA, - // headers: { - // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - // "Content-Type": "application/json", - // }, - // data: data, - // }; - - // const response = await axios(config); - - // let result = response.data.data.role; - // const roleData = await this.mappedResponse(result); - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: roleData, - // }); - // } - - // public async createRole(request: any, roleDto: RoleDto) { - // var axios = require("axios"); - // var data = { - // query: `mutation createRole($title: String, $parentId: String, $status: String) { - // insert_role_one(object: {title: $title, parentId: $parentId, status: $status}) { - // roleId - // } - // }`, - // variables: { - // title: roleDto.title, - // parentId: roleDto.parentId, - // status: roleDto.status, - // }, - // }; - - // var config = { - // method: "post", - // url: process.env.REGISTRYHASURA, - // headers: { - // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - // "Content-Type": "application/json", - // }, - // data: data, - // }; - - // const response = await axios(config); - - // const result = response.data.data.insert_role_one; - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } - - // public async updateRole(roleId: string, request: any, roleDto: RoleDto) { - // var axios = require("axios"); - - // const updateRoleData = { - // title: roleDto.title, - // parentId: roleDto.parentId, - // status: roleDto.status, - // }; - - // let query = ""; - // Object.keys(updateRoleData).forEach((e) => { - // if (updateRoleData[e] && updateRoleData[e] != "") { - // query += `${e}:${updateRoleData[e]} `; - // } - // }); - - // var data = { - // query: `mutation updateRole($roleId: uuid, $title: String, $parentId: String, $status: String) { - // update_role(where: {roleId: {_eq: $roleId}}, _set: {${query}}) { - // affected_rows - // } - // }`, - // variables: { - // roleId: roleId, - // }, - // }; - - // var config = { - // method: "post", - // url: process.env.REGISTRYHASURA, - // headers: { - // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - // "Content-Type": "application/json", - // }, - // data: data, - // }; - - // const response = await axios(config); - // const result = response.data.data; - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } - -// public async searchRole( -// limit: string, -// roleId: string, -// title: string, -// parentId: string, -// status: string, -// request: any -// ) { -// var axios = require("axios"); - -// const searchData = { -// roleId, -// title, -// parentId, -// status, -// }; - -// let query = ""; -// Object.keys(searchData).forEach((e) => { -// if (searchData[e] && searchData[e] != "") { -// query += `${e}:{_eq:"${searchData[e]}"}`; -// } -// }); -// var data = { -// query: `query searchRole($limit:Int) { -// role_aggregate { -// aggregate { -// count -// } -// } -// role(limit: $limit, where: {${query}}) { -// title -// roleId, -// status, -// parentId -// created_at -// updated_at -// } -// }`, -// variables: { -// limit: parseInt(limit), -// }, -// }; - -// var config = { -// method: "post", -// url: process.env.REGISTRYHASURA, -// headers: { -// "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, -// "Content-Type": "application/json", -// }, -// data: data, -// }; - -// const response = await axios(config); - -// let result = response.data.data.role; -// const roleData = await this.mappedResponse(result); -// const count = response?.data?.data?.role_aggregate?.aggregate?.count; -// return new SuccessResponse({ -// statusCode: 200, -// message: "Ok.", -// totalCount: count, -// data: roleData, -// }); -// } - - // public async mappedResponse(result: any) { - // const roleResponse = result.map((item: any) => { - // const roleMapping = { - // id: item?.roleId ? `${item.roleId}` : "", - // roleId: item?.roleId ? `${item.roleId}` : "", - // title: item?.title ? `${item.title}` : "", - // parentId: item?.parentId ? `${item.parentId}` : "", - // status: item?.status ? `${item.status}` : "", - // createdAt: item?.created_at ? `${item.created_at}` : "", - // updatedAt: item?.updated_at ? `${item.updated_at}` : "", - // }; - // return new RoleDto(roleMapping); - // }); - - // return roleResponse; - // } } diff --git a/src/adapters/rbacservicelocator.ts b/src/adapters/rbacservicelocator.ts index 2128914b..192d9dfb 100644 --- a/src/adapters/rbacservicelocator.ts +++ b/src/adapters/rbacservicelocator.ts @@ -8,5 +8,6 @@ export interface IServicelocatorRbac { ); updateRole(id?: string, request?: any, userDto?: any); createRole(request: any, roleDto: RoleDto); - searchRole(tenantid, request: any, roleSearchDto: RoleSearchDto) + searchRole(tenantid, request: any, roleSearchDto: RoleSearchDto); + deleteRole(roleId); } diff --git a/src/rbac/rbac.controller.ts b/src/rbac/rbac.controller.ts index 2f5e10cb..6fe46100 100644 --- a/src/rbac/rbac.controller.ts +++ b/src/rbac/rbac.controller.ts @@ -5,11 +5,8 @@ import { Body, Put, Param, - UseInterceptors, - ClassSerializerInterceptor, SerializeOptions, Req, - Query, UsePipes, ValidationPipe, Res, @@ -24,15 +21,11 @@ import { ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, - ApiQuery, - ApiExcludeController, - ApiConsumes, ApiHeader, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { RoleDto } from "./dto/rbac.dto"; import { RoleSearchDto } from "./dto/rbac-search.dto"; -// import { RoleService } from "src/adapters/hasura/role.adapter"; import { RoleService } from "./rbac.service"; import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @@ -44,14 +37,11 @@ import { RbacAdapter } from "./rbacadapter"; @UseGuards(JwtAuthGuard) export class RoleController { constructor(private readonly roleService: RoleService,private readonly rbacAdapter:RbacAdapter) { } - // constructor(private readonly cohortService: CohortService,private readonly cohortAdapter:CohortAdapter) {} - //Get role @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Role detail." }) + @ApiOkResponse({ description: "Role Detail." }) @ApiHeader({ name: "tenantid" }) @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({strategy: "excludeAll",}) @@ -60,7 +50,7 @@ export class RoleController { @Req() request: Request, @Res() response: Response ) { - const result = await this.roleService.getRole(roleId, request); + const result = await this.rbacAdapter.buildRbacAdapter().getRole(roleId, request); return response.status(result.statusCode).json(result); } @@ -71,7 +61,6 @@ export class RoleController { @ApiBody({ type: RoleDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ name: "tenantid" }) - @UseInterceptors(ClassSerializerInterceptor) public async createRole( @Req() request: Request, @Body() roleDto: RoleDto, @@ -88,27 +77,25 @@ export class RoleController { @ApiBody({ type: RoleDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ name: "tenantid", }) - @UseInterceptors(ClassSerializerInterceptor) public async updateRole( @Param("id") roleId: string, @Req() request: Request, @Body() roleDto: RoleDto, @Res() response: Response ) { - const result = await this.roleService.updateRole(roleId, request, roleDto); + const result = await this.rbacAdapter.buildRbacAdapter().updateRole(roleId, request, roleDto); return response.status(result.statusCode).json(result); } // search Role @Post("/search") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Role list." }) + @ApiCreatedResponse({ description: "Role List." }) @ApiBody({ type: RoleSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", }) @ApiHeader({ name: "tenantid" }) - @UseInterceptors(ClassSerializerInterceptor) public async searchRole( @Headers() headers, @Req() request: Request, @@ -116,26 +103,20 @@ export class RoleController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.roleService.searchRole( - tenantid, - request, - roleSearchDto - ); + const result = await this.rbacAdapter.buildRbacAdapter().searchRole(tenantid,request,roleSearchDto); return response.status(result.statusCode).json(result); } - //delete cohort + //delete role @Delete("/:id") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role deleted successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) public async deleteRole( @Param("id") roleId: string, @Res() response: Response ) { - const result = await this.roleService.deleteRole(roleId); + const result = await this.rbacAdapter.buildRbacAdapter().deleteRole(roleId); return response.status(result.statusCode).json(result); } - } diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index 69f050ce..149d0075 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -1,14 +1,11 @@ import { HttpModule } from "@nestjs/axios"; import { Module } from "@nestjs/common"; -// import { RoleService } from "src/adapters/hasura/role.adapter"; import { RoleController } from "./rbac.controller"; import { Role } from "./entities/rbac.entity"; import { RoleService } from "./rbac.service"; import { TypeOrmModule } from "@nestjs/typeorm"; - import { PostgresModule } from "src/adapters/postgres/potsgres-module"; import { PostgresRbacService } from "src/adapters/postgres/rbac-adapter"; -// import { RbacAdapter } from "./rbacadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { HasuraRoleService } from "src/adapters/hasura/rbac.adapter"; diff --git a/src/rbac/rbac.service.ts b/src/rbac/rbac.service.ts index dc14f292..2b959979 100644 --- a/src/rbac/rbac.service.ts +++ b/src/rbac/rbac.service.ts @@ -5,7 +5,6 @@ import { Repository } from 'typeorm'; import { RoleDto } from "./dto/rbac.dto"; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; -import { v4 as uuidv4 } from 'uuid'; import { RoleSearchDto } from "./dto/rbac-search.dto"; @Injectable() diff --git a/src/rbac/rbacadapter.ts b/src/rbac/rbacadapter.ts index 58c7fd7f..b2205f10 100644 --- a/src/rbac/rbacadapter.ts +++ b/src/rbac/rbacadapter.ts @@ -3,9 +3,6 @@ import { IServicelocatorRbac } from "../adapters/rbacservicelocator"; import { HasuraRoleService } from "../adapters/hasura/rbac.adapter"; import { PostgresRbacService } from "../adapters/postgres/rbac-adapter"; - - - @Injectable() export class RbacAdapter { constructor(private hasuraProvider: HasuraRoleService, From ebeead8a35cd53645bb8b85a4a598afafdc462d5 Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 8 Apr 2024 17:15:31 +0530 Subject: [PATCH 188/408] Task #216924: Added Parent Rbac Module and Role Child Module --- package-lock.json | 725 ++---------------- package.json | 2 +- src/adapters/hasura/rbac.adapter.ts | 4 +- .../{rbac-adapter.ts => rbac/role-adapter.ts} | 8 +- src/adapters/rbacservicelocator.ts | 4 +- src/app.module.ts | 10 +- src/rbac/rbac.module.ts | 19 +- src/rbac/rbac.service.spec.ts | 18 - src/rbac/rbac.service.ts | 134 ---- .../dto/role-search.dto.ts} | 0 .../{dto/rbac.dto.ts => role/dto/role.dto.ts} | 3 + src/rbac/{ => role}/entities/rbac.entity.ts | 0 .../role.controller.ts} | 22 +- src/rbac/role/role.module.ts | 22 + .../{rbacadapter.ts => role/roleadapter.ts} | 10 +- 15 files changed, 127 insertions(+), 854 deletions(-) rename src/adapters/postgres/{rbac-adapter.ts => rbac/role-adapter.ts} (94%) delete mode 100644 src/rbac/rbac.service.spec.ts delete mode 100644 src/rbac/rbac.service.ts rename src/rbac/{dto/rbac-search.dto.ts => role/dto/role-search.dto.ts} (100%) rename src/rbac/{dto/rbac.dto.ts => role/dto/role.dto.ts} (79%) rename src/rbac/{ => role}/entities/rbac.entity.ts (100%) rename src/rbac/{rbac.controller.ts => role/role.controller.ts} (82%) create mode 100644 src/rbac/role/role.module.ts rename src/rbac/{rbacadapter.ts => role/roleadapter.ts} (57%) diff --git a/package-lock.json b/package-lock.json index 969d06a4..05826c82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,13 @@ "dependencies": { "@nestjs/axios": "^0.0.7", "@nestjs/common": "^8.4.2", - "@nestjs/config": "^2.0.0", + "@nestjs/config": "^2.3.4", "@nestjs/core": "^8.0.0", "@nestjs/jwt": "^8.0.0", "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^8.0.0", "@nestjs/schedule": "^1.1.0", - "@nestjs/swagger": "^5.2.0", + "@nestjs/swagger": "^5.2.1", "@nestjs/typeorm": "^10.0.2", "axios": "^0.26.1", "cache-manager": "^3.6.1", @@ -29,13 +29,13 @@ "form-data": "^4.0.0", "graphql-tag": "^2.12.6", "jwt-decode": "^3.1.2", - "keycloak-connect": "^24.0.2", - "moment": "^2.29.3", + "moment": "^2.30.1", "multer": "^1.4.4", "node-cron": "^3.0.1", "node-schedule": "^2.1.0", "object-resolve-path": "^1.1.1", - "passport-keycloak-oauth2-oidc": "^1.0.5", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", @@ -1450,21 +1450,29 @@ } }, "node_modules/@nestjs/config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.0.0.tgz", - "integrity": "sha512-Hi1k/1S5ogsS5c0OtNm72thiLSngijOaLDFaGI5ZPxNGpF23lctPg6ox3pYIOhXVRX/u+eiUIp71gswH2k8YNw==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.3.4.tgz", + "integrity": "sha512-IGdSF+0F9MJO6dCRTEahdxPz4iVijjtolcFBxnY+2QYM3bXYQvAgzskGZi+WkAFJN/VzR3TEp60gN5sI74GxPA==", "dependencies": { - "dotenv": "16.0.0", - "dotenv-expand": "8.0.2", + "dotenv": "16.1.4", + "dotenv-expand": "10.0.0", "lodash": "4.17.21", - "uuid": "8.3.2" + "uuid": "9.0.0" }, "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0", + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", "reflect-metadata": "^0.1.13", "rxjs": "^6.0.0 || ^7.2.0" } }, + "node_modules/@nestjs/config/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@nestjs/core": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-8.4.1.tgz", @@ -1878,12 +1886,6 @@ "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" }, - "node_modules/@testim/chrome-version": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", - "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==", - "optional": true - }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1893,12 +1895,6 @@ "node": ">= 6" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "optional": true - }, "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", @@ -2244,15 +2240,6 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", @@ -2848,29 +2835,6 @@ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", "dev": true }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "optional": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/async": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", @@ -3005,23 +2969,6 @@ } ] }, - "node_modules/base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "optional": true, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3065,11 +3012,6 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, "node_modules/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", @@ -3124,11 +3066,6 @@ "node": ">=8" } }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -3203,15 +3140,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "optional": true, - "engines": { - "node": "*" - } - }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3369,39 +3297,6 @@ "node": ">=6.0" } }, - "node_modules/chromedriver": { - "version": "123.0.0", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-123.0.0.tgz", - "integrity": "sha512-OE9mpxXwbFy5LncAisqXm1aEzuLPtEMORIxyYIn9uT7N8rquJWyoip6w9Rytub3o2gnynW9+PFOTPVTldaYrtw==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "@testim/chrome-version": "^1.1.4", - "axios": "^1.6.7", - "compare-versions": "^6.1.0", - "extract-zip": "^2.0.1", - "proxy-agent": "^6.4.0", - "proxy-from-env": "^1.1.0", - "tcp-port-used": "^1.0.2" - }, - "bin": { - "chromedriver": "bin/chromedriver" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/chromedriver/node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "optional": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -3582,12 +3477,6 @@ "node": ">= 6" } }, - "node_modules/compare-versions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", - "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", - "optional": true - }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -3799,15 +3688,6 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "optional": true, - "engines": { - "node": ">= 14" - } - }, "node_modules/data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -3868,7 +3748,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "devOptional": true + "dev": true }, "node_modules/deepmerge": { "version": "4.2.2", @@ -3903,20 +3783,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "optional": true, - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4034,17 +3900,20 @@ } }, "node_modules/dotenv": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", - "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", + "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, "node_modules/dotenv-expand": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.2.tgz", - "integrity": "sha512-vKKAk+VOzAWOV/dPIeSYqhgC/TQY+6L6Ibkzfsr8xd1stdBsTuGu9asCOXgbYbBeS+f2Y6lqqEuw7riOA+xEUQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", "engines": { "node": ">=12" } @@ -4073,20 +3942,6 @@ "integrity": "sha512-b+DdcyOiZtLXHdgEG8lncYJdxbdJWJvclPNMg0eLUDcSOSO876WA/pYjdSblUTd7eJdIs4YdIxHWGazx7UPSJw==", "dev": true }, - "node_modules/elliptic": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", - "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -4116,7 +3971,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "devOptional": true, + "dev": true, "dependencies": { "once": "^1.4.0" } @@ -4175,7 +4030,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "devOptional": true, + "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -4390,7 +4245,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "devOptional": true, + "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4427,7 +4282,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=4.0" } @@ -4436,7 +4291,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.10.0" } @@ -4577,41 +4432,6 @@ "node": ">=4" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "optional": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4675,15 +4495,6 @@ "bser": "2.1.1" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "optional": true, - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -5084,35 +4895,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-uri": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", - "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", - "optional": true, - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4", - "fs-extra": "^11.2.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/get-uri/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -5189,16 +4971,7 @@ "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "devOptional": true - }, - "node_modules/graphql": { - "version": "16.8.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", - "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } + "dev": true }, "node_modules/graphql": { "version": "16.8.1", @@ -5264,15 +5037,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, "node_modules/hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -5290,16 +5054,6 @@ "node": "*" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -5526,34 +5280,6 @@ "node": ">= 0.10" } }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "optional": true, - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "optional": true - }, - "node_modules/ip-regex": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", - "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5699,26 +5425,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "optional": true - }, - "node_modules/is2": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", - "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", - "optional": true, - "dependencies": { - "deep-is": "^0.1.3", - "ip-regex": "^4.1.0", - "is-url": "^1.2.4" - }, - "engines": { - "node": ">=v0.10.0" - } - }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -6523,12 +6229,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "optional": true - }, "node_modules/jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", @@ -6650,7 +6350,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "devOptional": true, + "dev": true, "dependencies": { "universalify": "^2.0.0" }, @@ -6697,16 +6397,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/jwk-to-pem": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.5.tgz", - "integrity": "sha512-L90jwellhO8jRKYwbssU9ifaMVqajzj3fpRjDKcsDzrslU9syRbFqfkXtT4B89HYAap+xsxNcxgBSB09ig+a7A==", - "dependencies": { - "asn1.js": "^5.3.0", - "elliptic": "^6.5.4", - "safe-buffer": "^5.0.1" - } - }, "node_modules/jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -6721,20 +6411,6 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, - "node_modules/keycloak-connect": { - "version": "24.0.2", - "resolved": "https://registry.npmjs.org/keycloak-connect/-/keycloak-connect-24.0.2.tgz", - "integrity": "sha512-o4hrHAI5SxIVqyD1yY0uIhDM6y9hZyyb3pJc1yYakhfhn2WPqmOGeq8zELPS1XJpj+k/paS+65LW45en1HgebA==", - "dependencies": { - "jwk-to-pem": "^2.0.0" - }, - "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "chromedriver": "latest" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -7072,16 +6748,6 @@ "node": ">=6" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -7118,9 +6784,9 @@ } }, "node_modules/moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "engines": { "node": "*" } @@ -7207,15 +6873,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "optional": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/node-cron": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.1.tgz", @@ -7323,11 +6980,6 @@ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, - "node_modules/oauth": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", - "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==" - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7528,76 +7180,6 @@ "node": ">=6" } }, - "node_modules/pac-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", - "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", - "optional": true, - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "pac-resolver": "^7.0.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "optional": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "optional": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "optional": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "optional": true, - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -7658,7 +7240,6 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", - "peer": true, "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -7672,32 +7253,34 @@ "url": "https://github.com/sponsors/jaredhanson" } }, - "node_modules/passport-keycloak-oauth2-oidc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/passport-keycloak-oauth2-oidc/-/passport-keycloak-oauth2-oidc-1.0.5.tgz", - "integrity": "sha512-uvZGTFu7MozqOIocDdSlEImEQTaPd8g5Lwbt83SbFqOVvCS3PelKjMQOYoJ7ERL7ELOY6puV0BY+Pw8ExM4EYw==", + "node_modules/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "dependencies": { - "lodash": "^4.17.20", - "passport-oauth2": "^1.5.0" + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" } }, - "node_modules/passport-oauth2": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", - "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "node_modules/passport-jwt/node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dependencies": { - "base64url": "3.x.x", - "oauth": "0.10.x", - "passport-strategy": "1.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" }, "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" + "node": ">=12", + "npm": ">=6" } }, "node_modules/passport-strategy": { @@ -7779,14 +7362,7 @@ "node_modules/pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", - "peer": true - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "optional": true + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "node_modules/pg": { "version": "8.11.3", @@ -8034,78 +7610,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "optional": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "optional": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "optional": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "optional": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "optional": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "optional": true - }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -8116,7 +7620,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "devOptional": true, + "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -8447,10 +7951,9 @@ } }, "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8624,56 +8127,6 @@ "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", - "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", - "optional": true, - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "optional": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "optional": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/sorted-array-functions": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", @@ -9000,33 +8453,6 @@ "node": ">=6" } }, - "node_modules/tcp-port-used": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", - "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", - "optional": true, - "dependencies": { - "debug": "4.3.1", - "is2": "^2.0.6" - } - }, - "node_modules/tcp-port-used/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "optional": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/templates.js": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/templates.js/-/templates.js-0.3.11.tgz", @@ -9743,16 +9169,11 @@ "node": ">=4.2.0" } }, - "node_modules/uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" - }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "devOptional": true, + "dev": true, "engines": { "node": ">= 10.0.0" } @@ -10219,16 +9640,6 @@ "node": ">=10" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "optional": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 0ba47a92..181f6af2 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^8.0.0", "@nestjs/schedule": "^1.1.0", - "@nestjs/swagger": "^5.2.0", + "@nestjs/swagger": "^5.2.1", "@nestjs/typeorm": "^10.0.2", "axios": "^0.26.1", "cache-manager": "^3.6.1", diff --git a/src/adapters/hasura/rbac.adapter.ts b/src/adapters/hasura/rbac.adapter.ts index 628183a0..6aba0666 100644 --- a/src/adapters/hasura/rbac.adapter.ts +++ b/src/adapters/hasura/rbac.adapter.ts @@ -1,7 +1,7 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; -import { RoleDto } from "../../rbac/dto/rbac.dto"; -import { RoleSearchDto } from "../../rbac/dto/rbac-search.dto"; +import { RoleDto } from "../../rbac/role/dto/role.dto"; +import { RoleSearchDto } from "../../rbac/role/dto/role-search.dto"; @Injectable() export class HasuraRoleService { diff --git a/src/adapters/postgres/rbac-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts similarity index 94% rename from src/adapters/postgres/rbac-adapter.ts rename to src/adapters/postgres/rbac/role-adapter.ts index f06281c7..62ee33c0 100644 --- a/src/adapters/postgres/rbac-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -1,14 +1,14 @@ import { HttpStatus, Injectable } from '@nestjs/common'; -import { Role } from "../../rbac/entities/rbac.entity"; +import { Role } from "src/rbac/role/entities/rbac.entity" import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { RoleDto } from "../../rbac/dto/rbac.dto"; +import { RoleDto } from "../../../rbac/role/dto/role.dto"; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; -import { RoleSearchDto } from "../../rbac/dto/rbac-search.dto"; +import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; @Injectable() -export class PostgresRbacService { +export class PostgresRoleService { constructor( @InjectRepository(Role) private roleRepository: Repository diff --git a/src/adapters/rbacservicelocator.ts b/src/adapters/rbacservicelocator.ts index 192d9dfb..636d1f36 100644 --- a/src/adapters/rbacservicelocator.ts +++ b/src/adapters/rbacservicelocator.ts @@ -1,5 +1,5 @@ -import { RoleSearchDto } from "../rbac/dto/rbac-search.dto"; -import { RoleDto } from "../rbac/dto/rbac.dto"; +import { RoleSearchDto } from "../rbac/role/dto/role-search.dto"; +import { RoleDto } from "../rbac/role/dto/role.dto"; export interface IServicelocatorRbac { getRole( diff --git a/src/app.module.ts b/src/app.module.ts index 174c92e3..1dea9bf7 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -2,7 +2,7 @@ import { Module } from "@nestjs/common"; import { ConfigModule } from "@nestjs/config"; import { AppController } from "./app.controller"; import { AppService } from "./app.service"; -import { MulterModule } from "@nestjs/platform-express/multer"; +// import { MulterModule } from "@nestjs/platform-express/multer"; /* // Below modules not in use for Shiksha 2.0 import { StudentModule } from "./student/student.module"; @@ -28,13 +28,15 @@ import { CohortMembersModule } from "./cohortMembers/cohortMembers.module"; import { FieldsModule } from "./fields/fields.module"; import { AttendanceModule } from "./attendance/attendance.module"; import { UserModule } from "./user/user.module"; +import { RbacModule } from "./rbac/rbac.module"; @Module({ imports: [ + RbacModule, ConfigModule.forRoot({ isGlobal: true }), - MulterModule.register({ - dest: "./uploads", - }), + // MulterModule.register({ + // dest: "./uploads", + // }), UserModule, AttendanceModule, CohortModule, diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index 149d0075..d4ed6eb5 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -1,22 +1,9 @@ -import { HttpModule } from "@nestjs/axios"; import { Module } from "@nestjs/common"; -import { RoleController } from "./rbac.controller"; -import { Role } from "./entities/rbac.entity"; -import { RoleService } from "./rbac.service"; -import { TypeOrmModule } from "@nestjs/typeorm"; -import { PostgresModule } from "src/adapters/postgres/potsgres-module"; -import { PostgresRbacService } from "src/adapters/postgres/rbac-adapter"; -import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { HasuraRoleService } from "src/adapters/hasura/rbac.adapter"; +import { RoleModule } from "./role/role.module"; @Module({ imports: [ - TypeOrmModule.forFeature([Role]), - HttpModule, - PostgresModule, - HasuraModule + RoleModule ], - controllers: [RoleController], - providers: [RoleService,PostgresRbacService,HasuraRoleService], }) -export class RoleModule {} +export class RbacModule {} diff --git a/src/rbac/rbac.service.spec.ts b/src/rbac/rbac.service.spec.ts deleted file mode 100644 index 22d86b42..00000000 --- a/src/rbac/rbac.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { RoleService } from './rbac.service'; - -describe('RoleService', () => { - let service: RoleService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [RoleService], - }).compile(); - - service = module.get(RoleService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/src/rbac/rbac.service.ts b/src/rbac/rbac.service.ts deleted file mode 100644 index 2b959979..00000000 --- a/src/rbac/rbac.service.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { HttpStatus, Injectable } from '@nestjs/common'; -import { Role } from "./entities/rbac.entity"; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { RoleDto } from "./dto/rbac.dto"; -import { SuccessResponse } from 'src/success-response'; -import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; -import { RoleSearchDto } from "./dto/rbac-search.dto"; - -@Injectable() -export class RoleService { - constructor( - @InjectRepository(Role) - private roleRepository: Repository - ) { } - public async createRole(request: any, roleDto: RoleDto) { - try { - const response = await this.roleRepository.save(roleDto); - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Ok.", - data: response, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } - - public async getRole(roleId: string, request: any) { - - try { - const [results, totalCount] = await this.roleRepository.findAndCount({ - where: { roleId } - }) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - totalCount, - data: results, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - - - - } - - public async updateRole(roleId: string, request: any, roleDto: RoleDto) { - try { - const response = await this.roleRepository.update(roleId,roleDto) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: { - rowCount: response.affected, - } - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } - - public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) { - try { - - let { limit, page, filters } = roleSearchDto; - - let offset = 0; - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - - if (limit.trim() === '') { - limit = '0'; - } - - const whereClause = {}; - if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } - - const [results, totalCount] = await this.roleRepository.findAndCount({ - where: whereClause, - skip: offset, - take: parseInt(limit), - }); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - totalCount, - data: results, - }); - - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } - - public async deleteRole(roleId: string) { - try { - let response = await this.roleRepository.delete(roleId) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Role deleted successfully.', - data: { - rowCount: response.affected, - } - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } -} - - diff --git a/src/rbac/dto/rbac-search.dto.ts b/src/rbac/role/dto/role-search.dto.ts similarity index 100% rename from src/rbac/dto/rbac-search.dto.ts rename to src/rbac/role/dto/role-search.dto.ts diff --git a/src/rbac/dto/rbac.dto.ts b/src/rbac/role/dto/role.dto.ts similarity index 79% rename from src/rbac/dto/rbac.dto.ts rename to src/rbac/role/dto/role.dto.ts index 703c467d..93d7950e 100644 --- a/src/rbac/dto/rbac.dto.ts +++ b/src/rbac/role/dto/role.dto.ts @@ -1,8 +1,10 @@ import { Expose } from "class-transformer"; import { ApiProperty } from "@nestjs/swagger"; +import {IsNotEmpty,IsString, IsUUID} from "class-validator" export class RoleDto { @Expose() + @IsUUID() roleId: string; @ApiProperty({ @@ -11,6 +13,7 @@ export class RoleDto { default: "", }) @Expose() + @IsNotEmpty() roleName: string; constructor(obj: any) { diff --git a/src/rbac/entities/rbac.entity.ts b/src/rbac/role/entities/rbac.entity.ts similarity index 100% rename from src/rbac/entities/rbac.entity.ts rename to src/rbac/role/entities/rbac.entity.ts diff --git a/src/rbac/rbac.controller.ts b/src/rbac/role/role.controller.ts similarity index 82% rename from src/rbac/rbac.controller.ts rename to src/rbac/role/role.controller.ts index 6fe46100..e4e15c4e 100644 --- a/src/rbac/rbac.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -24,19 +24,18 @@ import { ApiHeader, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; -import { RoleDto } from "./dto/rbac.dto"; -import { RoleSearchDto } from "./dto/rbac-search.dto"; -import { RoleService } from "./rbac.service"; +import { RoleDto } from "./dto/role.dto"; +import { RoleSearchDto } from "./dto/role-search.dto"; import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; -import { RbacAdapter } from "./rbacadapter"; +import { RoleAdapter } from "./roleadapter" @ApiTags("rbac") -@Controller("rbac") +@Controller("role") @UseGuards(JwtAuthGuard) export class RoleController { - constructor(private readonly roleService: RoleService,private readonly rbacAdapter:RbacAdapter) { } + constructor(private readonly roleAdapter:RoleAdapter) { } //Get role @Get("/:id") @@ -50,12 +49,13 @@ export class RoleController { @Req() request: Request, @Res() response: Response ) { - const result = await this.rbacAdapter.buildRbacAdapter().getRole(roleId, request); + const result = await this.roleAdapter.buildRbacAdapter().getRole(roleId, request); return response.status(result.statusCode).json(result); } //Create role @Post() + @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role has been created successfully." }) @ApiBody({ type: RoleDto }) @@ -66,7 +66,7 @@ export class RoleController { @Body() roleDto: RoleDto, @Res() response: Response ) { - const result = await this.rbacAdapter.buildRbacAdapter().createRole(request, roleDto); + const result = await this.roleAdapter.buildRbacAdapter().createRole(request, roleDto); return response.status(result.statusCode).json(result); } @@ -83,7 +83,7 @@ export class RoleController { @Body() roleDto: RoleDto, @Res() response: Response ) { - const result = await this.rbacAdapter.buildRbacAdapter().updateRole(roleId, request, roleDto); + const result = await this.roleAdapter.buildRbacAdapter().updateRole(roleId, request, roleDto); return response.status(result.statusCode).json(result); } @@ -103,7 +103,7 @@ export class RoleController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.rbacAdapter.buildRbacAdapter().searchRole(tenantid,request,roleSearchDto); + const result = await this.roleAdapter.buildRbacAdapter().searchRole(tenantid,request,roleSearchDto); return response.status(result.statusCode).json(result); } @@ -116,7 +116,7 @@ export class RoleController { @Param("id") roleId: string, @Res() response: Response ) { - const result = await this.rbacAdapter.buildRbacAdapter().deleteRole(roleId); + const result = await this.roleAdapter.buildRbacAdapter().deleteRole(roleId); return response.status(result.statusCode).json(result); } } diff --git a/src/rbac/role/role.module.ts b/src/rbac/role/role.module.ts new file mode 100644 index 00000000..c71eb5d6 --- /dev/null +++ b/src/rbac/role/role.module.ts @@ -0,0 +1,22 @@ +import {Module } from '@nestjs/common'; +import { RoleController } from './role.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Role } from './entities/rbac.entity'; +import { HasuraModule } from 'src/adapters/hasura/hasura.module'; +import { PostgresModule } from 'src/adapters/postgres/potsgres-module'; +import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; +import { HasuraRoleService } from 'src/adapters/hasura/rbac.adapter'; +import { HttpModule } from '@nestjs/axios'; +import { RoleAdapter } from './roleadapter'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Role]), + HttpModule, + PostgresModule, + HasuraModule + ], + controllers: [RoleController], + providers: [RoleAdapter,HasuraRoleService,PostgresRoleService], +}) +export class RoleModule {} diff --git a/src/rbac/rbacadapter.ts b/src/rbac/role/roleadapter.ts similarity index 57% rename from src/rbac/rbacadapter.ts rename to src/rbac/role/roleadapter.ts index b2205f10..767257b9 100644 --- a/src/rbac/rbacadapter.ts +++ b/src/rbac/role/roleadapter.ts @@ -1,12 +1,12 @@ import { Injectable } from "@nestjs/common"; -import { IServicelocatorRbac } from "../adapters/rbacservicelocator"; -import { HasuraRoleService } from "../adapters/hasura/rbac.adapter"; -import { PostgresRbacService } from "../adapters/postgres/rbac-adapter"; +import { IServicelocatorRbac } from "../../adapters/rbacservicelocator"; +import { HasuraRoleService } from "../../adapters/hasura/rbac.adapter"; +import { PostgresRoleService } from "../../adapters/postgres/rbac/role-adapter"; @Injectable() -export class RbacAdapter { +export class RoleAdapter { constructor(private hasuraProvider: HasuraRoleService, - private postgresProvider:PostgresRbacService) {} + private postgresProvider:PostgresRoleService) {} buildRbacAdapter(): IServicelocatorRbac { let adapter: IServicelocatorRbac; From 9178bebd425432150a809d816f4c0225252f36f4 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 8 Apr 2024 18:17:09 +0530 Subject: [PATCH 189/408] Fix[folder structure change for hasura service and addition of privilege module ] --- src/adapters/hasura/rbac/privilege.adapter.ts | 10 + .../{rbac.adapter.ts => rbac/role.adapter.ts} | 4 +- src/adapters/hasura/role.adapter.ts | 210 ------------------ .../postgres/rbac/privilege-adapter.ts | 15 ++ src/rbac/privilege/dto/privilege.dto.ts | 23 ++ .../privilege/dto/update-privilege.dto.ts | 4 + .../privilege/entities/privilege.entity.ts | 11 + src/rbac/privilege/privilege.controller.ts | 38 ++++ src/rbac/privilege/privilege.module.ts | 28 +++ src/rbac/privilege/privilegeadapter.ts | 22 ++ src/rbac/rbac.module.ts | 9 +- src/rbac/role/role.module.ts | 2 +- src/rbac/role/roleadapter.ts | 2 +- src/role/dto/role.dto.ts | 38 ---- 14 files changed, 162 insertions(+), 254 deletions(-) create mode 100644 src/adapters/hasura/rbac/privilege.adapter.ts rename src/adapters/hasura/{rbac.adapter.ts => rbac/role.adapter.ts} (79%) delete mode 100644 src/adapters/hasura/role.adapter.ts create mode 100644 src/adapters/postgres/rbac/privilege-adapter.ts create mode 100644 src/rbac/privilege/dto/privilege.dto.ts create mode 100644 src/rbac/privilege/dto/update-privilege.dto.ts create mode 100644 src/rbac/privilege/entities/privilege.entity.ts create mode 100644 src/rbac/privilege/privilege.controller.ts create mode 100644 src/rbac/privilege/privilege.module.ts create mode 100644 src/rbac/privilege/privilegeadapter.ts delete mode 100644 src/role/dto/role.dto.ts diff --git a/src/adapters/hasura/rbac/privilege.adapter.ts b/src/adapters/hasura/rbac/privilege.adapter.ts new file mode 100644 index 00000000..17597081 --- /dev/null +++ b/src/adapters/hasura/rbac/privilege.adapter.ts @@ -0,0 +1,10 @@ +import { HttpService } from "@nestjs/axios"; +import { Injectable } from "@nestjs/common"; +import { RoleDto } from "../../../rbac/role/dto/role.dto"; +import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; + +@Injectable() +export class HasuraPrivilegeService { + constructor(private httpService: HttpService) {} + +} diff --git a/src/adapters/hasura/rbac.adapter.ts b/src/adapters/hasura/rbac/role.adapter.ts similarity index 79% rename from src/adapters/hasura/rbac.adapter.ts rename to src/adapters/hasura/rbac/role.adapter.ts index 6aba0666..a3fffc6e 100644 --- a/src/adapters/hasura/rbac.adapter.ts +++ b/src/adapters/hasura/rbac/role.adapter.ts @@ -1,7 +1,7 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; -import { RoleDto } from "../../rbac/role/dto/role.dto"; -import { RoleSearchDto } from "../../rbac/role/dto/role-search.dto"; +import { RoleDto } from "../../../rbac/role/dto/role.dto"; +import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; @Injectable() export class HasuraRoleService { diff --git a/src/adapters/hasura/role.adapter.ts b/src/adapters/hasura/role.adapter.ts deleted file mode 100644 index 0c4a2b21..00000000 --- a/src/adapters/hasura/role.adapter.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable } from "@nestjs/common"; -import { SuccessResponse } from "src/success-response"; -import { RoleDto } from "src/role/dto/role.dto"; -@Injectable() -export class RoleService { - constructor(private httpService: HttpService) {} - - public async getRole(title: string, request: any) { - var axios = require("axios"); - var data = { - query: `query getRole($title: String) { - role(where: {title: {_eq: $title}}) { - title - roleId, - status, - parentId - created_at - updated_at - } - }`, - variables: { title: title }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.role; - const roleData = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: roleData, - }); - } - - public async createRole(request: any, roleDto: RoleDto) { - var axios = require("axios"); - var data = { - query: `mutation createRole($title: String, $parentId: String, $status: String) { - insert_role_one(object: {title: $title, parentId: $parentId, status: $status}) { - roleId - } - }`, - variables: { - title: roleDto.title, - parentId: roleDto.parentId, - status: roleDto.status, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_role_one; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateRole(roleId: string, request: any, roleDto: RoleDto) { - var axios = require("axios"); - - const updateRoleData = { - title: roleDto.title, - parentId: roleDto.parentId, - status: roleDto.status, - }; - - let query = ""; - Object.keys(updateRoleData).forEach((e) => { - if (updateRoleData[e] && updateRoleData[e] != "") { - query += `${e}:${updateRoleData[e]} `; - } - }); - - var data = { - query: `mutation updateRole($roleId: uuid, $title: String, $parentId: String, $status: String) { - update_role(where: {roleId: {_eq: $roleId}}, _set: {${query}}) { - affected_rows - } - }`, - variables: { - roleId: roleId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async searchRole( - limit: string, - roleId: string, - title: string, - parentId: string, - status: string, - request: any - ) { - var axios = require("axios"); - - const searchData = { - roleId, - title, - parentId, - status, - }; - - let query = ""; - Object.keys(searchData).forEach((e) => { - if (searchData[e] && searchData[e] != "") { - query += `${e}:{_eq:"${searchData[e]}"}`; - } - }); - var data = { - query: `query searchRole($limit:Int) { - role_aggregate { - aggregate { - count - } - } - role(limit: $limit, where: {${query}}) { - title - roleId, - status, - parentId - created_at - updated_at - } -}`, - variables: { - limit: parseInt(limit), - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.role; - const roleData = await this.mappedResponse(result); - const count = response?.data?.data?.role_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: roleData, - }); - } - - public async mappedResponse(result: any) { - const roleResponse = result.map((item: any) => { - const roleMapping = { - id: item?.roleId ? `${item.roleId}` : "", - roleId: item?.roleId ? `${item.roleId}` : "", - title: item?.title ? `${item.title}` : "", - parentId: item?.parentId ? `${item.parentId}` : "", - status: item?.status ? `${item.status}` : "", - createdAt: item?.created_at ? `${item.created_at}` : "", - updatedAt: item?.updated_at ? `${item.updated_at}` : "", - }; - return new RoleDto(roleMapping); - }); - - return roleResponse; - } -} diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts new file mode 100644 index 00000000..464f30da --- /dev/null +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -0,0 +1,15 @@ +import { HttpStatus, Injectable } from '@nestjs/common'; +import { Role } from "src/rbac/role/entities/rbac.entity" +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { RoleDto } from "../../../rbac/role/dto/role.dto"; +import { SuccessResponse } from 'src/success-response'; +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; + +@Injectable() +export class PostgresPrivilegeService { + +} + + diff --git a/src/rbac/privilege/dto/privilege.dto.ts b/src/rbac/privilege/dto/privilege.dto.ts new file mode 100644 index 00000000..13615ab9 --- /dev/null +++ b/src/rbac/privilege/dto/privilege.dto.ts @@ -0,0 +1,23 @@ +// export class CreatePrivilegeDto {} +import { Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; +import {IsNotEmpty,IsString, IsUUID} from "class-validator" + +export class PrivilegeDto { + @Expose() + @IsUUID() + privilegeId: string; + + @ApiProperty({ + type: String, + description: "Privilege title", + default: "", + }) + @Expose() + @IsNotEmpty() + privilegeName: string; + + constructor(obj: any) { + Object.assign(this, obj); + } +} diff --git a/src/rbac/privilege/dto/update-privilege.dto.ts b/src/rbac/privilege/dto/update-privilege.dto.ts new file mode 100644 index 00000000..7aff7bd6 --- /dev/null +++ b/src/rbac/privilege/dto/update-privilege.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/mapped-types'; +import { PrivilegeDto } from './privilege.dto'; + +export class UpdatePrivilegeDto extends PartialType(PrivilegeDto) {} diff --git a/src/rbac/privilege/entities/privilege.entity.ts b/src/rbac/privilege/entities/privilege.entity.ts new file mode 100644 index 00000000..592d88c6 --- /dev/null +++ b/src/rbac/privilege/entities/privilege.entity.ts @@ -0,0 +1,11 @@ +// export class Privilege {} +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + +@Entity({ name: "Privilege" }) +export class Privilege { + @PrimaryGeneratedColumn('uuid') + privilegeId: string; + + @Column() + privilegeName: string; +} diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts new file mode 100644 index 00000000..19660da1 --- /dev/null +++ b/src/rbac/privilege/privilege.controller.ts @@ -0,0 +1,38 @@ +import { PrivilegeDto } from './dto/privilege.dto'; +import { UpdatePrivilegeDto } from './dto/update-privilege.dto'; +import { + Controller, + Get, + Post, + Body, + Put, + Param, + SerializeOptions, + Req, + UsePipes, + ValidationPipe, + Res, + Headers, + Delete, + UseGuards, +} from "@nestjs/common"; +import { + ApiTags, + ApiBody, + ApiOkResponse, + ApiForbiddenResponse, + ApiCreatedResponse, + ApiBasicAuth, + ApiHeader, +} from "@nestjs/swagger"; +import { Request } from "@nestjs/common"; +import { Response, response } from "express"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { PrivilegeAdapter } from './privilegeadapter'; + +@Controller('privilege') +export class PrivilegeController { + constructor(private readonly privilegeAdapter: PrivilegeAdapter) {} + + +} diff --git a/src/rbac/privilege/privilege.module.ts b/src/rbac/privilege/privilege.module.ts new file mode 100644 index 00000000..57f848ed --- /dev/null +++ b/src/rbac/privilege/privilege.module.ts @@ -0,0 +1,28 @@ +import { Module } from '@nestjs/common'; +import { PrivilegeController } from './privilege.controller'; +import { Privilege } from './entities/privilege.entity'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { HttpModule } from '@nestjs/axios'; +import { PostgresModule } from 'src/adapters/postgres/potsgres-module'; +import { HasuraModule } from 'src/adapters/hasura/hasura.module'; +import { PrivilegeAdapter } from './privilegeadapter'; +import { HasuraPrivilegeService } from 'src/adapters/hasura/rbac/privilege.adapter'; +import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; +import { PostgresPrivilegeService } from 'src/adapters/postgres/rbac/privilege-adapter'; +import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; +import { Role } from '../role/entities/rbac.entity'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Privilege,Role]), + HttpModule, + PostgresModule, + HasuraModule + ], + controllers: [PrivilegeController], + providers: [PrivilegeAdapter,HasuraPrivilegeService,PostgresPrivilegeService,HasuraRoleService,PostgresRoleService] +}) +export class PrivilegeModule {} + + + diff --git a/src/rbac/privilege/privilegeadapter.ts b/src/rbac/privilege/privilegeadapter.ts new file mode 100644 index 00000000..873074ae --- /dev/null +++ b/src/rbac/privilege/privilegeadapter.ts @@ -0,0 +1,22 @@ +import { Injectable } from "@nestjs/common"; +import { IServicelocatorRbac } from "../../adapters/rbacservicelocator"; +import { HasuraRoleService } from "../../adapters/hasura/rbac/role.adapter"; +import { PostgresRoleService } from "../../adapters/postgres/rbac/role-adapter"; + +@Injectable() +export class PrivilegeAdapter { + constructor(private hasuraProvider: HasuraRoleService, + private postgresProvider:PostgresRoleService) {} + buildRbacAdapter(): IServicelocatorRbac { + let adapter: IServicelocatorRbac; + + switch (process.env.ADAPTERSOURCE) { + case "hasura": + adapter = this.hasuraProvider; + break; + case "postgres": + adapter = this.postgresProvider; + } + return adapter; + } +} diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index d4ed6eb5..d86c975b 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -1,9 +1,14 @@ import { Module } from "@nestjs/common"; import { RoleModule } from "./role/role.module"; +import { PrivilegeModule } from './privilege/privilege.module'; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { Privilege } from "./privilege/entities/privilege.entity"; +import { Role } from "./role/entities/rbac.entity"; @Module({ - imports: [ - RoleModule + imports: [ + RoleModule, + PrivilegeModule ], }) export class RbacModule {} diff --git a/src/rbac/role/role.module.ts b/src/rbac/role/role.module.ts index c71eb5d6..63ed2952 100644 --- a/src/rbac/role/role.module.ts +++ b/src/rbac/role/role.module.ts @@ -5,7 +5,7 @@ import { Role } from './entities/rbac.entity'; import { HasuraModule } from 'src/adapters/hasura/hasura.module'; import { PostgresModule } from 'src/adapters/postgres/potsgres-module'; import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; -import { HasuraRoleService } from 'src/adapters/hasura/rbac.adapter'; +import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; import { HttpModule } from '@nestjs/axios'; import { RoleAdapter } from './roleadapter'; diff --git a/src/rbac/role/roleadapter.ts b/src/rbac/role/roleadapter.ts index 767257b9..6275db0a 100644 --- a/src/rbac/role/roleadapter.ts +++ b/src/rbac/role/roleadapter.ts @@ -1,6 +1,6 @@ import { Injectable } from "@nestjs/common"; import { IServicelocatorRbac } from "../../adapters/rbacservicelocator"; -import { HasuraRoleService } from "../../adapters/hasura/rbac.adapter"; +import { HasuraRoleService } from "../../adapters/hasura/rbac/role.adapter"; import { PostgresRoleService } from "../../adapters/postgres/rbac/role-adapter"; @Injectable() diff --git a/src/role/dto/role.dto.ts b/src/role/dto/role.dto.ts deleted file mode 100644 index 1b5e7338..00000000 --- a/src/role/dto/role.dto.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class RoleDto { - @Expose() - id: string; - - @Expose() - roleId: string; - - @ApiProperty({}) - @Expose() - title: string; - - @ApiProperty({}) - @Expose() - parentId: string; - - @ApiProperty({}) - @Expose() - status: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} From 831da5b281bc6252b4a910784e2cba3f877551e4 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 8 Apr 2024 18:21:16 +0530 Subject: [PATCH 190/408] Fix[changes] --- src/adapters/postgres/rbac/privilege-adapter.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index 464f30da..f4bd872b 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -1,11 +1,8 @@ import { HttpStatus, Injectable } from '@nestjs/common'; -import { Role } from "src/rbac/role/entities/rbac.entity" import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { RoleDto } from "../../../rbac/role/dto/role.dto"; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; -import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; @Injectable() export class PostgresPrivilegeService { From 3f03186699166055fc8df95b22c6ab75ffb37c36 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 8 Apr 2024 18:23:56 +0530 Subject: [PATCH 191/408] Fix[changes] --- src/adapters/hasura/rbac/privilege.adapter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/adapters/hasura/rbac/privilege.adapter.ts b/src/adapters/hasura/rbac/privilege.adapter.ts index 17597081..bf5904b4 100644 --- a/src/adapters/hasura/rbac/privilege.adapter.ts +++ b/src/adapters/hasura/rbac/privilege.adapter.ts @@ -1,7 +1,6 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; -import { RoleDto } from "../../../rbac/role/dto/role.dto"; -import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; + @Injectable() export class HasuraPrivilegeService { From 8092cd6bbb744b3263c29d65fc0b5035b7558037 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:31:25 +0530 Subject: [PATCH 192/408] chore : remove student module --- src/Question/dto/question.dto.ts | 1 - src/adapters/hasura/attendance.adapter.ts | 1 - src/adapters/hasura/cohort.adapter.ts | 1 - src/adapters/hasura/fields.adapter.ts | 1 - src/adapters/hasura/worksheet.adapter.ts | 3 +- src/adapters/postgres/cohort-adapter.ts | 1 - src/adapters/studentservicelocator.ts | 9 - src/app.module.ts | 4 +- src/cohort/cohort.service.ts | 132 ++++++------ src/interfaces/entities/IStudent.ts | 22 -- src/student/dto/student-detail.dto.ts | 99 --------- src/student/dto/student-search.dto.ts | 28 --- src/student/dto/student.dto.ts | 218 -------------------- src/student/interfaces/student.interface.ts | 23 --- src/student/student.controller.spec.ts | 18 -- src/student/student.controller.ts | 95 --------- src/student/student.module.ts | 11 - src/student/studentadapter.ts | 14 -- 18 files changed, 62 insertions(+), 619 deletions(-) delete mode 100644 src/adapters/studentservicelocator.ts delete mode 100644 src/interfaces/entities/IStudent.ts delete mode 100644 src/student/dto/student-detail.dto.ts delete mode 100644 src/student/dto/student-search.dto.ts delete mode 100644 src/student/dto/student.dto.ts delete mode 100644 src/student/interfaces/student.interface.ts delete mode 100644 src/student/student.controller.spec.ts delete mode 100644 src/student/student.controller.ts delete mode 100644 src/student/student.module.ts delete mode 100644 src/student/studentadapter.ts diff --git a/src/Question/dto/question.dto.ts b/src/Question/dto/question.dto.ts index db9177a2..1a1c73ae 100644 --- a/src/Question/dto/question.dto.ts +++ b/src/Question/dto/question.dto.ts @@ -1,6 +1,5 @@ import { ApiProperty } from "@nestjs/swagger"; import { Exclude, Expose } from "class-transformer"; -import { StudentDto } from "src/student/dto/student.dto"; export class QuestionDto { @Expose() diff --git a/src/adapters/hasura/attendance.adapter.ts b/src/adapters/hasura/attendance.adapter.ts index af209ac6..a6a029c7 100644 --- a/src/adapters/hasura/attendance.adapter.ts +++ b/src/adapters/hasura/attendance.adapter.ts @@ -8,7 +8,6 @@ import moment from "moment"; import jwt_decode from "jwt-decode"; import { IServicelocator } from "../attendanceservicelocator"; import { UserDto } from "src/user/dto/user.dto"; -import { StudentDto } from "src/student/dto/student.dto"; import { ErrorResponse } from "src/error-response"; import { AttendanceDateDto } from "src/attendance/dto/attendance-date.dto"; export const ShikshaAttendanceToken = "ShikshaAttendance"; diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index dcc17a5a..ae1ba820 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -9,7 +9,6 @@ import { CohortDto } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { IServicelocatorcohort } from "../cohortservicelocator"; import { UserDto } from "src/user/dto/user.dto"; -import { StudentDto } from "src/student/dto/student.dto"; import { FieldsService } from "./services/fields.service"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; diff --git a/src/adapters/hasura/fields.adapter.ts b/src/adapters/hasura/fields.adapter.ts index fe9b4979..7f1d7ff6 100644 --- a/src/adapters/hasura/fields.adapter.ts +++ b/src/adapters/hasura/fields.adapter.ts @@ -9,7 +9,6 @@ import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; import { IServicelocatorfields } from "../fieldsservicelocator"; import { UserDto } from "src/user/dto/user.dto"; -import { StudentDto } from "src/student/dto/student.dto"; export const HasuraFieldsToken = "HasuraFields"; import { FieldsService } from "./services/fields.service"; diff --git a/src/adapters/hasura/worksheet.adapter.ts b/src/adapters/hasura/worksheet.adapter.ts index 71757042..b04c678e 100644 --- a/src/adapters/hasura/worksheet.adapter.ts +++ b/src/adapters/hasura/worksheet.adapter.ts @@ -3,7 +3,6 @@ import { HttpService } from "@nestjs/axios"; import { SuccessResponse } from "src/success-response"; import { WorksheetDto } from "src/worksheet/dto/worksheet.dto"; import { WorksheetSearchDto } from "src/worksheet/dto/worksheet-search.dto"; -import { StudentDto } from "src/student/dto/student.dto"; import { ErrorResponse } from "src/error-response"; @Injectable() @@ -604,7 +603,7 @@ export class WorksheetService { createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", }; - return new StudentDto(studentMapping); + return studentMapping; }); return studentResponse; diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 2dda40c5..046f1e58 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -7,7 +7,6 @@ import jwt_decode from "jwt-decode"; import { CohortDto } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { UserDto } from "src/user/dto/user.dto"; -import { StudentDto } from "src/student/dto/student.dto"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; diff --git a/src/adapters/studentservicelocator.ts b/src/adapters/studentservicelocator.ts deleted file mode 100644 index 0912b59f..00000000 --- a/src/adapters/studentservicelocator.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { StudentSearchDto } from "src/student/dto/student-search.dto"; -import { StudentDto } from "src/student/dto/student.dto"; - -export interface IServicelocator { - getStudent(studentId: any, request: any); - createStudent(request: any, studentDto: StudentDto); - updateStudent(id: string, request: any, studentDto: StudentDto); - searchStudent(request: any, studentSearchDto: StudentSearchDto); -} diff --git a/src/app.module.ts b/src/app.module.ts index 1dea9bf7..639eaf01 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -3,9 +3,9 @@ import { ConfigModule } from "@nestjs/config"; import { AppController } from "./app.controller"; import { AppService } from "./app.service"; // import { MulterModule } from "@nestjs/platform-express/multer"; -/* // Below modules not in use for Shiksha 2.0 -import { StudentModule } from "./student/student.module"; + +/* import { SchoolModule } from "./school/school.module"; import { HolidayModule } from "./holiday/holiday.module"; import { ConfigurationModule } from "./configs/configuration.module"; diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 717f67ad..9e4759cc 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -8,7 +8,6 @@ import jwt_decode from "jwt-decode"; import { CohortDto } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { UserDto } from "src/user/dto/user.dto"; -import { StudentDto } from "src/student/dto/student.dto"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; @@ -20,7 +19,7 @@ import { FieldsService } from "../fields/fields.service"; import { response } from "express"; import APIResponse from "src/utils/response"; import { FieldValues } from "../fields/entities/fields-values.entity"; -import { v4 as uuidv4 } from 'uuid'; +import { v4 as uuidv4 } from "uuid"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; @@ -28,67 +27,52 @@ import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; export class CohortService { private cohort: CohortInterface; - constructor( @InjectRepository(Cohort) private cohortRepository: Repository, @InjectRepository(CohortMembers) private cohortMembersRepository: Repository, - private fieldsService: FieldsService, - ) { } + private fieldsService: FieldsService + ) {} - public async getCohortsDetails(userData, - request: any, - response: any){ - let apiId = 'api.concept.getCohortDetails' + public async getCohortsDetails(userData, request: any, response: any) { + let apiId = "api.concept.getCohortDetails"; try { - if(userData.name==='user'){ - let findCohortId = await this.findCohortName(userData?.id); - let result = { - cohortData: [], - }; - for (let data of findCohortId) { - let cohortData = { - cohortId: data?.cohortId, - name:data.name, - parentId:data?.parentId, - customField:{} + if (userData.name === "user") { + let findCohortId = await this.findCohortName(userData?.id); + let result = { + cohortData: [], }; - const getDetails = await this.getCohortListDetails(data?.cohortId); - cohortData.customField=getDetails - result.cohortData.push(cohortData); - } - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - result, - "OK" - ) - ); - }else{ + for (let data of findCohortId) { + let cohortData = { + cohortId: data?.cohortId, + name: data.name, + parentId: data?.parentId, + customField: {}, + }; + const getDetails = await this.getCohortListDetails(data?.cohortId); + cohortData.customField = getDetails; + result.cohortData.push(cohortData); + } + return response + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, result, "OK")); + } else { let cohortName = await this.cohortRepository.findOne({ - where:{cohortId:userData?.id}, - select:['name','parentId'] - }) + where: { cohortId: userData?.id }, + select: ["name", "parentId"], + }); let cohortData = { cohortId: userData?.id, - name:cohortName?.name, - parentId:cohortName?.parentId, - customField:{} + name: cohortName?.name, + parentId: cohortName?.parentId, + customField: {}, }; const getDetails = await this.getCohortListDetails(userData?.id); - cohortData.customField=getDetails + cohortData.customField = getDetails; return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - cohortData, - "OK" - ) - ); + .status(HttpStatus.OK) + .send(APIResponse.success(apiId, cohortData, "OK")); } } catch (error) { return response @@ -125,9 +109,7 @@ export class CohortService { ) fv ON fv."itemId" = cm."cohortId" INNER JOIN public."Fields" f ON fv."fieldId" = f."fieldId" WHERE cm."cohortId" = $1;`; - let result = await this.cohortMembersRepository.query(query, [ - userId - ]); + let result = await this.cohortMembersRepository.query(query, [userId]); return result; } public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { @@ -135,7 +117,11 @@ export class CohortService { const cohortData: any = {}; cohortCreateDto.cohortId = uuidv4(); Object.keys(cohortCreateDto).forEach((e) => { - if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { + if ( + cohortCreateDto[e] && + cohortCreateDto[e] != "" && + e != "fieldValues" + ) { if (Array.isArray(cohortCreateDto[e])) { cohortData[e] = JSON.stringify(cohortCreateDto[e]); } else { @@ -151,7 +137,6 @@ export class CohortService { if (field_value_array.length > 0) { let field_values = []; for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); let fieldValueDto: FieldValuesDto = { fieldValuesId: "", // Provide a value for fieldValuesId @@ -173,7 +158,6 @@ export class CohortService { message: "Ok.", data: response, }); - } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, @@ -191,7 +175,10 @@ export class CohortService { const cohortUpdateData: any = {}; Object.keys(cohortUpdateDto).forEach((e) => { - if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" + if ( + cohortUpdateDto[e] && + cohortUpdateDto[e] != "" && + e != "fieldValues" ) { if (Array.isArray(cohortUpdateDto[e])) { cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); @@ -201,19 +188,23 @@ export class CohortService { } }); - const response = await this.cohortRepository.update(cohortId, cohortUpdateData); - + const response = await this.cohortRepository.update( + cohortId, + cohortUpdateData + ); let field_value_array = cohortUpdateDto.fieldValues.split("|"); if (field_value_array.length > 0) { let field_values = []; for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; try { - const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + const fieldVauesRowId = await this.fieldsService.searchFieldValueId( + cohortId, + fieldId + ); const rowid = fieldVauesRowId.fieldValuesId; let fieldValueDto: FieldValuesDto = { @@ -227,7 +218,7 @@ export class CohortService { updatedAt: new Date().toISOString(), }; await this.fieldsService.updateFieldValues(rowid, fieldValueDto); - }catch{ + } catch { let fieldValueDto: FieldValuesDto = { fieldValuesId: null, value: fieldValues[1] ? fieldValues[1].trim() : "", @@ -248,7 +239,7 @@ export class CohortService { message: "Ok.", data: { rowCount: response.affected, - } + }, }); } catch (e) { return new ErrorResponseTypeOrm({ @@ -261,10 +252,9 @@ export class CohortService { public async searchCohort( tenantId: string, request: any, - cohortSearchDto: CohortSearchDto, + cohortSearchDto: CohortSearchDto ) { try { - let { limit, page, filters } = cohortSearchDto; let offset = 0; @@ -272,8 +262,8 @@ export class CohortService { offset = parseInt(limit) * (page - 1); } - if (limit.trim() === '') { - limit = '0'; + if (limit.trim() === "") { + limit = "0"; } const whereClause = {}; @@ -292,11 +282,10 @@ export class CohortService { return new SuccessResponse({ statusCode: HttpStatus.OK, - message: 'Ok.', + message: "Ok.", totalCount, data: mappedResponse, }); - } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, @@ -324,14 +313,11 @@ export class CohortService { metadata: item?.metadata ? `${item.metadata}` : "", }; return new CohortDto(cohortMapping); - }) + }); return cohortValueResponse; - } - public async updateCohortStatus( - cohortId: string - ) { + public async updateCohortStatus(cohortId: string) { try { let query = `UPDATE public."Cohort" SET "status" = false diff --git a/src/interfaces/entities/IStudent.ts b/src/interfaces/entities/IStudent.ts deleted file mode 100644 index 8cd815e1..00000000 --- a/src/interfaces/entities/IStudent.ts +++ /dev/null @@ -1,22 +0,0 @@ -interface IStudent { - studentId: string; - refId: string; - aadhaar: string; - firstName: string; - lastName: string; - schoolId: string; - currentClassId: string; - gender: string; - socialCategory: string; - iscwsn: string; - religion: string; - singleGirl: string; - weight: string; - height: string; - bloodGroup: string; - birthDate: string; - homeless: string; - bpl: string; - migrant: string; - status: string; -} diff --git a/src/student/dto/student-detail.dto.ts b/src/student/dto/student-detail.dto.ts deleted file mode 100644 index 36c63184..00000000 --- a/src/student/dto/student-detail.dto.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { Exclude, Expose } from "class-transformer"; - -export class StudentDetailDto { - @Expose() - studentId: string; - - @Expose() - refId: string; - - @Expose() - aadhaar: string; - - @Expose() - firstName: string; - - @Expose() - lastName: string; - - @Expose() - schoolId: string; - - @Expose() - currentClassId: string; - - @Expose() - gender: string; - - @Expose() - socialCategory: string; - - @Expose() - iscwsn: string; - - @Expose() - religion: string; - - @Expose() - singleGirl: string; - - @Expose() - weight: string; - - @Expose() - height: string; - - @Expose() - bloodGroup: string; - - @Expose() - birthDate: string; - - @Expose() - homeless: string; - - @Expose() - bpl: string; - - @Expose() - migrant: string; - - @Expose() - status: string; - - @Expose() - email: string; - - @Expose() - fullName: string; - - @Expose() - fatherName: string; - - @Expose() - phoneNumber: string; - - @Expose() - admissionNo: string; - - @Expose() - address: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: object = {}) { - Object.keys(obj).forEach((key) => (obj[key] === "" ? delete obj[key] : {})); - Object.assign(this, obj); - } -} diff --git a/src/student/dto/student-search.dto.ts b/src/student/dto/student-search.dto.ts deleted file mode 100644 index baaf8675..00000000 --- a/src/student/dto/student-search.dto.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Exclude, Expose } from "class-transformer"; -import { - MaxLength, - IsNotEmpty, - IsEmail, - IsString, - IsNumber, -} from "class-validator"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class StudentSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/student/dto/student.dto.ts b/src/student/dto/student.dto.ts deleted file mode 100644 index 3fb5f953..00000000 --- a/src/student/dto/student.dto.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { Exclude, Expose } from "class-transformer"; - -export class StudentDto { - @Expose() - studentId: string; - - @ApiProperty() - @Expose() - refId1: string; - - @ApiProperty() - @Expose() - refId2: string; - - @ApiPropertyOptional() - @Expose() - aadhaar: string; - - @ApiProperty() - @Expose() - firstName: string; - - @ApiProperty() - @Expose() - middleName: string; - - @ApiProperty() - @Expose() - lastName: string; - - @ApiProperty() - @Expose() - schoolId: string; - - @ApiProperty() - @Expose() - studentPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - studentEmail: string; - - @ApiProperty() - @Expose() - gender: string; - - @ApiProperty() - @Expose() - groupId: string; - - @ApiPropertyOptional() - @Expose() - socialCategory: string; - - @ApiPropertyOptional() - @Expose() - iscwsn: string; - - @ApiPropertyOptional() - @Expose() - religion: string; - - @ApiPropertyOptional() - @Expose() - singleGirl: Boolean; - - @ApiPropertyOptional() - @Expose() - weight: string; - - @ApiPropertyOptional() - @Expose() - height: string; - - @ApiPropertyOptional() - @Expose() - bloodGroup: string; - - @ApiProperty() - @Expose() - birthDate: string; - - @ApiPropertyOptional() - @Expose() - homeless: Boolean; - - @ApiProperty() - @Expose() - bpl: Boolean; - - @ApiProperty() - @Expose() - migrant: Boolean; - - @ApiProperty() - @Expose() - status: string; - - @ApiPropertyOptional() - @Expose() - fatherFirstName: string; - - @ApiPropertyOptional() - @Expose() - fatherMiddleName: string; - - @ApiPropertyOptional() - @Expose() - fatherLastName: string; - - @ApiPropertyOptional() - @Expose() - fatherPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - fatherEmail: string; - - @ApiPropertyOptional() - @Expose() - motherFirstName: string; - - @ApiPropertyOptional() - @Expose() - motherMiddleName: string; - - @ApiPropertyOptional() - @Expose() - motherLastName: string; - - @ApiPropertyOptional() - @Expose() - motherPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - motherEmail: string; - - @ApiPropertyOptional() - @Expose() - guardianFirstName: string; - - @ApiPropertyOptional() - @Expose() - guardianMiddleName: string; - - @ApiPropertyOptional() - @Expose() - guardianLastName: string; - - @ApiPropertyOptional() - @Expose() - guardianPhoneNumber: Number; - - @ApiPropertyOptional() - @Expose() - guardianEmail: string; - - @ApiPropertyOptional({ - type: "string", - format: "binary", - }) - @Expose() - image: string; - - @ApiPropertyOptional() - @Expose() - studentAddress: string; - - @ApiProperty() - @Expose() - village: string; - - @ApiProperty() - @Expose() - block: string; - - @ApiProperty() - @Expose() - district: string; - - @ApiProperty() - @Expose() - stateId: string; - - @ApiProperty() - @Expose() - pincode: Number; - - @ApiProperty() - @Expose() - locationId: string; - - @ApiPropertyOptional() - @Expose() - deactivationReason: string; - - @ApiPropertyOptional() - @Expose() - metaData: [string]; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/student/interfaces/student.interface.ts b/src/student/interfaces/student.interface.ts deleted file mode 100644 index db0d9903..00000000 --- a/src/student/interfaces/student.interface.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface StudentInterface { - studentId?: string; - refId?: string; - aadhaar?: string; - firstName?: string; - lastName?: string; - schoolId?: string; - currentClassId?: string; - gender?: string; - socialCategory?: string; - iscwsn?: string; - religion?: string; - singleGirl?: string; - weight?: string; - height?: string; - bloodGroup?: string; - birthDate?: string; - homeless?: string; - bpl?: string; - migrant?: string; - status?: string; - email?: string; -} diff --git a/src/student/student.controller.spec.ts b/src/student/student.controller.spec.ts deleted file mode 100644 index 52ad318f..00000000 --- a/src/student/student.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from "@nestjs/testing"; -import { StudentController } from "./student.controller"; - -describe("StudentController", () => { - let controller: StudentController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [StudentController], - }).compile(); - - controller = module.get(StudentController); - }); - - it("should be defined", () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/student/student.controller.ts b/src/student/student.controller.ts deleted file mode 100644 index 556b97b4..00000000 --- a/src/student/student.controller.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Request } from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiExcludeController, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Post, - Body, - Put, - Patch, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, -} from "@nestjs/common"; -import { StudentDto } from "./dto/student.dto"; -import { StudentSearchDto } from "./dto/student-search.dto"; -import { IServicelocator } from "src/adapters/studentservicelocator"; -import { StudentAdapter } from "./studentadapter"; -// @ApiTags("Student") -@ApiExcludeController() -@Controller("student") -export class StudentController { - constructor(private studentAdapter: StudentAdapter) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Student detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getStudent(@Param("id") studentId: string, @Req() request: Request) { - return this.studentAdapter - .buildStudentAdapter() - .getStudent(studentId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Student has been created successfully." }) - // @ApiBody({ type: StudentDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createStudent( - @Req() request: Request, - @Body() studentDto: StudentDto - ) { - return this.studentAdapter - .buildStudentAdapter() - .createStudent(request, studentDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Student has been updated successfully." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateStudent( - @Param("id") id: string, - @Req() request: Request, - @Body() studentDto: StudentDto - ) { - return await this.studentAdapter - .buildStudentAdapter() - .updateStudent(id, request, studentDto); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Student list." }) - // @ApiBody({ type: StudentSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchStudent( - @Req() request: Request, - @Body() studentSearchDto: StudentSearchDto - ) { - return this.studentAdapter - .buildStudentAdapter() - .searchStudent(request, studentSearchDto); - } -} diff --git a/src/student/student.module.ts b/src/student/student.module.ts deleted file mode 100644 index 23c37fbd..00000000 --- a/src/student/student.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from "@nestjs/common"; -import { StudentController } from "./student.controller"; -import { HttpModule } from "@nestjs/axios"; -import { StudentAdapter } from "./studentadapter"; - -@Module({ - imports: [HttpModule], - controllers: [StudentController], - providers: [StudentAdapter], -}) -export class StudentModule {} diff --git a/src/student/studentadapter.ts b/src/student/studentadapter.ts deleted file mode 100644 index b72d5097..00000000 --- a/src/student/studentadapter.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { IServicelocator } from "src/adapters/studentservicelocator"; - -@Injectable() -export class StudentAdapter { - constructor() {} - buildStudentAdapter(): IServicelocator { - let adapter: IServicelocator; - - switch (process.env.ADAPTERSOURCE) { - } - return adapter; - } -} From 02caa8b6ea5894aba10dbfd2cfc10892b1b2dfc7 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:34:47 +0530 Subject: [PATCH 193/408] chore : removed school module --- src/adapters/hasura/hasura.module.ts | 3 - src/adapters/hasura/school.adapter.ts | 286 ---------------------- src/adapters/schoolservicelocator.ts | 9 - src/app.module.ts | 1 - src/school/dto/school-response.dto.ts | 15 -- src/school/dto/school-search.dto.ts | 26 -- src/school/dto/school.dto.ts | 184 -------------- src/school/interfaces/school.interface.ts | 15 -- src/school/school.controller.spec.ts | 18 -- src/school/school.controller.ts | 90 ------- src/school/school.module.ts | 12 - src/school/schooladapter.ts | 18 -- 12 files changed, 677 deletions(-) delete mode 100644 src/adapters/hasura/school.adapter.ts delete mode 100644 src/adapters/schoolservicelocator.ts delete mode 100644 src/school/dto/school-response.dto.ts delete mode 100644 src/school/dto/school-search.dto.ts delete mode 100644 src/school/dto/school.dto.ts delete mode 100644 src/school/interfaces/school.interface.ts delete mode 100644 src/school/school.controller.spec.ts delete mode 100644 src/school/school.controller.ts delete mode 100644 src/school/school.module.ts delete mode 100644 src/school/schooladapter.ts diff --git a/src/adapters/hasura/hasura.module.ts b/src/adapters/hasura/hasura.module.ts index 67643280..d6a4354a 100644 --- a/src/adapters/hasura/hasura.module.ts +++ b/src/adapters/hasura/hasura.module.ts @@ -5,7 +5,6 @@ import { HasuraCommentService } from "./comment.adapter"; import { HasuraConfigService } from "./config.adapter"; import { HasuraHolidayService } from "./holiday.adapter"; import { HasuraLikeService } from "./like.adapter"; -import { SchoolHasuraService } from "./school.adapter"; import { HasuraCohortService } from "./cohort.adapter"; import { HasuraCohortMembersService } from "./cohortMembers.adapter"; import { HasuraFieldsService } from "./fields.adapter"; @@ -16,7 +15,6 @@ import { HasuraUserService } from "./user.adapter"; imports: [HttpModule], providers: [ AttendanceHasuraService, - SchoolHasuraService, HasuraCohortService, HasuraCohortMembersService, HasuraCommentService, @@ -29,7 +27,6 @@ import { HasuraUserService } from "./user.adapter"; ], exports: [ AttendanceHasuraService, - SchoolHasuraService, HasuraCohortService, HasuraCohortMembersService, HasuraCommentService, diff --git a/src/adapters/hasura/school.adapter.ts b/src/adapters/hasura/school.adapter.ts deleted file mode 100644 index ca6188f6..00000000 --- a/src/adapters/hasura/school.adapter.ts +++ /dev/null @@ -1,286 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { SchoolDto } from "src/school/dto/school.dto"; -import { SchoolSearchDto } from "src/school/dto/school-search.dto"; -import { IServicelocator } from "../schoolservicelocator"; -export const HasuraSchoolToken = "HasuraSchool"; -@Injectable() -export class SchoolHasuraService implements IServicelocator { - constructor(private httpService: HttpService) {} - - public async createSchool(request: any, schoolDto: SchoolDto) { - var axios = require("axios"); - const schoolSchema = new SchoolDto(schoolDto); - let query = ""; - Object.keys(schoolDto).forEach((e) => { - if ( - schoolDto[e] && - schoolDto[e] != "" && - Object.keys(schoolSchema).includes(e) - ) { - if (Array.isArray(schoolDto[e])) { - query += `${e}: ${JSON.stringify(schoolDto[e])}, `; - } else { - query += `${e}: "${schoolDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateSchool { - insert_school_one(object: {${query}}) { - schoolId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_school_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateSchool(id: string, request: any, schoolDto: SchoolDto) { - var axios = require("axios"); - const schoolSchema = new SchoolDto(schoolDto); - let query = ""; - Object.keys(schoolDto).forEach((e) => { - if ( - schoolDto[e] && - schoolDto[e] != "" && - Object.keys(schoolSchema).includes(e) - ) { - if (Array.isArray(schoolDto[e])) { - query += `${e}: ${JSON.stringify(schoolDto[e])}, `; - } else { - query += `${e}: "${schoolDto[e]}", `; - } - } - }); - - var data = { - query: `mutation UpdateSchool($schoolId:uuid) { - update_school(where: {schoolId: {_eq: $schoolId}}, _set: {${query}}) { - affected_rows - }}`, - variables: { - schoolId: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async getSchool(schoolId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetSchool($schoolId:uuid!) { - school_by_pk(schoolId: $schoolId) { - address - block - created_at - deactivationReason - district - email - latitude - enrollCount - locationId - longitude - mediumOfInstruction - metaData - phoneNumber - updated_at - status - udise - stateId - schoolType - schoolName - schoolId - pincode - village - website - cluster - headMaster - board - } - } - `, - variables: { schoolId: schoolId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = [response.data.data.school_by_pk]; - const schoolDto = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: schoolDto[0], - }); - } - public async searchSchool(request: any, schoolSearchDto: SchoolSearchDto) { - var axios = require("axios"); - - let offset = 0; - - if (schoolSearchDto.page > 1) { - offset = parseInt(schoolSearchDto.limit) * (schoolSearchDto.page - 1); - } - - let query = ""; - Object.keys(schoolSearchDto.filters).forEach((e) => { - if (schoolSearchDto.filters[e] && schoolSearchDto.filters[e] != "") { - query += `${e}:{_eq:"${schoolSearchDto.filters[e]}"}`; - } - }); - - var data = { - query: `query SearchSchool($limit:Int, $offset:Int) { - school_aggregate { - aggregate { - count - } - } - school(where:{ ${query}}, limit: $limit, offset: $offset,) { - address - block - created_at - deactivationReason - district - email - latitude - enrollCount - locationId - longitude - mediumOfInstruction - metaData - phoneNumber - updated_at - status - udise - stateId - schoolType - schoolName - schoolId - pincode - village - website - cluster - headMaster - board - } - }`, - variables: { - limit: parseInt(schoolSearchDto.limit), - offset: offset, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.school; - const schoolDto = await this.mappedResponse(result); - const count = response?.data?.data?.school_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: schoolDto, - }); - } - public async mappedResponse(result: any) { - const schoolResponse = result.map((item: any) => { - const schoolMapping = { - id: item?.schoolId ? `${item.schoolId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - schoolName: item?.schoolName ? `${item.schoolName}` : "", - email: item?.email ? `${item.email}` : "", - udise: item?.udise ? `${item.udise}` : "", - mediumOfInstruction: item?.mediumOfInstruction - ? item.mediumOfInstruction - : "", - phoneNumber: item?.phoneNumber ? item.phoneNumber : "", - address: item?.address ? item.address : "", - schoolType: item?.schoolType ? `${item.schoolType}` : "", - website: item?.website ? `${item.website}` : "", - headMaster: item?.headMaster ? `${item.headMaster}` : "", - board: item?.board ? `${item.board}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - cluster: item?.cluster ? `${item.cluster}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - enrollCount: item?.enrollCount ? `${item.enrollCount}` : "", - status: item?.status ? `${item.status}` : "", - latitude: item?.latitude ? item.latitude : "", - longitude: item?.longitude ? item.longitude : "", - metaData: item?.metaData ? item.metaData : [], - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - createdAt: item?.created_at ? `${item.created_at}` : "", - updatedAt: item?.updated_at ? `${item.updated_at}` : "", - }; - return new SchoolDto(schoolMapping); - }); - - return schoolResponse; - } -} diff --git a/src/adapters/schoolservicelocator.ts b/src/adapters/schoolservicelocator.ts deleted file mode 100644 index fae79c28..00000000 --- a/src/adapters/schoolservicelocator.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { SchoolSearchDto } from "src/school/dto/school-search.dto"; -import { SchoolDto } from "src/school/dto/school.dto"; - -export interface IServicelocator { - searchSchool(request: any, schoolSearchDto: SchoolSearchDto); - createSchool(request: any, schoolDto: SchoolDto); - updateSchool(id: string, request: any, schoolDto: SchoolDto); - getSchool(schoolId: any, request: any); -} diff --git a/src/app.module.ts b/src/app.module.ts index 639eaf01..f5c7dfaf 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -6,7 +6,6 @@ import { AppService } from "./app.service"; // Below modules not in use for Shiksha 2.0 /* -import { SchoolModule } from "./school/school.module"; import { HolidayModule } from "./holiday/holiday.module"; import { ConfigurationModule } from "./configs/configuration.module"; import { WorksheetModule } from "./worksheet/worksheet.module"; diff --git a/src/school/dto/school-response.dto.ts b/src/school/dto/school-response.dto.ts deleted file mode 100644 index 8435e097..00000000 --- a/src/school/dto/school-response.dto.ts +++ /dev/null @@ -1,15 +0,0 @@ -export interface SchoolResponseDto { - schoolId: string; - schoolName: string; - email: string; - schoolRefId: string; - instituteManagement: string; - address: string; - schoolType: string; - website: string; - street: string; - city: string; - district: string; - state: string; - pincode: string; -} diff --git a/src/school/dto/school-search.dto.ts b/src/school/dto/school-search.dto.ts deleted file mode 100644 index b7f1cd9c..00000000 --- a/src/school/dto/school-search.dto.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class SchoolSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Number, - description: "Page", - }) - page: number; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/school/dto/school.dto.ts b/src/school/dto/school.dto.ts deleted file mode 100644 index 03c278f9..00000000 --- a/src/school/dto/school.dto.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { Exclude, Expose } from "class-transformer"; -import { - MaxLength, - IsNotEmpty, - IsEmail, - IsString, - IsNumber, -} from "class-validator"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class SchoolDto { - @Expose() - id: string; - - @Expose() - schoolId: string; - - @ApiProperty({ - type: String, - description: "The schoolName of the school", - }) - @Expose() - schoolName: string; - - @ApiProperty({ - type: String, - description: "The email of the school", - }) - @IsEmail() - @Expose() - email: string; - - @ApiProperty({ - type: String, - description: "The udise of the school", - }) - @Expose() - udise: string; - - @ApiProperty({ - type: [String], - description: "The medium of instruction of the school", - }) - @Expose() - mediumOfInstruction: [string]; - - @ApiProperty({ - type: Number, - description: "The phone number of the school", - }) - @IsNumber() - @Expose() - phoneNumber: Number; - - @ApiProperty({ - type: String, - description: "The address of the school", - }) - @Expose() - address: string; - - @ApiProperty({ - type: String, - description: "The schoolType of the school", - }) - @Expose() - schoolType: string; - - @ApiProperty({ - type: String, - description: "The website of the school", - }) - @Expose() - website: string; - - @ApiProperty({ - type: String, - description: "The Head master of the school", - }) - @Expose() - headMaster: string; - - @ApiProperty({ - type: String, - description: "The Board of the school", - }) - @Expose() - board: string; - - @ApiProperty({ - type: String, - description: "The village of the school", - }) - @Expose() - village: string; - - @ApiProperty({ - type: String, - description: "The block of the school", - }) - @Expose() - block: string; - - @ApiProperty({ - type: String, - description: "The district of the school", - }) - @Expose() - district: string; - - @ApiProperty({ - type: String, - description: "The stateId of the school", - }) - @Expose() - stateId: string; - - @ApiProperty({ - type: Number, - description: "The pincode of the school", - }) - @Expose() - pincode: Number; - - @ApiProperty({ - type: String, - description: "The cluster of the school", - }) - @Expose() - cluster: string; - - @ApiProperty({ - type: String, - description: "The locationId of the school", - }) - @Expose() - locationId: string; - - @ApiProperty({ - type: String, - description: "The enrollCount of the school", - }) - @Expose() - enrollCount: string; - - @ApiProperty({ - type: String, - description: "The status of the school", - }) - @Expose() - status: string; - - @ApiProperty({ - type: Number, - description: "The latitude of the school", - }) - @Expose() - latitude: Number; - - @ApiProperty({ - type: Number, - description: "The longitude of the school", - }) - @Expose() - longitude: Number; - - @ApiPropertyOptional() - @Expose() - metaData: [string]; - - @ApiPropertyOptional({}) - @Expose() - deactivationReason: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/school/interfaces/school.interface.ts b/src/school/interfaces/school.interface.ts deleted file mode 100644 index aea9e0a0..00000000 --- a/src/school/interfaces/school.interface.ts +++ /dev/null @@ -1,15 +0,0 @@ -export interface SchoolInterface { - schoolId?: string; - schoolName?: string; - email?: string; - schoolRefId?: string; - instituteManagement?: string; - address?: string; - schoolType?: string; - website?: string; - street?: string; - city?: string; - district?: string; - state?: string; - pincode?: string; -} diff --git a/src/school/school.controller.spec.ts b/src/school/school.controller.spec.ts deleted file mode 100644 index 6c749dfb..00000000 --- a/src/school/school.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from "@nestjs/testing"; -import { SchoolController } from "./school.controller"; - -describe("SchoolController", () => { - let controller: SchoolController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [SchoolController], - }).compile(); - - controller = module.get(SchoolController); - }); - - it("should be defined", () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/school/school.controller.ts b/src/school/school.controller.ts deleted file mode 100644 index ff5b1adc..00000000 --- a/src/school/school.controller.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - Controller, - Get, - Post, - Put, - Param, - Body, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Request, -} from "@nestjs/common"; -import { SchoolDto } from "./dto/school.dto"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiExcludeController, -} from "@nestjs/swagger"; -import { SchoolSearchDto } from "./dto/school-search.dto"; -import { SchoolAdapter } from "./schooladapter"; -// @ApiTags("School") -@ApiExcludeController() -@Controller("school") -export class SchoolController { - constructor(private schoolAdapter: SchoolAdapter) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: "School detail." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getSchool(@Param("id") id: string, @Req() request: Request) { - return this.schoolAdapter.buildSchoolAdapter().getSchool(id, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "School has been created successfully." }) - // @ApiBody({ type: SchoolDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createSchool( - @Req() request: Request, - @Body() schoolDto: SchoolDto - ) { - return this.schoolAdapter - .buildSchoolAdapter() - .createSchool(request, schoolDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "School has been updated successfully." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateSchool( - @Param("id") id: string, - @Req() request: Request, - @Body() schoolDto: SchoolDto - ) { - return this.schoolAdapter - .buildSchoolAdapter() - .updateSchool(id, request, schoolDto); - } - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "School list." }) - // @ApiBody({ type: SchoolSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchSchool( - @Req() request: Request, - @Body() schoolSearchDto: SchoolSearchDto - ) { - return this.schoolAdapter - .buildSchoolAdapter() - .searchSchool(request, schoolSearchDto); - } -} diff --git a/src/school/school.module.ts b/src/school/school.module.ts deleted file mode 100644 index d17e243e..00000000 --- a/src/school/school.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CacheModule, Module } from "@nestjs/common"; -import { SchoolController } from "./school.controller"; -import { HttpModule } from "@nestjs/axios"; -import { SchoolAdapter } from "./schooladapter"; -import { HasuraModule } from "src/adapters/hasura/hasura.module"; - -@Module({ - imports: [HttpModule, HasuraModule], - controllers: [SchoolController], - providers: [SchoolAdapter], -}) -export class SchoolModule {} diff --git a/src/school/schooladapter.ts b/src/school/schooladapter.ts deleted file mode 100644 index 0dc24e95..00000000 --- a/src/school/schooladapter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { SchoolHasuraService } from "src/adapters/hasura/school.adapter"; -import { IServicelocator } from "src/adapters/schoolservicelocator"; - -@Injectable() -export class SchoolAdapter { - constructor(private hasuraProvider: SchoolHasuraService) {} - buildSchoolAdapter(): IServicelocator { - let adapter: IServicelocator; - - switch (process.env.ADAPTERSOURCE) { - case "hasura": - adapter = this.hasuraProvider; - break; - } - return adapter; - } -} From 71f36d85801baed8af6bddd6656bf5a2bff0ce18 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 8 Apr 2024 18:37:21 +0530 Subject: [PATCH 194/408] minor changes --- src/adapters/hasura/user.adapter.ts | 224 ++++++++-------- src/adapters/postgres/user-adapter.ts | 364 ++++++++++++++++---------- src/adapters/userservicelocator.ts | 18 +- src/user/user.controller.ts | 48 ++-- 4 files changed, 383 insertions(+), 271 deletions(-) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 6e5ae0da..73ad7050 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -28,117 +28,119 @@ export class HasuraUserService implements IServicelocator { public async findUserDetails(userID: any, username: String) { } - public async getUser( - userData?:Record, - res?: any, - tenantId?: string, - userId?: string, - accessRole?: string, - request?: any, - ) { - try { - const decoded: any = jwt_decode(request.headers.authorization); - const userRoles = - decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; - - const data = { - query: `query GetUser($userId: uuid!, $tenantId: uuid!, $context: String!, $contextId: uuid!, $access : String!) { - Users(where: {tenantId: {_eq: $tenantId}, userId: {_eq: $userId}}) { - username - userId - name - email - district - state - address - pincode - mobile - dob - role - tenantId - updatedAt - updatedBy - createdBy - createdAt - fields: UsersFieldsTenants(where: {_or: [{contextId: {_is_null: true}}, {contextId: {_eq: $contextId}}], context: {_eq: $context}, _and: {_or: [{access: {_is_null: true}}, {access: {_eq: $access}}]}}) { - tenantId - fieldId - assetId - context - contextId - groupId - name - label - defaultValue - type - note - description - state - required - ordering - metadata - access - onlyUseInSubform - updatedAt - updatedBy - createdAt - createdBy - fieldValues: FieldValues(where: {itemId: {_eq: $contextId}}) { - value - itemId - fieldId - fieldValuesId - updatedBy - updatedAt - createdBy - createdAt - } - } - } - }`, - variables: { - userId: userId, - tenantId: tenantId, - context: "Users", - contextId: userId, - access: accessRole, - }, - }; - - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-role": getUserRole(userRoles), - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await this.axios(config); - - if (response?.data?.errors) { - return res.status(400).send({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - const result = response.data.data.Users; - return res.status(200).send({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - } catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } - } + public async getUsersDetailsById(userData: Record, response:any) {} + public async getUsersDetailsByCohortId(userData: Record, response:any) {} + // public async getUser( + // userData?:Record, + // res?: any, + // tenantId?: string, + // userId?: string, + // accessRole?: string, + // request?: any, + // ) { + // try { + // const decoded: any = jwt_decode(request.headers.authorization); + // const userRoles = + // decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; + + // const data = { + // query: `query GetUser($userId: uuid!, $tenantId: uuid!, $context: String!, $contextId: uuid!, $access : String!) { + // Users(where: {tenantId: {_eq: $tenantId}, userId: {_eq: $userId}}) { + // username + // userId + // name + // email + // district + // state + // address + // pincode + // mobile + // dob + // role + // tenantId + // updatedAt + // updatedBy + // createdBy + // createdAt + // fields: UsersFieldsTenants(where: {_or: [{contextId: {_is_null: true}}, {contextId: {_eq: $contextId}}], context: {_eq: $context}, _and: {_or: [{access: {_is_null: true}}, {access: {_eq: $access}}]}}) { + // tenantId + // fieldId + // assetId + // context + // contextId + // groupId + // name + // label + // defaultValue + // type + // note + // description + // state + // required + // ordering + // metadata + // access + // onlyUseInSubform + // updatedAt + // updatedBy + // createdAt + // createdBy + // fieldValues: FieldValues(where: {itemId: {_eq: $contextId}}) { + // value + // itemId + // fieldId + // fieldValuesId + // updatedBy + // updatedAt + // createdBy + // createdAt + // } + // } + // } + // }`, + // variables: { + // userId: userId, + // tenantId: tenantId, + // context: "Users", + // contextId: userId, + // access: accessRole, + // }, + // }; + + // const config = { + // method: "post", + // url: process.env.REGISTRYHASURA, + // headers: { + // Authorization: request.headers.authorization, + // "x-hasura-role": getUserRole(userRoles), + // "Content-Type": "application/json", + // }, + // data: data, + // }; + + // const response = await this.axios(config); + + // if (response?.data?.errors) { + // return res.status(400).send({ + // errorCode: response?.data?.errors[0]?.extensions?.code, + // errorMessage: response?.data?.errors[0]?.message, + // }); + // } else { + // const result = response.data.data.Users; + // return res.status(200).send({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } + // } catch (e) { + // console.error(e); + // return new ErrorResponse({ + // errorCode: "400", + // errorMessage: e, + // }); + // } + // } public async checkAndAddUser(request: any, userDto: UserCreateDto) { try { diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 63bc8017..dad205a1 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -1,4 +1,4 @@ -import {ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; import { User } from '../../user/entities/user-entity' import { FieldValues } from '../../user/entities/field-value-entities'; import { InjectRepository } from '@nestjs/typeorm'; @@ -6,16 +6,17 @@ import { Repository } from 'typeorm'; import { UserCreateDto } from '../../user/dto/user-create.dto'; import jwt_decode from "jwt-decode"; import { - getKeycloakAdminToken, - createUserInKeyCloak, - checkIfUsernameExistsInKeycloak, + getKeycloakAdminToken, + createUserInKeyCloak, + checkIfUsernameExistsInKeycloak, } from "../../common/utils/keycloak.adapter.util" import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; import { Field } from '../../user/entities/field-entity'; import APIResponse from '../../utils/response'; import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; -import axios,{AxiosInstance, AxiosRequestConfig} from "axios" +import axios, { AxiosInstance, AxiosRequestConfig } from "axios" +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; @Injectable() @@ -28,100 +29,197 @@ export class PostgresUserService { @InjectRepository(FieldValues) private fieldsValueRepository: Repository, @InjectRepository(Field) - private fieldsRepository : Repository, - @InjectRepository (CohortMembers) + private fieldsRepository: Repository, + @InjectRepository(CohortMembers) private cohortMemberRepository: Repository - ) {} - - async getUser(userData:Record,response){ - let apiId='api.users.getUsersDetails' + ) { } + + async getUsersDetailsById(userData: Record, response: any) { + let apiId = 'api.users.getUsersDetails' try { const result = { - userData:{ + userData: { } }; - let customFieldsArray =[]; - const [customFields, filledValues,userDetails] = await Promise.all([ - this.findCustomFields(userData), - this.findFilledValues(userData.userId), - this.findUserDetails(userData.userId) - ]); - result.userData=userDetails; - const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); - for (let data of customFields) { + + let customFieldsArray = []; + + const [filledValues, userDetails] = await Promise.all([ + this.findFilledValues(userData.userId), + this.findUserDetails(userData.userId) + ]); + + const customFields = await this.findCustomFields(userData, userDetails.role) + + result.userData = userDetails; + const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); + for (let data of customFields) { const fieldValue = filledValuesMap.get(data.fieldId); const customField = { - fieldId: data.fieldId, - label: data.label, - value: fieldValue || '', - options: data?.fieldParams?.['options'] || {}, - type: data.type || '' + fieldId: data.fieldId, + label: data.label, + value: fieldValue || '', + options: data?.fieldParams?.['options'] || {}, + type: data.type || '' }; customFieldsArray.push(customField); + } + result.userData['customFields'] = customFieldsArray; + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: result, + }); + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } - result.userData['customFields'] = customFieldsArray; - return response - .status(HttpStatus.OK) - .send(APIResponse.success(apiId, result, 'OK')); + } + + async getUsersDetailsByCohortId(userData: Record, response: any) { + let apiId = 'api.users.getAllUsersDetails' + try { + if (userData.fieldValue) { + let getUserDetails = await this.findUserName(userData.cohortId, userData.contextType) + let result = { + userDetails: [], + }; + + for (let data of getUserDetails) { + let userDetails = { + userId: data.userId, + userName: data.userName, + name: data.name, + role: data.role, + district: data.district, + state: data.state, + mobile: data.mobile, + } + result.userDetails.push(userDetails); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: result, + }); + + } else { + let getUserDetails = await this.findUserName(userData.cohortId, userData.contextType) + let result = { + userDetails: [], + }; + + for (let data of getUserDetails) { + let userDetails = { + userId: data.userId, + userName: data.userName, + name: data.name, + role: data.role, + district: data.district, + state: data.state, + mobile: data.mobile, + customField: [], + } + const fieldValues = await this.getFieldandFieldValues(data.userId) + + userDetails.customField.push(fieldValues); + + result.userDetails.push(userDetails); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: result, + }); + + } + } catch (e) { - response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - 'Something went wrong In finding UserDetails', - e, - 'INTERNAL_SERVER_ERROR', - ), - ); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } -} + } - async findUserDetails(userId,username?:any){ - let whereClause:any = { userId: userId }; - if(username && userId === null){ + async findUserName(cohortId: string, role: string) { + let query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + LEFT JOIN public."Users" U + ON CM."userId" = U."userId" + where CM."cohortId" =$1 ` + if (role !== null) { + query += ` AND U."role" = $2`; + } + let result: any[]; + if (role !== null) { + result = await this.usersRepository.query(query, [cohortId, role]); + } else { + result = await this.usersRepository.query(query, [cohortId]); + } + return result; + } + + async getFieldandFieldValues(userId: string) { + let query = `SELECT Fv."fieldId",F."label" AS FieldName,Fv."value" as FieldValues + FROM public."FieldValues" Fv + LEFT JOIN public."Fields" F + ON F."fieldId" = Fv."fieldId" + where Fv."itemId" =$1 ` + let result = await this.usersRepository.query(query, [userId]); + return result + } + + async findUserDetails(userId, username?: any) { + let whereClause: any = { userId: userId }; + if (username && userId === null) { delete whereClause.userId; whereClause.username = username; } let userDetails = await this.usersRepository.findOne({ - where:whereClause + where: whereClause }) return userDetails; } - async findCustomFields(userData){ + async findCustomFields(userData, role) { let customFields = await this.fieldsRepository.find({ - where:{ - context:userData.context, - contextType:userData.contextType.toUpperCase() + where: { + context: userData.context, + contextType: role.toUpperCase() } }) return customFields; } - async findFilledValues(userId:string){ + async findFilledValues(userId: string) { let query = `SELECT U."userId",F."fieldId",F."value" FROM public."Users" U LEFT JOIN public."FieldValues" F ON U."userId" = F."itemId" where U."userId" =$1`; - let result = await this.usersRepository.query(query,[userId]); + let result = await this.usersRepository.query(query, [userId]); return result; } - async updateUser(userDto,response){ + async updateUser(userDto, response) { const apiId = 'api.users.UpdateUserDetails' try { let updatedData = {}; - if(userDto.userData || Object.keys(userDto.userData).length > 0){ - await this.updateBasicUserDetails(userDto.userId,userDto.userData); + if (userDto.userData || Object.keys(userDto.userData).length > 0) { + await this.updateBasicUserDetails(userDto.userId, userDto.userData); updatedData['basicDetails'] = userDto.userData; } - if(userDto.customFields.length > 0){ + if (userDto.customFields.length > 0) { for (let data of userDto.customFields) { const result = await this.updateCustomFields(userDto.userId, data); if (result) { - if (!updatedData['customFields']) - updatedData['customFields']= []; - updatedData['customFields'].push(result); + if (!updatedData['customFields']) + updatedData['customFields'] = []; + updatedData['customFields'].push(result); } - } + } } return response .status(HttpStatus.OK) @@ -140,7 +238,7 @@ export class PostgresUserService { } } - async updateBasicUserDetails(userId,userData: Partial): Promise { + async updateBasicUserDetails(userId, userData: Partial): Promise { const user = await this.usersRepository.findOne({ where: { userId: userId } }); if (!user) { return null; @@ -150,26 +248,26 @@ export class PostgresUserService { return this.usersRepository.save(user); } - async updateCustomFields(itemId,data){ + async updateCustomFields(itemId, data) { let result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); let newResult; if (result.affected === 0) { - newResult = await this.fieldsValueRepository.save({ - itemId, - fieldId: data.fieldId, - value: data.value + newResult = await this.fieldsValueRepository.save({ + itemId, + fieldId: data.fieldId, + value: data.value }); - } + } Object.assign(result, newResult); return result; } async createUser(request: any, userCreateDto: UserCreateDto) { // It is considered that if user is not present in keycloak it is not present in database as well - let apiId='api.user.creatUser' + let apiId = 'api.user.creatUser' try { const decoded: any = jwt_decode(request.headers.authorization); - const userId =decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + const userId = decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; let cohortId = userCreateDto.cohortId; delete userCreateDto?.cohortId; userCreateDto.createdBy = userId @@ -181,11 +279,11 @@ export class PostgresUserService { let errKeycloak = ""; let resKeycloak = ""; - + const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) - if(checkUserinKeyCloakandDb){ + if (checkUserinKeyCloakandDb) { return new ErrorResponse({ errorCode: "400", errorMessage: "User Already Exists", @@ -202,31 +300,31 @@ export class PostgresUserService { } ); userCreateDto.userId = resKeycloak; - let result = await this.createUserInDatabase(request, userCreateDto,cohortId); + let result = await this.createUserInDatabase(request, userCreateDto, cohortId); let field_value_array = userCreateDto.fieldValues?.split("|"); let fieldData = {}; - if(result && field_value_array?.length > 0) { - let userId = result.userId; - for (let i = 0; i < field_value_array?.length; i++) { - let fieldValues = field_value_array[i].split(":"); - fieldData={ - fieldId:fieldValues[0], - value:fieldValues[1] - } - let result = await this.updateCustomFields(userId,fieldData); - if(!result) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: `Error is ${result}`, - }); + if (result && field_value_array?.length > 0) { + let userId = result.userId; + for (let i = 0; i < field_value_array?.length; i++) { + let fieldValues = field_value_array[i].split(":"); + fieldData = { + fieldId: fieldValues[0], + value: fieldValues[1] + } + let result = await this.updateCustomFields(userId, fieldData); + if (!result) { + return new ErrorResponse({ + errorCode: "500", + errorMessage: `Error is ${result}`, + }); + } } } - } - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: result, - }); + return new SuccessResponse({ + statusCode: 200, + message: "ok", + data: result, + }); } catch (e) { return new ErrorResponse({ errorCode: "500", @@ -235,58 +333,58 @@ export class PostgresUserService { } } -// Can be Implemeneted after we know what are the unique entties - async checkUserinKeyCloakandDb(userDto){ - const keycloakResponse = await getKeycloakAdminToken(); - const token = keycloakResponse.data.access_token; - const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( - userDto.username, - token - ); - if(usernameExistsInKeycloak.data.length > 0) { - return usernameExistsInKeycloak; - } - return false; + // Can be Implemeneted after we know what are the unique entties + async checkUserinKeyCloakandDb(userDto) { + const keycloakResponse = await getKeycloakAdminToken(); + const token = keycloakResponse.data.access_token; + const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( + userDto.username, + token + ); + if (usernameExistsInKeycloak.data.length > 0) { + return usernameExistsInKeycloak; + } + return false; } - async createUserInDatabase(request: any, userCreateDto: UserCreateDto,cohortId) { - const user = new User() - user.username=userCreateDto?.username - user.name=userCreateDto?.name - user.role=userCreateDto?.role - user.mobile= Number(userCreateDto?.mobile), - user.tenantId=userCreateDto?.tenantId - user.createdBy=userCreateDto?.createdBy - user.updatedBy=userCreateDto?.updatedBy - user.userId=userCreateDto?.userId, - user.state=userCreateDto?.state, - user.district=userCreateDto?.district, - user.address=userCreateDto?.address, - user.pincode=userCreateDto?.pincode - - if (userCreateDto?.dob) { - user.dob = new Date(userCreateDto.dob); + async createUserInDatabase(request: any, userCreateDto: UserCreateDto, cohortId) { + const user = new User() + user.username = userCreateDto?.username + user.name = userCreateDto?.name + user.role = userCreateDto?.role + user.mobile = Number(userCreateDto?.mobile), + user.tenantId = userCreateDto?.tenantId + user.createdBy = userCreateDto?.createdBy + user.updatedBy = userCreateDto?.updatedBy + user.userId = userCreateDto?.userId, + user.state = userCreateDto?.state, + user.district = userCreateDto?.district, + user.address = userCreateDto?.address, + user.pincode = userCreateDto?.pincode + + if (userCreateDto?.dob) { + user.dob = new Date(userCreateDto.dob); } - let result = await this.usersRepository.save(user); - if(result) { + let result = await this.usersRepository.save(user); + if (result) { let cohortData = { - userId:result?.userId, - role:result?.role, + userId: result?.userId, + role: result?.role, // createdBy:result?.userId, // updatedBy:result?.userId, - tenantId:result?.tenantId, - cohortId:cohortId + tenantId: result?.tenantId, + cohortId: cohortId } await this.addCohortMember(cohortData); - } - return result; + } + return result; } - async addCohortMember(cohortData){ + async addCohortMember(cohortData) { try { - let result = await this.cohortMemberRepository.insert(cohortData); - return result;; + let result = await this.cohortMemberRepository.insert(cohortData); + return result;; } catch (error) { console.log(error); throw new Error(error) @@ -410,8 +508,8 @@ export class PostgresUserService { } } - - + + diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index d0818c5a..2059553b 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -3,14 +3,16 @@ import { UserSearchDto } from "src/user/dto/user-search.dto"; import { UserDto } from "src/user/dto/user.dto"; export interface IServicelocator { - getUser( - userId?:Record, - response?: any, - tenantId?: string, - id?: any, - accessRole?: string, - request?: any, - ); + // getUser( + // userId?:Record, + // response?: any, + // tenantId?: string, + // id?: any, + // accessRole?: string, + // request?: any, + // ); + getUsersDetailsById(userData: Record, response:any); + getUsersDetailsByCohortId(userData: Record, response:any); updateUser(id?: string, request?: any, userDto?: any,response?: any); createUser(request: any, userDto: UserCreateDto); findUserDetails(userID:any,username:String) diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 7bf22d07..916e9471 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -10,6 +10,7 @@ import { Res, Patch, UseGuards, + Query, } from "@nestjs/common"; import { Request } from "@nestjs/common"; @@ -48,36 +49,45 @@ export class UserController { * * @since 1.6 */ - @Get("/:userid/:role") - @UseGuards(JwtAuthGuard) + @Get() @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) + @SerializeOptions({ strategy: "excludeAll", }) + @ApiHeader({ name: "tenantid", }) + @ApiQuery({ name: 'userid', description: 'The user ID (optional)', required: false, }) + @ApiQuery({ name: 'cohortid', description: 'The cohort ID (optional)', required: false, }) + @ApiQuery({ name: 'role', description: 'The role (optional)', required: false, }) + @ApiQuery({ name: 'fieldvalue', description: 'The field Value (optional)', required: false }) public async getUser( @Headers() headers, - @Param("userid") userId: string, - @Param("role") role: string, @Req() request: Request, - @Res() response: Response + @Res() response: Response, + @Query("userid") userId: string | null = null, + @Query("cohortid") cohortId: string | null = null, + @Query("role") role: string | null = null, + @Query("fieldvalue") fieldvalue: string | null = null ) { + // const tenantId = headers["tenantid"]; Can be Used In future - // Context and ContextType can be taked from .env later - let userData = { - userId: userId, + // Context and ContextType can be taken from .env later + let userData: any = { context: "USERS", - contextType: role, + userId: userId && typeof userId === 'string' && userId !== ',' && userId !== '{userid}' ? userId : null, + cohortId: cohortId && typeof cohortId === 'string' && cohortId !== ',' && cohortId !== '{cohortid}' ? cohortId : null, + contextType: role && typeof role === 'string' && role !== ',' && role !== '{role}' ? role : null, + fieldValue: fieldvalue && typeof fieldvalue === 'string' && fieldvalue !== ',' && fieldvalue !== '{fieldvalue}' ? fieldvalue : null }; - const result = await this.userAdapter.buildUserAdapter().getUser( - userData, - response - ); + let result; + if (userData.userId !== null) { + result = await this.userAdapter.buildUserAdapter().getUsersDetailsById( + userData, response); + } + if (userData.cohortId !== null) { + result = await this.userAdapter.buildUserAdapter().getUsersDetailsByCohortId( + userData, response); + } return response.status(result.statusCode).json(result); } From b044f9b208689e9cf548a00a90c55b6f1d039da4 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:37:38 +0530 Subject: [PATCH 195/408] chore : removed holiday module --- src/adapters/hasura/hasura.module.ts | 3 - src/adapters/hasura/holiday.adapter.ts | 290 ------------------------- src/adapters/holidayservicelocator.ts | 10 - src/app.module.ts | 1 - src/holiday/dto/holiday-search.dto.ts | 26 --- src/holiday/dto/holiday.dto.ts | 57 ----- src/holiday/holiday.controller.spec.ts | 18 -- src/holiday/holiday.controller.ts | 112 ---------- src/holiday/holiday.module.ts | 12 - src/holiday/holidayadapter.ts | 18 -- 10 files changed, 547 deletions(-) delete mode 100644 src/adapters/hasura/holiday.adapter.ts delete mode 100644 src/adapters/holidayservicelocator.ts delete mode 100644 src/holiday/dto/holiday-search.dto.ts delete mode 100644 src/holiday/dto/holiday.dto.ts delete mode 100644 src/holiday/holiday.controller.spec.ts delete mode 100644 src/holiday/holiday.controller.ts delete mode 100644 src/holiday/holiday.module.ts delete mode 100644 src/holiday/holidayadapter.ts diff --git a/src/adapters/hasura/hasura.module.ts b/src/adapters/hasura/hasura.module.ts index d6a4354a..f33e4be1 100644 --- a/src/adapters/hasura/hasura.module.ts +++ b/src/adapters/hasura/hasura.module.ts @@ -3,7 +3,6 @@ import { Module } from "@nestjs/common"; import { AttendanceHasuraService } from "./attendance.adapter"; import { HasuraCommentService } from "./comment.adapter"; import { HasuraConfigService } from "./config.adapter"; -import { HasuraHolidayService } from "./holiday.adapter"; import { HasuraLikeService } from "./like.adapter"; import { HasuraCohortService } from "./cohort.adapter"; import { HasuraCohortMembersService } from "./cohortMembers.adapter"; @@ -20,7 +19,6 @@ import { HasuraUserService } from "./user.adapter"; HasuraCommentService, HasuraConfigService, HasuraLikeService, - HasuraHolidayService, HasuraFieldsService, FieldsService, HasuraUserService, @@ -32,7 +30,6 @@ import { HasuraUserService } from "./user.adapter"; HasuraCommentService, HasuraConfigService, HasuraLikeService, - HasuraHolidayService, HasuraFieldsService, HasuraUserService, ], diff --git a/src/adapters/hasura/holiday.adapter.ts b/src/adapters/hasura/holiday.adapter.ts deleted file mode 100644 index 99d82637..00000000 --- a/src/adapters/hasura/holiday.adapter.ts +++ /dev/null @@ -1,290 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; - -import { IServicelocator } from "../holidayservicelocator"; -import { HolidayDto } from "src/holiday/dto/holiday.dto"; -import { HolidaySearchDto } from "src/holiday/dto/holiday-search.dto"; -export const HasuraHolidayToken = "HasuraHoliday"; -@Injectable() -export class HasuraHolidayService implements IServicelocator { - constructor(private httpService: HttpService) {} - - public async createHoliday(request: any, holidayDto: HolidayDto) { - var axios = require("axios"); - - const holidaySchema = new HolidayDto(holidayDto); - let query = ""; - Object.keys(holidayDto).forEach((e) => { - if ( - holidayDto[e] && - holidayDto[e] != "" && - Object.keys(holidaySchema).includes(e) - ) { - if (Array.isArray(holidayDto[e])) { - query += `${e}: ${JSON.stringify(holidayDto[e])}, `; - } else { - query += `${e}: "${holidayDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateHoliday { - insert_holiday_one(object: {${query}}) { - holidayId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_holiday_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateHoliday(id: string, request: any, holidayDto: HolidayDto) { - var axios = require("axios"); - - const holidaySchema = new HolidayDto(holidayDto); - let query = ""; - Object.keys(holidayDto).forEach((e) => { - if ( - holidayDto[e] && - holidayDto[e] != "" && - Object.keys(holidaySchema).includes(e) - ) { - if (Array.isArray(holidayDto[e])) { - query += `${e}: ${JSON.stringify(holidayDto[e])}, `; - } else { - query += `${e}: "${holidayDto[e]}", `; - } - } - }); - - var data = { - query: `mutation UpdateHoliday($holidayId:uuid) { - update_holiday(where: {holidayId: {_eq: $holidayId}}, _set: {${query}}) { - affected_rows - }}`, - variables: { - holidayId: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async getHoliday(holidayId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetHoliday($holidayId:uuid!) { - holiday_by_pk(holidayId: $holidayId) { - context - contextId - created_at - date - holidayId - remark - updated_at - year - } - } - `, - variables: { holidayId: holidayId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = [response.data.data.holiday_by_pk]; - const holidayData = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: holidayData[0], - }); - } - - public async searchHoliday(request: any, holidaySearchDto: HolidaySearchDto) { - var axios = require("axios"); - - let offset = 0; - if (holidaySearchDto.page > 1) { - offset = parseInt(holidaySearchDto.limit) * (holidaySearchDto.page - 1); - } - - let filters = holidaySearchDto.filters; - - Object.keys(holidaySearchDto.filters).forEach((item) => { - Object.keys(holidaySearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchHoliday($filters:holiday_bool_exp,$limit:Int, $offset:Int) { - holiday_aggregate { - aggregate { - count - } - } - holiday(where:$filters, limit: $limit, offset: $offset,) { - context - contextId - created_at - date - holidayId - remark - updated_at - year - } - }`, - variables: { - limit: parseInt(holidaySearchDto.limit), - offset: offset, - filters: holidaySearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.holiday; - const holidayData = await this.mappedResponse(result); - const count = response?.data?.data?.holiday_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: holidayData, - }); - } - - public async holidayFilter(fromDate: string, toDate: string, request: any) { - let axios = require("axios"); - - let searchData = { - fromDate, - toDate, - }; - - let query = `date:{_gte: "${searchData.fromDate}"}, _and: {date: {_lte: "${searchData.toDate}"}} `; - - var data = { - query: `query searchHoliday { - holiday_aggregate { - aggregate { - count - } - } - holiday( where: {${query}}) { - context - contextId - created_at - date - holidayId - remark - updated_at - year - } -}`, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.holiday; - const holidayData = await this.mappedResponse(result); - const count = response?.data?.data?.holiday_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: holidayData, - }); - } - - public async mappedResponse(result: any) { - const holidayResponse = result.map((item: any) => { - const holidayMapping = { - id: item?.holidayId ? `${item.holidayId}` : "", - holidayId: item?.holidayId ? `${item.holidayId}` : "", - date: item?.remark ? item.remark : "", - remark: item?.remark ? `${item.remark}` : "", - year: item?.year ? item.year : "", - context: item?.context ? `${item.context}` : "", - contextId: item?.contextId ? `${item.contextId}` : "", - createdAt: item?.created_at ? `${item.created_at}` : "", - updatedAt: item?.updated_at ? `${item.updated_at}` : "", - }; - return new HolidayDto(holidayMapping); - }); - - return holidayResponse; - } -} diff --git a/src/adapters/holidayservicelocator.ts b/src/adapters/holidayservicelocator.ts deleted file mode 100644 index e6b0e687..00000000 --- a/src/adapters/holidayservicelocator.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { HolidaySearchDto } from "src/holiday/dto/holiday-search.dto"; -import { HolidayDto } from "src/holiday/dto/holiday.dto"; - -export interface IServicelocator { - getHoliday(holidayId: string, request: any); - createHoliday(request: any, holidayDto: HolidayDto); - updateHoliday(holidayId: string, request: any, holidayDto: HolidayDto); - searchHoliday(request: any, holidaySearchDto: HolidaySearchDto); - holidayFilter(fromDate: string, toDate: string, request: any); -} diff --git a/src/app.module.ts b/src/app.module.ts index f5c7dfaf..58cb811d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -6,7 +6,6 @@ import { AppService } from "./app.service"; // Below modules not in use for Shiksha 2.0 /* -import { HolidayModule } from "./holiday/holiday.module"; import { ConfigurationModule } from "./configs/configuration.module"; import { WorksheetModule } from "./worksheet/worksheet.module"; import { QuestionModule } from "./Question/question.module"; diff --git a/src/holiday/dto/holiday-search.dto.ts b/src/holiday/dto/holiday-search.dto.ts deleted file mode 100644 index c8ffbe39..00000000 --- a/src/holiday/dto/holiday-search.dto.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class HolidaySearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Number, - description: "Page", - }) - page: number; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/holiday/dto/holiday.dto.ts b/src/holiday/dto/holiday.dto.ts deleted file mode 100644 index 344f42a7..00000000 --- a/src/holiday/dto/holiday.dto.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class HolidayDto { - @Expose() - id: string; - - @Expose() - holidayId: string; - - @ApiProperty({ - type: String, - description: "The date of the holiday", - default: `eg. ${new Date().toISOString().split("T")[0]}`, - }) - @Expose() - date: Date; - - @ApiProperty({ - type: String, - description: "The remark of the holiday", - }) - @Expose() - remark: string; - - @ApiProperty({ - type: String, - description: "The year of the holiday", - default: `eg. ${new Date().toISOString().split("T")[0]}`, - }) - @Expose() - year: Date; - - @ApiProperty({ - type: String, - description: "The context of the holiday", - }) - @Expose() - context: string; - - @ApiProperty({ - type: String, - description: "The context id of the holiday", - }) - @Expose() - contextId: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/holiday/holiday.controller.spec.ts b/src/holiday/holiday.controller.spec.ts deleted file mode 100644 index d7734f6d..00000000 --- a/src/holiday/holiday.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from "@nestjs/testing"; -import { HolidayController } from "./holiday.controller"; - -describe("HolidayController", () => { - let controller: HolidayController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [HolidayController], - }).compile(); - - controller = module.get(HolidayController); - }); - - it("should be defined", () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/holiday/holiday.controller.ts b/src/holiday/holiday.controller.ts deleted file mode 100644 index f5e03c84..00000000 --- a/src/holiday/holiday.controller.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Query, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, - ApiExcludeController, -} from "@nestjs/swagger"; -import { HolidayDto } from "./dto/holiday.dto"; -import { HolidaySearchDto } from "./dto/holiday-search.dto"; -import { Request } from "@nestjs/common"; -import { HolidayAdapter } from "./holidayadapter"; -// @ApiTags("Holiday") - -@ApiExcludeController() -@Controller("holiday") -export class HolidayController { - constructor(private holidayProvider: HolidayAdapter) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Holiday detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getHolidays(@Param("id") holidayId: string, @Req() request: Request) { - return this.holidayProvider - .buildHolidayAdapter() - .getHoliday(holidayId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Holiday has been created successfully." }) - // @ApiBody({ type: HolidayDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createHoliday( - @Req() request: Request, - @Body() holidayDto: HolidayDto - ) { - return await this.holidayProvider - .buildHolidayAdapter() - .createHoliday(request, holidayDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Holiday has been updated successfully." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateHoliday( - @Param("id") holidayId: string, - @Req() request: Request, - @Body() holidayDto: HolidayDto - ) { - return await this.holidayProvider - .buildHolidayAdapter() - .updateHoliday(holidayId, request, holidayDto); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Holiday list." }) - // @ApiBody({ type: HolidaySearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchHoliday( - @Req() request: Request, - @Body() holidaySearchDto: HolidaySearchDto - ) { - return await this.holidayProvider - .buildHolidayAdapter() - .searchHoliday(request, holidaySearchDto); - } - - @Get("") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "fromDate" }) - @ApiQuery({ name: "toDate" }) - public async holidayFilter( - @Query("fromDate") date: string, - @Query("toDate") toDate: string, - @Req() request: Request - ) { - return await this.holidayProvider - .buildHolidayAdapter() - .holidayFilter(date, toDate, request); - } -} diff --git a/src/holiday/holiday.module.ts b/src/holiday/holiday.module.ts deleted file mode 100644 index a6bb8b57..00000000 --- a/src/holiday/holiday.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { CacheModule, Module } from "@nestjs/common"; -import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { HolidayController } from "./holiday.controller"; -import { HolidayAdapter } from "./holidayadapter"; - -@Module({ - imports: [HasuraModule, HttpModule], - controllers: [HolidayController], - providers: [HolidayAdapter], -}) -export class HolidayModule {} diff --git a/src/holiday/holidayadapter.ts b/src/holiday/holidayadapter.ts deleted file mode 100644 index c81f7cd8..00000000 --- a/src/holiday/holidayadapter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HasuraHolidayService } from "src/adapters/hasura/holiday.adapter"; -import { IServicelocator } from "src/adapters/holidayservicelocator"; - -@Injectable() -export class HolidayAdapter { - constructor(private hasuraProvider: HasuraHolidayService) {} - buildHolidayAdapter(): IServicelocator { - let adapter: IServicelocator; - - switch (process.env.ADAPTERSOURCE) { - case "hasura": - adapter = this.hasuraProvider; - break; - } - return adapter; - } -} From 9d92c608de362fcd9d9758fc4a39330a149ad193 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:39:50 +0530 Subject: [PATCH 196/408] chore : removed worksheet module --- src/adapters/hasura/worksheet.adapter.ts | 611 ---------------------- src/app.module.ts | 1 - src/worksheet/dto/worksheet-search.dto.ts | 25 - src/worksheet/dto/worksheet.dto.ts | 169 ------ src/worksheet/worksheet.controller.ts | 142 ----- src/worksheet/worksheet.module.ts | 11 - 6 files changed, 959 deletions(-) delete mode 100644 src/adapters/hasura/worksheet.adapter.ts delete mode 100644 src/worksheet/dto/worksheet-search.dto.ts delete mode 100644 src/worksheet/dto/worksheet.dto.ts delete mode 100644 src/worksheet/worksheet.controller.ts delete mode 100644 src/worksheet/worksheet.module.ts diff --git a/src/adapters/hasura/worksheet.adapter.ts b/src/adapters/hasura/worksheet.adapter.ts deleted file mode 100644 index b04c678e..00000000 --- a/src/adapters/hasura/worksheet.adapter.ts +++ /dev/null @@ -1,611 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { WorksheetDto } from "src/worksheet/dto/worksheet.dto"; -import { WorksheetSearchDto } from "src/worksheet/dto/worksheet-search.dto"; -import { ErrorResponse } from "src/error-response"; - -@Injectable() -export class WorksheetService { - constructor(private httpService: HttpService) {} - questionurl = process.env.DIKSHADEVBASEAPIURL; - templateurl = process.env.TEMPLATERURL; - url = `${process.env.BASEAPIURL}`; - public async createWorksheet(request: any, worksheetDto: WorksheetDto) { - var axios = require("axios"); - const worksheetSchema = new WorksheetDto(worksheetDto); - let query = ""; - Object.keys(worksheetDto).forEach((e) => { - if ( - worksheetDto[e] && - worksheetDto[e] != "" && - Object.keys(worksheetSchema).includes(e) - ) { - if (Array.isArray(worksheetDto[e])) { - query += `${e}: ${JSON.stringify(worksheetDto[e])}, `; - } else { - query += `${e}: "${worksheetDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateWorksheet { - insert_worksheet_one(object: {${query}}) { - worksheetId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_worksheet_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateWorksheet( - id: string, - request: any, - worksheetDto: WorksheetDto - ) { - var axios = require("axios"); - const worksheetSchema = new WorksheetDto(worksheetDto); - let query = ""; - Object.keys(worksheetDto).forEach((e) => { - if ( - worksheetDto[e] && - worksheetDto[e] != "" && - Object.keys(worksheetSchema).includes(e) - ) { - if (Array.isArray(worksheetDto[e])) { - query += `${e}: ${JSON.stringify(worksheetDto[e])}, `; - } else { - query += `${e}: ${worksheetDto[e]}, `; - } - } - }); - - var data = { - query: `mutation UpdateWorksheet($worksheetId:uuid) { - update_worksheet(where: {worksheetId: {_eq: $worksheetId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - worksheetId: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async getWorksheet(worksheetId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetWorksheet($worksheetId:uuid!) { - worksheet_by_pk(worksheetId: $worksheetId) { - created_at - feedback - criteria - grade - hints - instructions - level - name - navigationMode - outcomeDeclaration - outcomeProcessing - purpose - questionSetType - questionSets - questions - qumlVersion - showHints - source - state - subject - timeLimits - topic - updated_at - usedFor - visibility - worksheetId - } - } - `, - variables: { worksheetId: worksheetId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - let result = [response.data.data.worksheet_by_pk]; - const worksheetResponse = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: worksheetResponse[0], - }); - } - - public async searchWorksheet( - worksheetSearchDto: WorksheetSearchDto, - request: any - ) { - var axios = require("axios"); - - let offset = 0; - if (worksheetSearchDto.page > 1) { - offset = - parseInt(worksheetSearchDto.limit) * (worksheetSearchDto.page - 1); - } - - let filters = worksheetSearchDto.filters; - - Object.keys(worksheetSearchDto.filters).forEach((item) => { - Object.keys(worksheetSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - - var data = { - query: `query SearchWorksheet($filters:worksheet_bool_exp,$limit:Int, $offset:Int) { - worksheet_aggregate { - aggregate { - count - } - } - worksheet(where:$filters, limit: $limit, offset: $offset,) { - created_at - feedback - criteria - grade - hints - instructions - level - name - navigationMode - outcomeDeclaration - outcomeProcessing - purpose - questionSetType - questionSets - questions - qumlVersion - showHints - source - state - subject - timeLimits - topic - updated_at - usedFor - visibility - worksheetId - } - }`, - variables: { - limit: parseInt(worksheetSearchDto.limit), - offset: offset, - filters: worksheetSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.worksheet; - const worksheetResponse = await this.mappedResponse(result); - const count = response?.data?.data?.worksheet_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: worksheetResponse, - }); - } - - public async downloadWorksheet( - worksheetId: any, - templateId: any, - request: any - ) { - var axios = require("axios"); - var template_id = parseInt(templateId); - - const templateDetail = await axios.get( - `${this.templateurl}${template_id}`, - { - headers: { - Authorization: request.headers.authorization, - }, - } - ); - - const templateData = templateDetail.data; - var templateTags = templateData.tag; - - var worksheetData = { - query: `query GetWorksheet($worksheetId:uuid) { - worksheet(where: {worksheetId: {_eq: $worksheetId}}) { - created_at - feedback - criteria - grade - hints - instructions - level - name - navigationMode - outcomeDeclaration - outcomeProcessing - purpose - questionSetType - questionSets - questions - qumlVersion - showHints - source - state - subject - timeLimits - topic - updated_at - usedFor - visibility - worksheetId - } - } - `, - variables: { worksheetId: worksheetId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: worksheetData, - }; - - const response = await axios(config); - - let resData = response.data.data.worksheet[0]; - - let questionIds = resData.questions; - - let questionsArray = []; - - for (let value of questionIds) { - let qData = { - method: "get", - url: `${this.questionurl}/question/v1/read/${value}?fields=body`, - }; - const response = await axios(qData); - const data = response?.data; - const final = data.result.question; - - if (templateTags.includes("with_answers")) { - questionsArray.push( - "
  • " + final.body + "
    Ans -


  • " - ); - } else { - questionsArray.push("
  • " + final.body + "
  • "); - } - } - - var data = { - config_id: 1, - data: { - title: resData.name, - grade: resData.grade, - subject: resData.subject, - questions: questionsArray, - }, - template_id: template_id, - }; - - const pdf = await axios.post( - `http://68.183.94.187:8000/generate/?plugin=pdf`, - data, - { - headers: { - "Content-Type": "application/json", - }, - } - ); - - const pdfUrl = pdf.data; - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: pdfUrl, - }); - } - - public async mappedResponse(result: any) { - const worksheetResponse = result.map((item: any) => { - const worksheetMapping = { - id: item?.worksheetId ? `${item.worksheetId}` : "", - worksheetId: item?.worksheetId ? `${item.worksheetId}` : "", - name: item?.name ? `${item.name}` : "", - state: item?.state ? `${item.state}` : "", - subject: item?.subject ? `${item.subject}` : "", - grade: item?.grade ? `${item.grade}` : "", - level: item?.level ? `${item.level}` : "", - instructions: item?.instructions ? `${item.instructions}` : "", - feedback: item?.feedback ? `${item.feedback}` : "", - hints: item?.hints ? `${item.hints}` : "", - navigationMode: item?.navigationMode ? `${item.navigationMode}` : "", - timeLimits: item?.timeLimits ? `${item.timeLimits}` : "", - showHints: item?.showHints ? item.showHints : "", - questions: item?.questions ? item.questions : "", - questionSets: item?.questionSets ? `${item.questionSets}` : "", - outcomeDeclaration: item?.outcomeDeclaration - ? `${item.outcomeDeclaration}` - : "", - outcomeProcessing: item?.outcomeProcessing - ? `${item.outcomeProcessing}` - : "", - questionSetType: item?.questionSetType ? `${item.questionSetType}` : "", - criteria: item?.criteria ? `${item.criteria}` : "", - usedFor: item?.usedFor ? `${item.usedFor}` : "", - purpose: item?.purpose ? `${item.purpose}` : "", - visibility: item?.visibility ? `${item.visibility}` : "", - qumlVersion: item?.qumlVersion ? `${item.qumlVersion}` : "", - topic: item?.topic ? item.topic : "", - source: item?.source ? `${item.source}` : "", - createdAt: item?.created_at ? `${item.created_at}` : "", - updatedAt: item?.updated_at ? `${item.updated_at}` : "", - }; - return new WorksheetDto(worksheetMapping); - }); - - return worksheetResponse; - } - - public async sendWorksheet( - studentIds: [string], - teacherId: string, - templateId: string, - link: string, - subject: string, - topic: string, - request: any - ) { - var axios = require("axios"); - const teacherResponse = await axios.get(`${this.url}User/${teacherId}`); - const teacher = teacherResponse.data; - const templateDetail = await axios.get(`${this.templateurl}${templateId}`); - const templateData = templateDetail.data; - - var getSchool = { - query: `query GetSchool($schoolId:uuid!) { - school_by_pk(schoolId: $schoolId) { - schoolName - } -}`, - variables: { - schoolId: teacher.schoolId, - }, - }; - - var schoolCall = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: getSchool, - }; - - const schoolResponse = await axios(schoolCall); - - let schoolData = schoolResponse?.data?.data?.school_by_pk; - studentIds.map(async (studentId) => { - const student = await axios.get(`${this.url}Student/${studentId}`); - - const process = { - id: parseInt(templateId), - data: { - studentName: - (student?.data?.firstName ? student?.data?.firstName : "") + - " " + - (student?.data?.lastName ? student?.data?.lastName : ""), - subject: subject, - topic: topic, - teacherName: - (teacher?.firstName ? teacher?.firstName : "") + - " " + - (teacher?.lastName ? teacher?.lastName : ""), - schoolName: schoolData.schoolName, - link: link, - }, - }; - - var templateCall = { - method: "post", - url: `${this.templateurl}process`, - headers: { - Authorization: request.headers.authorization, - }, - data: process, - }; - const responseData = await axios(templateCall); - - const templateDataResponse = responseData.data; - var data = { - adapterId: templateData.user, - to: { - userID: student.data.studentPhoneNumber, - deviceType: "PHONE", - }, - payload: { - text: templateDataResponse.processed, - }, - }; - - var smsSend = { - method: "post", - url: "http://143.110.255.220:9090/message/send", - headers: { - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(smsSend); - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: response.data, - }); - }); - } - - public async StudentMappedResponse(result: any) { - const studentResponse = result.map((item: any) => { - const studentMapping = { - studentId: item?.osid ? `${item.osid}` : "", - refId1: item?.admissionNo ? `${item.admissionNo}` : "", - refId2: item?.refId2 ? `${item.refId2}` : "", - aadhaar: item?.aadhaar ? `${item.aadhaar}` : "", - firstName: item?.firstName ? `${item.firstName}` : "", - middleName: item?.middleName ? `${item.middleName}` : "", - lastName: item?.lastName ? `${item.lastName}` : "", - groupId: item?.groupId ? `${item.groupId}` : "", - schoolId: item?.schoolId ? `${item.schoolId}` : "", - studentEmail: item?.studentEmail ? `${item.studentEmail}` : "", - studentPhoneNumber: item?.studentPhoneNumber - ? item.studentPhoneNumber - : "", - iscwsn: item?.iscwsn ? `${item.iscwsn}` : "", - gender: item?.gender ? `${item.gender}` : "", - socialCategory: item?.socialCategory ? `${item.socialCategory}` : "", - religion: item?.religion ? `${item.religion}` : "", - singleGirl: item?.singleGirl ? item.singleGirl : "", - weight: item?.weight ? `${item.weight}` : "", - height: item?.height ? `${item.height}` : "", - bloodGroup: item?.bloodGroup ? `${item.bloodGroup}` : "", - birthDate: item?.birthDate ? `${item.birthDate}` : "", - homeless: item?.homeless ? item.homeless : "", - bpl: item?.bpl ? item.bpl : "", - migrant: item?.migrant ? item.migrant : "", - status: item?.status ? `${item.status}` : "", - - fatherFirstName: item?.fatherFirstName ? `${item.fatherFirstName}` : "", - - fatherMiddleName: item?.fatherMiddleName - ? `${item.fatherMiddleName}` - : "", - - fatherLastName: item?.fatherLastName ? `${item.fatherLastName}` : "", - fatherPhoneNumber: item?.fatherPhoneNumber - ? item.fatherPhoneNumber - : "", - fatherEmail: item?.fatherEmail ? `${item.fatherEmail}` : "", - - motherFirstName: item?.motherFirstName ? `${item.motherFirstName}` : "", - motherMiddleName: item?.motherMiddleName - ? `${item.motherMiddleName}` - : "", - motherLastName: item?.motherLastName ? `${item.motherLastName}` : "", - motherPhoneNumber: item?.motherPhoneNumber - ? item.motherPhoneNumber - : "", - motherEmail: item?.motherEmail ? `${item.motherEmail}` : "", - - guardianFirstName: item?.guardianFirstName - ? `${item.guardianFirstName}` - : "", - guardianMiddleName: item?.guardianMiddleName - ? `${item.guardianMiddleName}` - : "", - guardianLastName: item?.guardianLastName - ? `${item.guardianLastName}` - : "", - guardianPhoneNumber: item?.guardianPhoneNumber - ? item.guardianPhoneNumber - : "", - guardianEmail: item?.guardianEmail ? `${item.guardianEmail}` : "", - image: item?.image ? `${item.image}` : "", - deactivationReason: item?.deactivationReason - ? `${item.deactivationReason}` - : "", - studentAddress: item?.studentAddress ? `${item.studentAddress}` : "", - village: item?.village ? `${item.village}` : "", - block: item?.block ? `${item.block}` : "", - district: item?.district ? `${item.district}` : "", - stateId: item?.stateId ? `${item.stateId}` : "", - pincode: item?.pincode ? item.pincode : "", - locationId: item?.locationId ? `${item.locationId}` : "", - metaData: item?.metaData ? item.metaData : [], - createdAt: item?.osCreatedAt ? `${item.osCreatedAt}` : "", - updatedAt: item?.osUpdatedAt ? `${item.osUpdatedAt}` : "", - createdBy: item?.osCreatedBy ? `${item.osCreatedBy}` : "", - updatedBy: item?.osUpdatedBy ? `${item.osUpdatedBy}` : "", - }; - return studentMapping; - }); - - return studentResponse; - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 58cb811d..9ef9fe1a 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { WorksheetModule } from "./worksheet/worksheet.module"; import { QuestionModule } from "./Question/question.module"; import { LikeModule } from "./like/like.module"; import { CommentModule } from "./comment/comment.module"; diff --git a/src/worksheet/dto/worksheet-search.dto.ts b/src/worksheet/dto/worksheet-search.dto.ts deleted file mode 100644 index ee2fdf8d..00000000 --- a/src/worksheet/dto/worksheet-search.dto.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class WorksheetSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Number, - description: "Page", - }) - page: number; - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/worksheet/dto/worksheet.dto.ts b/src/worksheet/dto/worksheet.dto.ts deleted file mode 100644 index 196cd1cd..00000000 --- a/src/worksheet/dto/worksheet.dto.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { ApiProperty } from "@nestjs/swagger"; -import { Expose } from "class-transformer"; - -export class WorksheetDto { - @Expose() - id: string; - - @Expose() - worksheetId: string; - - @ApiProperty({ - description: - "Instructions on how to understand, attempt or how the question set will be evaluated.", - }) - @Expose() - name: string; - - @ApiProperty({ - description: "Worksheet Title", - }) - @Expose() - state: string; - @ApiProperty({ - description: "Worksheet state", - }) - @Expose() - subject: string; - @ApiProperty({ - description: "Worksheet subject", - }) - @Expose() - grade: string; - @ApiProperty({ - description: "Worksheet grade level", - }) - @Expose() - level: string; - @ApiProperty({ - description: "Worksheet level", - }) - @Expose() - instructions: string; - - @ApiProperty({ - description: "Feedback shown to the students after outcome processing.", - }) - @Expose() - feedback: any; - - @ApiProperty({ - description: - "Hints are shown to the students after outcome processing or when the student requests for hints.", - }) - @Expose() - hints: any; - - @ApiProperty({ - description: - "Determines the general paths that the student may take during the test session. Applicable only when questions data is present.", - }) - @Expose() - navigationMode: string; - - @ApiProperty({ - description: - "Time limits for the complete set and/or for each question in the question set.", - }) - @Expose() - timeLimits: string; - - @ApiProperty({ - description: - "Configuration to enable/disable hints for the student while using the question set.", - }) - @Expose() - showHints: string; - - @ApiProperty({ - description: " learning outcome", - }) - @Expose() - questions: [string]; - - @ApiProperty({ - description: "Question Sets associated with the current set.", - }) - @Expose() - questionSets: any; - - @ApiProperty({ - description: - "Information about the outcome variables of the question set, i.e the values that are output of a question set session.", - }) - @Expose() - outcomeDeclaration: any; - - @ApiProperty({ - description: - "Rules to assign values to outcome variables based on the student's reponses.", - }) - @Expose() - outcomeProcessing: any; - - @ApiProperty({ - description: - "A question set can be comprised of a materialized list of questions, or can also be dynamically built at runtime by using a criteria to select member questions.", - }) - @Expose() - questionSetType: string; - - @ApiProperty({ - description: "Criteria to be used when the set type is dynamic.", - }) - @Expose() - criteria: string; - - @ApiProperty({ - description: " ", - }) - @Expose() - usedFor: string; - - @ApiProperty({ - description: "Purpose served by the question.", - }) - @Expose() - purpose: string; - - @ApiProperty({ - description: "Visibility of the question set.", - }) - @Expose() - visibility: string; - - @ApiProperty({ - description: - "Version of the QuML specification using which the question set is created.", - }) - @Expose() - qumlVersion: string; - - @ApiProperty({ - description: "Array of topic.", - }) - @Expose() - topic: [string]; - - @ApiProperty({ - description: "source of worksheet", - }) - @Expose() - source: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/worksheet/worksheet.controller.ts b/src/worksheet/worksheet.controller.ts deleted file mode 100644 index 357b4ed3..00000000 --- a/src/worksheet/worksheet.controller.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { - ApiBasicAuth, - ApiBody, - ApiCreatedResponse, - ApiExcludeController, - ApiForbiddenResponse, - ApiOkResponse, - ApiQuery, - ApiTags, -} from "@nestjs/swagger"; -import { - Body, - ClassSerializerInterceptor, - Controller, - Get, - Param, - Query, - Post, - Put, - Req, - SerializeOptions, - UseInterceptors, - Request, -} from "@nestjs/common"; -import { WorksheetService } from "src/adapters/hasura/worksheet.adapter"; -import { WorksheetDto } from "./dto/worksheet.dto"; -import { WorksheetSearchDto } from "./dto/worksheet-search.dto"; - -// @ApiTags("Worksheet") -@ApiExcludeController() -@Controller("worksheet") -export class WorksheetController { - constructor(private service: WorksheetService) {} - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Worksheet has been created successfully.", - // }) - // @ApiBody({ type: WorksheetDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createWorksheet( - @Req() request: Request, - @Body() worksheetDto: WorksheetDto - ) { - return this.service.createWorksheet(request, worksheetDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Worksheet has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateWorksheet( - @Param("id") id: string, - @Req() request: Request, - @Body() worksheetDto: WorksheetDto - ) { - return await this.service.updateWorksheet(id, request, worksheetDto); - } - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Worksheet detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getWorksheet( - @Param("id") worksheetId: string, - @Req() request: Request - ) { - return this.service.getWorksheet(worksheetId, request); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Worksheet list." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchWorksheet( - @Body() worksheetSearchDto: WorksheetSearchDto, - @Req() request: Request - ) { - return await this.service.searchWorksheet(worksheetSearchDto, request); - } - - @Post(":worksheet/pdf") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: " Ok." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "worksheetId", required: true }) - // @ApiQuery({ name: "templateId", required: true }) - public async getWorksheetPdf( - @Query("worksheetId") worksheetId: string, - @Query("templateId") templateId: number, - @Req() request: Request - ) { - return this.service.downloadWorksheet(worksheetId, templateId, request); - } - - @Post("/share") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: " Ok." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "studentIds", required: true }) - // @ApiQuery({ name: "teacherId", required: true }) - // @ApiQuery({ name: "templateId", required: true }) - // @ApiQuery({ name: "link", required: true }) - // @ApiQuery({ name: "subject", required: true }) - // @ApiQuery({ name: "topic", required: true }) - public async sendWorksheet( - @Query("studentIds") studentIds: [string], - @Query("teacherId") teacherId: string, - @Query("templateId") templateId: string, - @Query("link") link: string, - @Query("subject") subject: string, - @Query("topic") topic: string, - - @Req() - request: Request - ) { - return this.service.sendWorksheet( - studentIds, - teacherId, - templateId, - link, - subject, - topic, - request - ); - } -} diff --git a/src/worksheet/worksheet.module.ts b/src/worksheet/worksheet.module.ts deleted file mode 100644 index ee17258b..00000000 --- a/src/worksheet/worksheet.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CacheModule, Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { WorksheetController } from "./worksheet.controller"; -import { WorksheetService } from "src/adapters/hasura/worksheet.adapter"; - -@Module({ - imports: [HttpModule], - controllers: [WorksheetController], - providers: [WorksheetService], -}) -export class WorksheetModule {} From 87bb96d41316f4d75181c7bb643057ab802f4eb1 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:43:28 +0530 Subject: [PATCH 197/408] chore : removed question module --- src/Question/dto/question.dto.ts | 248 ------------ src/Question/dto/question.search.dto.ts | 20 - src/Question/question.controller.ts | 310 -------------- src/Question/question.module.ts | 22 - src/adapters/diksha/quml.adapter.ts | 511 ------------------------ src/adapters/hasura/question.adapter.ts | 464 --------------------- src/app.module.ts | 1 - 7 files changed, 1576 deletions(-) delete mode 100644 src/Question/dto/question.dto.ts delete mode 100644 src/Question/dto/question.search.dto.ts delete mode 100644 src/Question/question.controller.ts delete mode 100644 src/Question/question.module.ts delete mode 100644 src/adapters/diksha/quml.adapter.ts delete mode 100644 src/adapters/hasura/question.adapter.ts diff --git a/src/Question/dto/question.dto.ts b/src/Question/dto/question.dto.ts deleted file mode 100644 index 1a1c73ae..00000000 --- a/src/Question/dto/question.dto.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { ApiProperty } from "@nestjs/swagger"; -import { Exclude, Expose } from "class-transformer"; - -export class QuestionDto { - @Expose() - examQuestionId: string; - - @ApiProperty({ - description: - "Body contains the text, graphics, media objects and interactions that describe the question’s content.", - }) - @Expose() - body: string; - - @ApiProperty({ - description: - "Instructions on how to understand, attempt or how the question will be evaluated.", - }) - @Expose() - instructions: string; - - @ApiProperty({ - description: "Feedback shown to the students after response processing.", - }) - @Expose() - feedback: [string]; - - @ApiProperty({ - description: - "Hints are shown to the students after response processing or when the student requests for hints.", - }) - @Expose() - hints: [string]; - - @ApiProperty({ - description: "options of question.", - }) - @Expose() - options: [string]; - - @ApiProperty({ - description: "List of media used in the question", - }) - @Expose() - media: [string]; - - @ApiProperty({ - description: - "Information about answer to the question, when it is correct and optionally, how it is scored.", - }) - @Expose() - responseDeclaration: [string]; - - @ApiProperty({ - description: - "Information about the outcome variables of the question, i.e the values that are output of a question session.", - }) - @Expose() - outcomeDeclaration: [string]; - - @ApiProperty({ - description: - "Declaration of template variables that are to used for the purposes of cloning questions, i.e. auto-generating different sets of values for variables in the question.", - }) - @Expose() - templateDeclaration: [string]; - - @ApiProperty({ - description: - "One or more template rules to assign values to the template variables.", - }) - @Expose() - templateProcessing: [string]; - - @ApiProperty({ - description: - "Rules to assign values to outcome variables based on the student's reponses.", - }) - @Expose() - responseProcessing: [string]; - - @ApiProperty({ - description: "Cognitive processes involved to answer the question.", - }) - @Expose() - bloomsLevel: [string]; - - @ApiProperty({ - description: "Difficulty level of the question.", - }) - @Expose() - qlevel: [string]; - - @ApiProperty({ - description: "Purpose served by the question.", - }) - @Expose() - purpose: string; - - @ApiProperty({ - description: "Expected time for one attempt of the question.", - }) - @Expose() - expectedDuration: number; - - @ApiProperty({ - description: "Maximum score that can be awarded for the question.", - }) - @Expose() - maxScore: number; - - @ApiProperty({ - description: - "One of the standard question types - mcq, mtf, ftb, mmcq, essay, short answers, programming, other. this can be auto-derived based on the interactions used in the question.", - }) - @Expose() - type: string; - - @ApiProperty({ - description: - "If the question is visible for all or only for those who created it and/or for some specific systems or use cases.", - }) - @Expose() - visibility: string; - - @ApiProperty({ - description: - "Set to true if question data has template variables and template processing, else it is set to false.", - }) - @Expose() - isTemplate: boolean; - - @ApiProperty({ - description: "List of interactions present in the question.", - }) - @Expose() - interactions: [string]; - - @ApiProperty({ - description: "true, if question data has solutions, else, set to false", - }) - @Expose() - solutionAvailable: boolean; - - @ApiProperty({ - description: - "One of the values: responseProcessing (if question has inbuild response processing), offline (if scoring will be done offline and/or manually) or external (if an external system does the evaluation and submit the score).", - }) - @Expose() - scoringMode: string; - - @ApiProperty({ - description: - "Version of the QuML specification using which the question is created.", - }) - @Expose() - qumlVersion: string; - - @ApiProperty({ - description: - "Total cumulative time spent, in milliseconds, on the question by all users.", - }) - @Expose() - totalTimeSpent: number; - - @ApiProperty({ - description: "Average time spent per attempt, in milliseconds.", - }) - @Expose() - avgTimeSpent: number; - - @ApiProperty({ - description: "total number of attempts.", - }) - @Expose() - numAttempts: number; - - @ApiProperty({ - description: "Number of attempts where the user response is correct.", - }) - @Expose() - numCorrectAttempts: number; - - @ApiProperty({ - description: "Number of attempts where the user response is in-correct.", - }) - @Expose() - numInCorrectAttempts: number; - - @ApiProperty({ - description: - "Total number of attempts where the user did not give a response.", - }) - @Expose() - numSkips: number; - - @ApiProperty({ - description: "Average rating of the question.", - }) - @Expose() - avgRating: number; - - @ApiProperty({ - description: "Total number of ratings given for the question.", - }) - @Expose() - totalRatings: number; - - @ApiProperty({}) - @Expose() - topic: string; - - @ApiProperty({}) - @Expose() - subject: string; - - @ApiProperty({}) - @Expose() - class: string; - - @ApiProperty({}) - @Expose() - questionId: string; - - @ApiProperty({}) - @Expose() - language: string; - - @ApiProperty({}) - @Expose() - compatibilityLevel: string; - - @ApiProperty({}) - @Expose() - learningOutcome: string; - - @ApiProperty({}) - @Expose() - source: string; - - @ApiProperty({}) - @Expose() - answer: string; - - constructor(obj: QuestionDto) { - Object.assign(this, obj); - } -} diff --git a/src/Question/dto/question.search.dto.ts b/src/Question/dto/question.search.dto.ts deleted file mode 100644 index 70bcdcdd..00000000 --- a/src/Question/dto/question.search.dto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class QuestionSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/Question/question.controller.ts b/src/Question/question.controller.ts deleted file mode 100644 index ac9fe940..00000000 --- a/src/Question/question.controller.ts +++ /dev/null @@ -1,310 +0,0 @@ -import { - ApiBasicAuth, - ApiBody, - ApiCreatedResponse, - ApiExcludeController, - ApiForbiddenResponse, - ApiOkResponse, - ApiQuery, - ApiTags, -} from "@nestjs/swagger"; -import { - ClassSerializerInterceptor, - Controller, - Get, - UseInterceptors, - Query, - Param, - Req, - Request, - Inject, - Post, - SerializeOptions, - Body, - Put, -} from "@nestjs/common"; -import { - DikshaQuestionToken, - QumlQuestionService, -} from "src/adapters/diksha/quml.adapter"; -import { IServicelocator } from "src/adapters/questionservicelocator"; -import { QuestionDto } from "./dto/question.dto"; -import { HasuraQuestionToken } from "src/adapters/hasura/question.adapter"; - -// @ApiTags("Question") -@ApiExcludeController() -@Controller("question") -export class QuestionController { - constructor( - @Inject(DikshaQuestionToken) private dikshaProvider: IServicelocator, - - @Inject(HasuraQuestionToken) - private hasuraProvider: IServicelocator - ) {} - - @Get(":adapter/search") - @UseInterceptors(ClassSerializerInterceptor) - //@ApiBasicAuth("access-token") - // @ApiOkResponse({ description: "Get all Questions detail." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "questionType", required: false }) - // @ApiQuery({ name: "subject", required: false }) - // @ApiQuery({ name: "limit", required: false }) - // @ApiQuery({ name: "language", required: false }) - // @ApiQuery({ name: "medium", required: false }) - // @ApiQuery({ name: "bloomsLevel", required: false }) - // @ApiQuery({ name: "topic", required: false }) - // @ApiQuery({ name: "className", required: false }) - public async getAllQuestions( - @Param("adapter") adapter: string, - @Query("questionType") questionType: string, - @Query("subject") subject: [string], - @Query("limit") limit: string, - @Query("language") language: string, - @Query("medium") medium: string, - @Query("bloomsLevel") bloomsLevel: [string], - @Query("topic") topic: [string], - @Query("className") className: [string], - @Req() request: Request - ) { - if (adapter === "diksha") { - return this.dikshaProvider.getAllQuestions( - questionType, - subject, - limit, - language, - medium, - bloomsLevel, - topic, - className, - request - ); - } - } - - @Get(":adapter/questionIds") - @UseInterceptors(ClassSerializerInterceptor) - //@ApiBasicAuth("access-token") - // @ApiOkResponse({ description: "Get all Questions detail." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "questionIds", required: false }) - public async getAllQuestionsByQuestionIds( - @Param("adapter") adapter: string, - @Query("questionIds") questionIds: [string], - @Req() request: Request - ) { - if (adapter === "diksha") { - return this.dikshaProvider.getAllQuestionsByQuestionIds( - questionIds, - request - ); - } - } - - @Get(":adapter/subjectlist") - @UseInterceptors(ClassSerializerInterceptor) - @ApiOkResponse({ description: "Get all subject list" }) - @ApiQuery({ name: "gradeLevel", required: true }) - @ApiForbiddenResponse({ description: "Forbidden" }) - public async getSubjectList( - @Param("adapter") adapter: string, - @Query("gradeLevel") gradeLevel: string - ) { - if (adapter === "diksha") { - return this.dikshaProvider.getSubjectList(gradeLevel); - } - } - - @Get(":adapter/topicslist") - @UseInterceptors(ClassSerializerInterceptor) - @ApiOkResponse({ description: "Get all subject list" }) - @ApiQuery({ name: "subject", required: true }) - @ApiForbiddenResponse({ description: "Forbidden" }) - public async getTopicsList( - @Param("adapter") adapter: string, - @Query("subject") subject: string - ) { - if (adapter === "diksha") { - return this.dikshaProvider.getTopicsList(subject); - } - } - - @Get(":adapter/questionid") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: "Get Questions detail." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "questionId", required: false }) - public async getOneQuestion( - @Param("adapter") adapter: string, - @Query("questionId") questionId: string, - @Req() request: Request - ) { - if (adapter === "diksha") { - return this.dikshaProvider.getOneQuestion(questionId, request); - } - } - - @Get(":adapter/competencieslist") - @UseInterceptors(ClassSerializerInterceptor) - //@ApiBasicAuth("access-token") - // @ApiOkResponse({ description: "Get all competencies list." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "subject", required: false }) - // @ApiQuery({ name: "limit", required: false }) - public async getcompetenciesList( - @Param("adapter") adapter: string, - @Query("subject") subject: string, - @Query("limit") limit: string, - @Req() request: Request - ) { - if (adapter === "diksha") { - return this.dikshaProvider.getCompetenciesList(subject, limit, request); - } - } - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Question detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiQuery({ name: "adapter" }) - getQuestion( - @Param("id") questionId: string, - @Query("adapter") adapter: string, - @Req() request: Request - ) { - if (adapter === "diksha") { - return this.dikshaProvider.getQuestion(questionId, request); - } else if (adapter === "shiksha") { - return this.hasuraProvider.getQuestion(questionId, request); - } - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Question has been created successfully.", - // }) - // @ApiBody({ type: QuestionDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - // @ApiQuery({ name: "adapter" }) - public async createQuestion( - @Req() request: Request, - @Query("adapter") adapter: string, - @Body() questionDto: QuestionDto - ) { - if (adapter === "diksha") { - return this.dikshaProvider.createQuestion(request, questionDto); - } else if (adapter === "shiksha") { - return this.hasuraProvider.createQuestion(request, questionDto); - } - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Question has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - // @ApiQuery({ name: "adapter" }) - public async updateQuestion( - @Param("id") questionId: string, - @Req() request: Request, - @Body() questionDto: QuestionDto, - @Query("adapter") adapter: string - ) { - if (adapter === "diksha") { - return this.dikshaProvider.updateQuestion( - questionId, - request, - questionDto - ); - } else if (adapter === "shiksha") { - return this.hasuraProvider.updateQuestion( - questionId, - request, - questionDto - ); - } - } - - @Post("filter/:adapter") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: " Ok." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "limit", required: false }) - // @ApiQuery({ name: "body", required: false }) - // @ApiQuery({ name: "className", required: false }) - // @ApiQuery({ name: "maxScore", required: false }) - // @ApiQuery({ name: "questionId", required: false }) - // @ApiQuery({ name: "subject", required: false }) - // @ApiQuery({ name: "topic", required: false }) - // @ApiQuery({ name: "type", required: false }) - // @ApiQuery({ name: "page", required: false }) - public async filterQuestion( - @Param("adapter") adapter: string, - @Query("limit") limit: string, - @Query("body") body: string, - @Query("className") className: string, - @Query("maxScore") maxScore: string, - @Query("questionId") questionId: string, - @Query("subject") subject: string, - @Query("topic") topic: string, - @Query("type") type: string, - @Query("page") page: number, - @Req() request: Request - ) { - if (adapter === "diksha") { - return this.dikshaProvider.filterQuestion( - limit, - body, - className, - maxScore, - questionId, - subject, - topic, - type, - page, - request - ); - } else if (adapter === "shiksha") { - return this.hasuraProvider.filterQuestion( - limit, - body, - className, - maxScore, - questionId, - subject, - topic, - type, - page, - request - ); - } - } - - @Post(":adapter/bulkImport") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Bulk Question has been created successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async bulkImport( - @Param("adapter") adapter: string, - @Req() request: Request, - @Body() questionDto: [Object] - ) { - if (adapter === "diksha") { - return this.dikshaProvider.bulkImport(request, questionDto); - } else if (adapter === "shiksha") { - return this.hasuraProvider.bulkImport(request, questionDto); - } - } -} diff --git a/src/Question/question.module.ts b/src/Question/question.module.ts deleted file mode 100644 index 6c6a008d..00000000 --- a/src/Question/question.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { QuestionController } from "./question.controller"; -import { - DikshaQuestionToken, - QumlQuestionService, -} from "src/adapters/diksha/quml.adapter"; -import { - HasuraQuestionToken, - QuestionService, -} from "src/adapters/hasura/question.adapter"; - -@Module({ - imports: [HttpModule], - controllers: [QuestionController], - providers: [ - QumlQuestionService, - { provide: DikshaQuestionToken, useClass: QumlQuestionService }, - { provide: HasuraQuestionToken, useClass: QuestionService }, - ], -}) -export class QuestionModule {} diff --git a/src/adapters/diksha/quml.adapter.ts b/src/adapters/diksha/quml.adapter.ts deleted file mode 100644 index aeccfa6a..00000000 --- a/src/adapters/diksha/quml.adapter.ts +++ /dev/null @@ -1,511 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { QuestionDto } from "src/Question/dto/question.dto"; -import { IServicelocator } from "../questionservicelocator"; -import e from "express"; -export const DikshaQuestionToken = "Question"; -@Injectable() -export class QumlQuestionService implements IServicelocator { - constructor(private httpService: HttpService) {} - url = process.env.DIKSHADEVBASEAPIURL; - public async getAllQuestions( - questionType: string, - subject: [string], - limit: string, - language: string, - medium: string, - bloomsLevel: [string], - topic: [string], - className: [string], - request: any - ) { - var axios = require("axios"); - - var data = { - request: { - filters: { - objectType: "Question", - status: ["Live"], - qType: questionType, - subject: subject, - language: language, - topic: topic, - gradeLevel: className, - medium: medium, - bloomsLevel: bloomsLevel, - }, - limit: limit, - }, - }; - - var config = { - method: "post", - url: `${this.url}/composite/v3/search`, - data: data, - }; - - const response = await axios(config); - const responseData = response.data.result.Question; - let arrayIds = responseData.map((e: any) => { - return e.identifier; - }); - - let questionArray = []; - for (let value of arrayIds) { - let questionData = this.getQuestions(value); - questionArray.push(await questionData); - } - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: questionArray, - }); - } - - public async getQuestions(value: any) { - var axios = require("axios"); - - let config = { - method: "get", - url: `${this.url}/question/v1/read/${value}?fields=body,qType,answer,responseDeclaration,name,solutions,editorState,media,name,board,medium,gradeLevel,subject,topic,learningOutcome,marks,maxScore,bloomsLevel,compatibilityLevel,language,source`, - }; - - const response = await axios(config); - - const data = response?.data; - const final = data.result.question; - - const mappedResponse = { - body: final.body, - - instructions: final.instructions, - - feedback: final.feedback, - - topic: final.topic, - - subject: final.subject, - - class: final.gradeLevel, - - questionId: final.identifier, - - hints: final.hints, - - options: final.editorState.options, - - answer: final.answer, - - media: final.media, - - responseDeclaration: final.responseDeclaration, - - outcomeDeclaration: final.outcomeDeclaration, - - templateDeclaration: final.templateDeclaration, - - templateProcessing: final.templateProcessing, - - responseProcessing: final.responseProcessing, - - bloomsLevel: final.bloomsLevel, - - qlevel: final.qlevel, - - purpose: final.purpose, - - expectedDuration: final.expectedDuration, - - maxScore: final.maxScore, - - type: final.qType, - - visibility: final.visibility, - - isTemplate: final.isTemplate, - - interactions: final.interactions, - - solutionAvailable: final.solutionAvailable, - - scoringMode: final.scoringMode, - - qumlVersion: final.qumlVersion, - - totalTimeSpent: final.totalTimeSpent, - - avgTimeSpent: final.avgTimeSpent, - - numAttempts: final.numAttempts, - - numCorrectAttempts: final.numCorrectAttempts, - - numInCorrectAttempts: final.numInCorrectAttempts, - - numSkips: final.numSkips, - - source: final.source, - - learningOutcome: final.learningOutcome, - - compatibilityLevel: final.compatibilityLevel, - - language: final.language, - - avgRating: final.avgRating, - - totalRatings: final.totalRatings, - - examQuestionId: final.examQuestionId, - }; - - let res = new QuestionDto(mappedResponse); - return res; - } - - public async getAllQuestionsByQuestionIds( - questionIds: [string], - request: any - ) { - var axios = require("axios"); - let questionArray = []; - for (let value of questionIds) { - let config = { - method: "get", - url: `${this.url}/question/v1/read/${value}?fields=body,qType,answer,responseDeclaration,name,solutions,editorState,media,name,board,medium,gradeLevel,subject,topic,learningOutcome,marks,maxScore,bloomsLevel,compatibilityLevel,language,source`, - }; - - const response = await axios(config); - const data = response?.data; - const final = data.result.question; - - const mappedResponse = { - body: final.body, - - instructions: final.instructions, - - feedback: final.feedback, - - topic: final.topic, - - subject: final.subject, - - class: final.gradeLevel, - - questionId: final.identifier, - - hints: final.hints, - - options: final.editorState.options, - - answer: final.answer, - - media: final.media, - - responseDeclaration: final.responseDeclaration, - - outcomeDeclaration: final.outcomeDeclaration, - - templateDeclaration: final.templateDeclaration, - - templateProcessing: final.templateProcessing, - - responseProcessing: final.responseProcessing, - - bloomsLevel: final.bloomsLevel, - - qlevel: final.qlevel, - - purpose: final.purpose, - - expectedDuration: final.expectedDuration, - - maxScore: final.maxScore, - - type: final.qType, - - visibility: final.visibility, - - isTemplate: final.isTemplate, - - interactions: final.interactions, - - solutionAvailable: final.solutionAvailable, - - scoringMode: final.scoringMode, - - qumlVersion: final.qumlVersion, - - totalTimeSpent: final.totalTimeSpent, - - avgTimeSpent: final.avgTimeSpent, - - numAttempts: final.numAttempts, - - numCorrectAttempts: final.numCorrectAttempts, - - numInCorrectAttempts: final.numInCorrectAttempts, - - numSkips: final.numSkips, - - source: final.source, - - learningOutcome: final.learningOutcome, - - compatibilityLevel: final.compatibilityLevel, - - language: final.language, - - avgRating: final.avgRating, - - totalRatings: final.totalRatings, - - examQuestionId: final.examQuestionId, - }; - - let res = new QuestionDto(mappedResponse); - questionArray.push(res); - } - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: questionArray, - }); - } - - public async getSubjectList(gradeLevel: string) { - try { - var axios = require("axios"); - let subjects = Array; - var config = { - method: "get", - url: "https://diksha.gov.in/api/framework/v1/read/mh_k-12_1?categories=board,gradeLevel,medium,class,subject", - headers: { - "Content-Type": "application/json", - }, - }; - const responseData = await axios(config); - const categories = responseData.data.result.framework.categories; - if (typeof categories !== "undefined" && categories.length > 0) { - const grades = categories.find((o) => o.code === "gradeLevel"); - let terms = grades.terms; - if (typeof terms !== "undefined" && terms.length > 0) { - let associations = terms.find((o) => o.code === gradeLevel); - subjects = associations.associations; - } - } - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: subjects, - }); - } catch (e) { - return `${e}`; - } - } - public async getTopicsList(subject: string) { - try { - var axios = require("axios"); - var data = { - request: { - filters: { - objectType: "Question", - status: ["Live"], - subject: [subject], - }, - }, - }; - - var config = { - method: "post", - url: "https://vdn.diksha.gov.in/action/composite/v3/search", - headers: { - "Content-Type": "application/json", - }, - data: data, - }; - - const responseData = await axios(config); - const categories = responseData.data.result.Question; - const topicList = categories.map((e: any) => { - return e.se_topics[0]; - }); - const subjectTopicList = [...new Set(topicList)]; - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: subjectTopicList, - }); - } catch (e) { - return `${e}`; - } - } - public async getOneQuestion(questionId: string, request: any) { - var axios = require("axios"); - - let config = { - method: "get", - url: `${this.url}/question/v1/read/${questionId}?fields=body,qType,answer,responseDeclaration,name,solutions,editorState,media,name,board,medium,gradeLevel,subject,topic,learningOutcome,marks,maxScore,bloomsLevel,compatibilityLevel,language,source`, - }; - - const response = await axios(config); - - const data = response?.data; - - const final = data.result.question; - - const mappedResponse = { - body: final.body, - - instructions: final.instructions, - - feedback: final.feedback, - - topic: final.topic, - - subject: final.subject, - - class: final.gradeLevel, - - questionId: final.identifier, - - hints: final.hints, - - options: final.editorState.options, - - answer: final.answer, - - media: final.media, - - responseDeclaration: final.responseDeclaration, - - outcomeDeclaration: final.outcomeDeclaration, - - templateDeclaration: final.templateDeclaration, - - templateProcessing: final.templateProcessing, - - responseProcessing: final.responseProcessing, - - bloomsLevel: final.bloomsLevel, - - qlevel: final.qlevel, - - purpose: final.purpose, - - expectedDuration: final.expectedDuration, - - maxScore: final.maxScore, - - type: final.qType, - - visibility: final.visibility, - - isTemplate: final.isTemplate, - - interactions: final.interactions, - - solutionAvailable: final.solutionAvailable, - - scoringMode: final.scoringMode, - - qumlVersion: final.qumlVersion, - - totalTimeSpent: final.totalTimeSpent, - - avgTimeSpent: final.avgTimeSpent, - - numAttempts: final.numAttempts, - - numCorrectAttempts: final.numCorrectAttempts, - - numInCorrectAttempts: final.numInCorrectAttempts, - - numSkips: final.numSkips, - - source: final.source, - - learningOutcome: final.learningOutcome, - - compatibilityLevel: final.compatibilityLevel, - - language: final.language, - - avgRating: final.avgRating, - - totalRatings: final.totalRatings, - - examQuestionId: final.examQuestionId, - }; - - let res = new QuestionDto(mappedResponse); - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: res, - }); - } - - public async getCompetenciesList( - subject: string, - limit: string, - request: any - ) { - var axios = require("axios"); - try { - var data = { - request: { - filters: { - objectType: "Question", - status: ["Live"], - - subject: subject, - }, - limit: limit, - }, - }; - - var config = { - method: "post", - url: `${this.url}/composite/v3/search`, - data: data, - }; - - const response = await axios(config); - const responseData = response.data.result.Question; - const resData = responseData.map((e: any) => { - return e.bloomsLevel; - }); - let bloomsLevel = [...new Set(resData)]; - - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: bloomsLevel, - }); - } catch (e) { - return ` Competencies not found.`; - } - } - - getQuestion(questionId: string, request: any) {} - createQuestion(request: any, questionDto: QuestionDto) {} - updateQuestion(questionId: string, request: any, questionDto: QuestionDto) {} - filterQuestion( - limit: string, - body: string, - className: string, - maxScore: string, - questionId: string, - subject: string, - topic: string, - type: string, - page: number, - request: any - ) {} - bulkImport(request: any, questionDto: [Object]) {} -} diff --git a/src/adapters/hasura/question.adapter.ts b/src/adapters/hasura/question.adapter.ts deleted file mode 100644 index 8646dfba..00000000 --- a/src/adapters/hasura/question.adapter.ts +++ /dev/null @@ -1,464 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable } from "@nestjs/common"; -import { SuccessResponse } from "src/success-response"; -import { QuestionDto } from "src/Question/dto/question.dto"; -import { IServicelocator } from "../questionservicelocator"; -export const HasuraQuestionToken = "HasuraQuestion"; -@Injectable() -export class QuestionService implements IServicelocator { - constructor(private httpService: HttpService) {} - - public async getQuestion(questionId: string, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetQuestion($examQuestionId:uuid) { - question_by_pk(examQuestionId: $examQuestionId) { - answer - avgRating - avgTimeSpent - bloomsLevel - body - class - compatibilityLevel - created_at - examQuestionId - expectedDuration - feedback - hints - instructions - interactions - isTemplate - language - learningOutcome - maxScore - media - numAttempts - numCorrectAttempts - numInCorrectAttempts - numSkips - options - outcomeDeclaration - purpose - qlevel - questionId - qumlVersion - responseDeclaration - responseProcessing - scoringMode - solutionAvailable - source - subject - templateDeclaration - templateProcessing - topic - totalRatings - totalTimeSpent - type - updated_at - visibility - } - } - `, - variables: { examQuestionId: questionId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = [response.data.data.question_by_pk]; - const questionResponse = await this.mappedResponse(result); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: questionResponse[0], - }); - } - public async createQuestion(request: any, questionDto: QuestionDto) { - var axios = require("axios"); - let query = ""; - Object.keys(questionDto).forEach((e) => { - if (questionDto[e] && questionDto[e] != "") { - if (Array.isArray(questionDto[e])) { - query += `${e}: ${JSON.stringify(questionDto[e])}, `; - } else { - query += `${e}: "${questionDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateQuestion { - insert_question_one(object: {${query}}) { - examQuestionId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_question_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateQuestion( - questionId: string, - request: any, - questionDto: QuestionDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(questionDto).forEach((e) => { - if (questionDto[e] && questionDto[e] != "") { - if (Array.isArray(questionDto[e])) { - query += `${e}: ${JSON.stringify(questionDto[e])}, `; - } else { - query += `${e}: ${questionDto[e]}, `; - } - } - }); - - var data = { - query: `mutation UpdateQuestion($examQuestionId:uuid) { - update_question(where: {examQuestionId: {_eq: $examQuestionId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - examQuestionId: questionId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async filterQuestion( - limit: string, - body: string, - className: string, - maxScore: string, - questionId: string, - subject: string, - topic: string, - type: string, - page: number, - request: any - ) { - var axios = require("axios"); - - let offset = 0; - - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - - const searchData = { - body: body, - class: className, - maxScore: maxScore, - questionId: questionId, - subject: subject, - topic: topic, - type: type, - }; - - let query = ""; - Object.keys(searchData).forEach((e) => { - if (searchData[e] && searchData[e] != "") { - query += `${e}:{_eq:"${searchData[e]}"}`; - } - }); - - var data = { - query: `query SearchQuestion($limit:Int, $offset:Int) { - question_aggregate { - aggregate { - count - } - } - question(where:{ ${query}}, limit: $limit, offset: $offset,) { - answer - avgRating - avgTimeSpent - bloomsLevel - body - class - compatibilityLevel - created_at - examQuestionId - expectedDuration - feedback - hints - instructions - interactions - isTemplate - language - learningOutcome - maxScore - media - numAttempts - numCorrectAttempts - numInCorrectAttempts - numSkips - options - outcomeDeclaration - purpose - qlevel - questionId - qumlVersion - responseDeclaration - responseProcessing - scoringMode - solutionAvailable - source - subject - templateDeclaration - templateProcessing - topic - totalRatings - totalTimeSpent - type - updated_at - visibility - } - }`, - variables: { - limit: parseInt(limit), - offset: offset, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.question; - const questionResponse = await this.mappedResponse(result); - const count = response?.data?.data?.question_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: questionResponse, - }); - } - - public async bulkImport(request: any, questionDto: [Object]) { - let axios = require("axios"); - const result = Promise.all( - questionDto.map(async (data: any) => { - let query = ""; - Object.keys(data).forEach((e) => { - if (data[e] && data[e] != "") { - if (Array.isArray(data[e])) { - query += `${e}: ${JSON.stringify(data[e])}, `; - } else { - query += `${e}: ${data[e]}, `; - } - } - }); - - var createQuery = { - query: `mutation CreateQuestion { - insert_question_one(object: {${query}}) { - examQuestionId - } - } - `, - variables: {}, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: createQuery, - }; - - const response = await axios(config); - return await response.data; - }) - ); - const responseArray = await result; - return new SuccessResponse({ - statusCode: 200, - message: " Ok.", - data: responseArray, - }); - } - - public async getAllQuestions( - questionType: string, - subject: [string], - limit: string, - language: string, - medium: string, - bloomsLevel: [string], - topic: [string], - className: [string], - request: any - ) {} - - public async getAllQuestionsByQuestionIds( - questionIds: [string], - request: any - ) {} - public async getSubjectList(gradeLevel: string) {} - public async getTopicsList(subject: string) {} - - public async getOneQuestion(questionId: string, request: any) {} - - public async getCompetenciesList( - subject: string, - limit: string, - request: any - ) {} - public async mappedResponse(result: any) { - const questionResponse = result.map((item: any) => { - const questionMapping = { - id: item?.examQuestionId, - - examQuestionId: item?.examQuestionId, - - body: item?.body, - - instructions: item?.instructions, - - feedback: item?.feedback, - - topic: item?.topic, - - subject: item?.subject, - - class: item?.class, - - questionId: item?.questionId, - - hints: item?.hints, - - options: item?.options, - - media: item?.media, - - responseDeclaration: item?.responseDeclaration, - - outcomeDeclaration: item?.outcomeDeclaration, - - templateDeclaration: item?.templateDeclaration, - - templateProcessing: item?.templateProcessing, - - responseProcessing: item?.responseProcessing, - - bloomsLevel: item?.bloomsLevel, - - qlevel: item?.qlevel, - - purpose: item?.purpose, - - expectedDuration: item?.expectedDuration, - - maxScore: item?.maxScore, - - type: item?.type, - - visibility: item?.visibility, - - isTemplate: item?.isTemplate, - - interactions: item?.interactions, - - solutionAvailable: item?.solutionAvailable, - - scoringMode: item?.scoringMode, - - qumlVersion: item?.qumlVersion, - - totalTimeSpent: item?.totalTimeSpent, - - avgTimeSpent: item?.avgTimeSpent, - - numAttempts: item?.numAttempts, - - numCorrectAttempts: item?.numCorrectAttempts, - - numInCorrectAttempts: item?.numInCorrectAttempts, - - numSkips: item?.numSkips, - - source: item?.source, - - answer: item?.answer, - - learningOutcome: item?.learningOutcome, - - compatibilityLevel: item?.compatibilityLevel, - - language: item?.language, - - avgRating: item?.avgRating, - - totalRatings: item?.totalRatings, - }; - return new QuestionDto(questionMapping); - }); - - return questionResponse; - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 9ef9fe1a..186c4928 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { QuestionModule } from "./Question/question.module"; import { LikeModule } from "./like/like.module"; import { CommentModule } from "./comment/comment.module"; import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; From 43b9e9abf2f34c92c5fac1314b4b1c3623acda5f Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:46:02 +0530 Subject: [PATCH 198/408] chore : removed like module --- src/adapters/hasura/hasura.module.ts | 3 - src/adapters/hasura/like.adapter.ts | 345 --------------------------- src/adapters/likeservicelocator.ts | 11 - src/app.module.ts | 1 - src/like/dto/like-search.dto.ts | 26 -- src/like/dto/like.dto.ts | 35 --- src/like/like.controller.ts | 121 ---------- src/like/like.module.ts | 12 - src/like/likeadapter.ts | 18 -- 9 files changed, 572 deletions(-) delete mode 100644 src/adapters/hasura/like.adapter.ts delete mode 100644 src/adapters/likeservicelocator.ts delete mode 100644 src/like/dto/like-search.dto.ts delete mode 100644 src/like/dto/like.dto.ts delete mode 100644 src/like/like.controller.ts delete mode 100644 src/like/like.module.ts delete mode 100644 src/like/likeadapter.ts diff --git a/src/adapters/hasura/hasura.module.ts b/src/adapters/hasura/hasura.module.ts index f33e4be1..93ea618b 100644 --- a/src/adapters/hasura/hasura.module.ts +++ b/src/adapters/hasura/hasura.module.ts @@ -3,7 +3,6 @@ import { Module } from "@nestjs/common"; import { AttendanceHasuraService } from "./attendance.adapter"; import { HasuraCommentService } from "./comment.adapter"; import { HasuraConfigService } from "./config.adapter"; -import { HasuraLikeService } from "./like.adapter"; import { HasuraCohortService } from "./cohort.adapter"; import { HasuraCohortMembersService } from "./cohortMembers.adapter"; import { HasuraFieldsService } from "./fields.adapter"; @@ -18,7 +17,6 @@ import { HasuraUserService } from "./user.adapter"; HasuraCohortMembersService, HasuraCommentService, HasuraConfigService, - HasuraLikeService, HasuraFieldsService, FieldsService, HasuraUserService, @@ -29,7 +27,6 @@ import { HasuraUserService } from "./user.adapter"; HasuraCohortMembersService, HasuraCommentService, HasuraConfigService, - HasuraLikeService, HasuraFieldsService, HasuraUserService, ], diff --git a/src/adapters/hasura/like.adapter.ts b/src/adapters/hasura/like.adapter.ts deleted file mode 100644 index 0a6c1ecb..00000000 --- a/src/adapters/hasura/like.adapter.ts +++ /dev/null @@ -1,345 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { LikeDto } from "src/like/dto/like.dto"; -import { LikeSearchDto } from "src/like/dto/like-search.dto"; -import { IServicelocator } from "../likeservicelocator"; -import jwt_decode from "jwt-decode"; -export const HasuraLikeToken = "HasuraLike"; -@Injectable() -export class HasuraLikeService implements IServicelocator { - constructor(private httpService: HttpService) {} - userUrl = `${process.env.BASEAPIURL}/User`; - - public async createLike(request: any, likeDto: LikeDto) { - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let axios = require("axios"); - let userData = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let searchData = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: userData, - }; - const resData = await axios(searchData); - const resultData = resData.data[0]; - likeDto.userId = resultData.osid; - const likeSchema = new LikeDto(likeDto); - - let query = ""; - Object.keys(likeDto).forEach((e) => { - if ( - likeDto[e] && - likeDto[e] != "" && - Object.keys(likeSchema).includes(e) - ) { - if (Array.isArray(likeDto[e])) { - query += `${e}: ${JSON.stringify(likeDto[e])}, `; - } else { - query += `${e}: "${likeDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateLike { - insert_like_one(object: {${query}}) { - likeId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data.insert_like_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateLike(id: string, request: any, likeDto: LikeDto) { - var axios = require("axios"); - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let updateData = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let configData = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: updateData, - }; - const userResponse = await axios(configData); - const resultData = userResponse.data[0]; - likeDto.userId = resultData.osid; - const likeSchema = new LikeDto(likeDto); - let query = ""; - Object.keys(likeDto).forEach((e) => { - if ( - likeDto[e] && - likeDto[e] != "" && - Object.keys(likeSchema).includes(e) - ) { - if (Array.isArray(likeDto[e])) { - query += `${e}: ${JSON.stringify(likeDto[e])}, `; - } else { - query += `${e}: "${likeDto[e]}", `; - } - } - }); - - var data = { - query: `mutation UpdateLike($likeId:uuid) { - update_like(where: {likeId: {_eq: $likeId}}, _set: {${query}}) { - affected_rows - }}`, - variables: { - likeId: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async getLike(likeId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetLike($likeId:uuid!) { - like_by_pk(likeId: $likeId) { - userId - updated_at - type - likeId - created_at - contextId - context - } - } - `, - variables: { likeId: likeId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - let result = [response.data.data.like_by_pk]; - const likeDto = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: likeDto[0], - }); - } - - public async searchLike(request: any, likeSearchDto: LikeSearchDto) { - var axios = require("axios"); - - let offset = 0; - if (likeSearchDto.page > 1) { - offset = parseInt(likeSearchDto.limit) * (likeSearchDto.page - 1); - } - - let filters = likeSearchDto.filters; - - Object.keys(likeSearchDto.filters).forEach((item) => { - Object.keys(likeSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchLike($filters:like_bool_exp,$limit:Int, $offset:Int) { - like_aggregate { - aggregate { - count - } - } - like(where:$filters, limit: $limit, offset: $offset,) { - userId - updated_at - type - likeId - created_at - contextId - context - } - }`, - variables: { - limit: parseInt(likeSearchDto.limit), - offset: offset, - filters: likeSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = response.data.data.like; - const likeDto = await this.mappedResponse(result); - const count = response?.data?.data?.like_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: likeDto, - }); - } - public async getCountLike(contextId: string, context: string, request: any) { - var axios = require("axios"); - - var data = { - query: `query SearchLike($contextId:String,$context:String) { - like(where: {contextId: {_eq: $contextId}, context: {_eq: $context}}) { - userId - updated_at - type - likeId - created_at - contextId - context - } - }`, - variables: { - contextId: contextId, - context: context, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - let result = response.data.data.like; - const likeDto = await this.mappedResponse(result); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: likeDto.length, - }); - } - - public async deleteLike(likeId: string, request: any) { - var axios = require("axios"); - var data = { - query: `mutation UpdateLike($likeId:uuid) { - delete_like(where: {likeId: {_eq: $likeId}}) { - affected_rows - }}`, - variables: { - likeId: likeId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async mappedResponse(result: any) { - const likeResponse = result.map((obj: any) => { - const likeMapping = { - id: obj?.likeId ? `${obj.likeId}` : "", - likeId: obj?.likeId ? `${obj.likeId}` : "", - contextId: obj?.contextId ? `${obj.contextId}` : "", - context: obj?.context ? `${obj.context}` : "", - userId: obj?.userId ? `${obj.userId}` : "", - type: obj?.type ? `${obj.type}` : "", - createdAt: obj?.created_at ? `${obj.created_at}` : "", - updatedAt: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new LikeDto(likeMapping); - }); - - return likeResponse; - } -} diff --git a/src/adapters/likeservicelocator.ts b/src/adapters/likeservicelocator.ts deleted file mode 100644 index d5728291..00000000 --- a/src/adapters/likeservicelocator.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { LikeSearchDto } from "src/like/dto/like-search.dto"; -import { LikeDto } from "src/like/dto/like.dto"; - -export interface IServicelocator { - getLike(likeId: string, request: any); - createLike(request: any, likeDto: LikeDto); - updateLike(likeId: string, request: any, likeDto: LikeDto); - searchLike(request: any, likeSearchDto: LikeSearchDto); - getCountLike(contextId: string, context: string, request: any); - deleteLike(likeId: string, request: any); -} diff --git a/src/app.module.ts b/src/app.module.ts index 186c4928..3e238aa2 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { LikeModule } from "./like/like.module"; import { CommentModule } from "./comment/comment.module"; import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; import { AssessmentSetModule } from "./assessmentset/assessmentset.module"; diff --git a/src/like/dto/like-search.dto.ts b/src/like/dto/like-search.dto.ts deleted file mode 100644 index 8991eb27..00000000 --- a/src/like/dto/like-search.dto.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class LikeSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Number, - description: "Page", - }) - page: number; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/like/dto/like.dto.ts b/src/like/dto/like.dto.ts deleted file mode 100644 index 5b68ae13..00000000 --- a/src/like/dto/like.dto.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class LikeDto { - @Expose() - id: string; - - @Expose() - likeId: string; - - @ApiProperty({}) - @Expose() - contextId: string; - - @ApiProperty({}) - @Expose() - context: string; - - @Expose() - userId: string; - - @ApiProperty({}) - @Expose() - type: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/like/like.controller.ts b/src/like/like.controller.ts deleted file mode 100644 index 4cd105ee..00000000 --- a/src/like/like.controller.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Query, - Delete, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, - ApiExcludeController, -} from "@nestjs/swagger"; -import { Request } from "@nestjs/common"; -import { LikeDto } from "./dto/like.dto"; -import { LikeSearchDto } from "./dto/like-search.dto"; -import { LikeAdapter } from "./likeadapter"; -// @ApiTags("Like") -@ApiExcludeController() -@Controller("like") -export class LikeController { - constructor(private likeAdapter: LikeAdapter) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Like detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getLike(@Param("id") likeId: string, @Req() request: Request) { - return this.likeAdapter.buildLikeAdapter().getLike(likeId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Like has been created successfully.", - // }) - // @ApiBody({ type: LikeDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - public async createLike(@Req() request: Request, @Body() likeDto: LikeDto) { - return this.likeAdapter.buildLikeAdapter().createLike(request, likeDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Like has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateLike( - @Param("id") likeId: string, - @Req() request: Request, - @Body() likeDto: LikeDto - ) { - return await this.likeAdapter - .buildLikeAdapter() - .updateLike(likeId, request, likeDto); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Like list." }) - // @ApiBody({ type: LikeSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchLike( - @Req() request: Request, - @Body() likeSearchDto: LikeSearchDto - ) { - return await this.likeAdapter - .buildLikeAdapter() - .searchLike(request, likeSearchDto); - } - - @Post("/getAllLikes") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "All Like." }) - @ApiQuery({ name: "contextId" }) - @ApiQuery({ name: "context" }) - public async getCountLike( - @Query("contextId") contextId: string, - @Query("context") context: string, - @Req() request: Request - ) { - return await this.likeAdapter - .buildLikeAdapter() - .getCountLike(contextId, context, request); - } - - @Delete("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Delete like. " }) - public async deleteLike( - @Param("id") likeId: string, - @Req() request: Request - ) { - return await this.likeAdapter - .buildLikeAdapter() - .deleteLike(likeId, request); - } -} diff --git a/src/like/like.module.ts b/src/like/like.module.ts deleted file mode 100644 index 72700db7..00000000 --- a/src/like/like.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { CacheModule, Module } from "@nestjs/common"; -import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { LikeController } from "./like.controller"; -import { LikeAdapter } from "./likeadapter"; - -@Module({ - imports: [HasuraModule, HttpModule], - controllers: [LikeController], - providers: [LikeAdapter], -}) -export class LikeModule {} diff --git a/src/like/likeadapter.ts b/src/like/likeadapter.ts deleted file mode 100644 index b6b9e02a..00000000 --- a/src/like/likeadapter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HasuraLikeService } from "src/adapters/hasura/like.adapter"; -import { IServicelocator } from "src/adapters/likeservicelocator"; - -@Injectable() -export class LikeAdapter { - constructor(private hasuraProvider: HasuraLikeService) {} - buildLikeAdapter(): IServicelocator { - let adapter: IServicelocator; - - switch (process.env.ADAPTERSOURCE) { - case "hasura": - adapter = this.hasuraProvider; - break; - } - return adapter; - } -} From 7d754a2c3d8e14a1313db65a55c290a99322a5ea Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:48:11 +0530 Subject: [PATCH 199/408] chore : removed comment module --- src/adapters/commentservicelocator.ts | 9 - src/adapters/hasura/comment.adapter.ts | 282 ------------------------- src/adapters/hasura/hasura.module.ts | 3 - src/app.module.ts | 3 +- src/comment/comment.controller.ts | 97 --------- src/comment/comment.module.ts | 12 -- src/comment/commentadapter.ts | 18 -- src/comment/dto/comment-search.dto.ts | 26 --- src/comment/dto/comment.dto.ts | 47 ----- 9 files changed, 1 insertion(+), 496 deletions(-) delete mode 100644 src/adapters/commentservicelocator.ts delete mode 100644 src/adapters/hasura/comment.adapter.ts delete mode 100644 src/comment/comment.controller.ts delete mode 100644 src/comment/comment.module.ts delete mode 100644 src/comment/commentadapter.ts delete mode 100644 src/comment/dto/comment-search.dto.ts delete mode 100644 src/comment/dto/comment.dto.ts diff --git a/src/adapters/commentservicelocator.ts b/src/adapters/commentservicelocator.ts deleted file mode 100644 index 6792cd76..00000000 --- a/src/adapters/commentservicelocator.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { CommentSearchDto } from "src/comment/dto/comment-search.dto"; -import { CommentDto } from "src/comment/dto/comment.dto"; - -export interface IServicelocator { - getComment(commentId: string, request: any); - createComment(request: any, commentDto: CommentDto); - updateComment(commentId: string, request: any, commentDto: CommentDto); - searchComment(request: any, commentSearchDto: CommentSearchDto); -} diff --git a/src/adapters/hasura/comment.adapter.ts b/src/adapters/hasura/comment.adapter.ts deleted file mode 100644 index 10a5c4be..00000000 --- a/src/adapters/hasura/comment.adapter.ts +++ /dev/null @@ -1,282 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { IServicelocator } from "../commentservicelocator"; -import { CommentDto } from "src/comment/dto/comment.dto"; -import { CommentSearchDto } from "src/comment/dto/comment-search.dto"; -import jwt_decode from "jwt-decode"; -export const HasuraCommentToken = "HasuraComment"; -@Injectable() -export class HasuraCommentService implements IServicelocator { - constructor(private httpService: HttpService) {} - userUrl = `${process.env.BASEAPIURL}/User`; - public async createComment(request: any, commentDto: CommentDto) { - var axios = require("axios"); - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - - let userData = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let user = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: userData, - }; - const resData = await axios(user); - const res = resData.data[0]; - commentDto.userId = res.osid; - const commentSchema = new CommentDto(commentDto); - let query = ""; - Object.keys(commentDto).forEach((e) => { - if ( - commentDto[e] && - commentDto[e] != "" && - Object.keys(commentSchema).includes(e) - ) { - if (Array.isArray(commentDto[e])) { - query += `${e}: ${JSON.stringify(commentDto[e])}, `; - } else { - query += `${e}: "${commentDto[e]}", `; - } - } - }); - - var data = { - query: `mutation CreateComment { - insert_comment_one(object: {${query}}) { - commentId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_comment_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateComment(id: string, request: any, commentDto: CommentDto) { - var axios = require("axios"); - const authToken = request.headers.authorization; - const decoded: any = jwt_decode(authToken); - let email = decoded.email; - let updateData = { - filters: { - email: { - eq: `${email}`, - }, - }, - }; - let configData = { - method: "post", - url: `${this.userUrl}/search`, - headers: { - Authorization: request.headers.authorization, - }, - data: updateData, - }; - const userResponse = await axios(configData); - const resultData = userResponse.data[0]; - commentDto.userId = resultData.osid; - const commentSchema = new CommentDto(commentDto); - let query = ""; - Object.keys(commentDto).forEach((e) => { - if ( - commentDto[e] && - commentDto[e] != "" && - Object.keys(commentSchema).includes(e) - ) { - if (Array.isArray(commentDto[e])) { - query += `${e}: ${JSON.stringify(commentDto[e])}, `; - } else { - query += `${e}: "${commentDto[e]}", `; - } - } - }); - - var data = { - query: `mutation UpdateComment($commentId:uuid) { - update_comment(where: {commentId: {_eq: $commentId}}, _set: {${query}}) { - affected_rows - }}`, - variables: { - commentId: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async getComment(commentId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetComment($commentId:uuid!) { - comment_by_pk(commentId: $commentId) { - comment - commentId - context - contextId - created_at - parentId - privacy - status - updated_at - userId - } - } - `, - variables: { commentId: commentId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = await this.mappedResponse([ - response.data.data.comment_by_pk, - ]); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result[0], - }); - } - - public async searchComment(request: any, commentSearchDto: CommentSearchDto) { - var axios = require("axios"); - - let offset = 0; - if (commentSearchDto.page > 1) { - offset = parseInt(commentSearchDto.limit) * (commentSearchDto.page - 1); - } - - let filters = commentSearchDto.filters; - - Object.keys(commentSearchDto.filters).forEach((item) => { - Object.keys(commentSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchComment($filters:comment_bool_exp,$limit:Int, $offset:Int) { - comment_aggregate { - aggregate { - count - } - } - comment(where:$filters, limit: $limit, offset: $offset,) { - comment - commentId - context - contextId - created_at - parentId - privacy - status - updated_at - userId - } - }`, - variables: { - limit: parseInt(commentSearchDto.limit), - offset: offset, - filters: commentSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = await this.mappedResponse(response.data.data.comment); - const count = response?.data?.data?.comment_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result, - }); - } - - public async mappedResponse(result: any) { - const commentResponse = result.map((obj: any) => { - const commentMapping = { - id: obj?.commentId ? `${obj.commentId}` : "", - commentId: obj?.commentId ? `${obj.commentId}` : "", - contextId: obj?.contextId ? `${obj.contextId}` : "", - context: obj?.context ? `${obj.context}` : "", - userId: obj?.userId ? `${obj.userId}` : "", - comment: obj?.comment ? `${obj.comment}` : "", - privacy: obj?.privacy ? `${obj.privacy}` : "", - parentId: obj?.parentId ? `${obj.parentId}` : "", - status: obj?.status ? `${obj.status}` : "", - createdAt: obj?.created_at ? `${obj.created_at}` : "", - updatedAt: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new CommentDto(commentMapping); - }); - - return commentResponse; - } -} diff --git a/src/adapters/hasura/hasura.module.ts b/src/adapters/hasura/hasura.module.ts index 93ea618b..a9f65f8c 100644 --- a/src/adapters/hasura/hasura.module.ts +++ b/src/adapters/hasura/hasura.module.ts @@ -1,7 +1,6 @@ import { HttpModule } from "@nestjs/axios"; import { Module } from "@nestjs/common"; import { AttendanceHasuraService } from "./attendance.adapter"; -import { HasuraCommentService } from "./comment.adapter"; import { HasuraConfigService } from "./config.adapter"; import { HasuraCohortService } from "./cohort.adapter"; import { HasuraCohortMembersService } from "./cohortMembers.adapter"; @@ -15,7 +14,6 @@ import { HasuraUserService } from "./user.adapter"; AttendanceHasuraService, HasuraCohortService, HasuraCohortMembersService, - HasuraCommentService, HasuraConfigService, HasuraFieldsService, FieldsService, @@ -25,7 +23,6 @@ import { HasuraUserService } from "./user.adapter"; AttendanceHasuraService, HasuraCohortService, HasuraCohortMembersService, - HasuraCommentService, HasuraConfigService, HasuraFieldsService, HasuraUserService, diff --git a/src/app.module.ts b/src/app.module.ts index 3e238aa2..6148a71e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -5,10 +5,9 @@ import { AppService } from "./app.service"; // import { MulterModule } from "@nestjs/platform-express/multer"; // Below modules not in use for Shiksha 2.0 +import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { CommentModule } from "./comment/comment.module"; -import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; import { AssessmentSetModule } from "./assessmentset/assessmentset.module"; import { MentorTrackingModule } from "./mentorTracking/mentorTracking.module"; import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module"; diff --git a/src/comment/comment.controller.ts b/src/comment/comment.controller.ts deleted file mode 100644 index 42aac031..00000000 --- a/src/comment/comment.controller.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiExcludeController, -} from "@nestjs/swagger"; -import { Request } from "@nestjs/common"; -import { CommentDto } from "./dto/comment.dto"; -import { CommentSearchDto } from "./dto/comment-search.dto"; -import { IServicelocator } from "src/adapters/commentservicelocator"; -import { CommentAdapter } from "./commentadapter"; -// @ApiTags("Comment") -@ApiExcludeController() -@Controller("comment") -export class CommentController implements IServicelocator { - constructor(private commentAdapter: CommentAdapter) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Comment detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getComment(@Param("id") commentId: string, @Req() request: Request) { - return this.commentAdapter - .buildCommentAdapter() - .getComment(commentId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Comment has been created successfully.", - // }) - // @ApiBody({ type: CommentDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createComment( - @Req() request: Request, - @Body() commentDto: CommentDto - ) { - return this.commentAdapter - .buildCommentAdapter() - .createComment(request, commentDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Comment has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateComment( - @Param("id") commentId: string, - @Req() request: Request, - @Body() commentDto: CommentDto - ) { - return this.commentAdapter - .buildCommentAdapter() - .updateComment(commentId, request, commentDto); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Comment list." }) - // @ApiBody({ type: CommentSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async searchComment( - @Req() request: Request, - @Body() CommentSearchDto: CommentSearchDto - ) { - return this.commentAdapter - .buildCommentAdapter() - .searchComment(request, CommentSearchDto); - } -} diff --git a/src/comment/comment.module.ts b/src/comment/comment.module.ts deleted file mode 100644 index ec978896..00000000 --- a/src/comment/comment.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { CacheModule, Module } from "@nestjs/common"; -import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { CommentController } from "./comment.controller"; -import { CommentAdapter } from "./commentadapter"; - -@Module({ - imports: [HasuraModule, HttpModule], - controllers: [CommentController], - providers: [CommentAdapter], -}) -export class CommentModule {} diff --git a/src/comment/commentadapter.ts b/src/comment/commentadapter.ts deleted file mode 100644 index 3a6953bd..00000000 --- a/src/comment/commentadapter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { IServicelocator } from "src/adapters/commentservicelocator"; -import { HasuraCommentService } from "src/adapters/hasura/comment.adapter"; - -@Injectable() -export class CommentAdapter { - constructor(private hasuraProvider: HasuraCommentService) {} - buildCommentAdapter(): IServicelocator { - let adapter: IServicelocator; - - switch (process.env.ADAPTERSOURCE) { - case "hasura": - adapter = this.hasuraProvider; - break; - } - return adapter; - } -} diff --git a/src/comment/dto/comment-search.dto.ts b/src/comment/dto/comment-search.dto.ts deleted file mode 100644 index 0cb5dd7b..00000000 --- a/src/comment/dto/comment-search.dto.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class CommentSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Number, - description: "Page", - }) - page: number; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/comment/dto/comment.dto.ts b/src/comment/dto/comment.dto.ts deleted file mode 100644 index 0782fa3d..00000000 --- a/src/comment/dto/comment.dto.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class CommentDto { - @Expose() - id: string; - - @Expose() - commentId: string; - - @ApiProperty({}) - @Expose() - contextId: string; - - @ApiProperty({}) - @Expose() - context: string; - - @Expose() - userId: string; - - @ApiProperty({}) - @Expose() - comment: string; - - @ApiProperty({}) - @Expose() - privacy: string; - - @ApiProperty({}) - @Expose() - parentId: string; - - @ApiProperty({}) - @Expose() - status: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} From 2618c4755e497e3d66612781bd410950a7ec61e2 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:49:24 +0530 Subject: [PATCH 200/408] chore : removed track assessment module --- .../hasura/trackassessment.adapter.ts | 309 ------------------ src/app.module.ts | 1 - .../dto/trackassessment.dto.ts | 97 ------ src/trackAssessment/enums/statuses.enum.ts | 5 - .../trackassessment.controller.ts | 109 ------ src/trackAssessment/trackassessment.module.ts | 12 - 6 files changed, 533 deletions(-) delete mode 100644 src/adapters/hasura/trackassessment.adapter.ts delete mode 100644 src/trackAssessment/dto/trackassessment.dto.ts delete mode 100644 src/trackAssessment/enums/statuses.enum.ts delete mode 100644 src/trackAssessment/trackassessment.controller.ts delete mode 100644 src/trackAssessment/trackassessment.module.ts diff --git a/src/adapters/hasura/trackassessment.adapter.ts b/src/adapters/hasura/trackassessment.adapter.ts deleted file mode 100644 index 4d8be164..00000000 --- a/src/adapters/hasura/trackassessment.adapter.ts +++ /dev/null @@ -1,309 +0,0 @@ -import { HttpException, Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { AxiosResponse } from "axios"; -import { catchError, map } from "rxjs"; -import { SuccessResponse } from "src/success-response"; -import { TrackAssessmentDto } from "src/trackAssessment/dto/trackassessment.dto"; -import { ErrorResponse } from "src/error-response"; -import { Status } from "../../trackAssessment/enums/statuses.enum"; - -@Injectable() -export class TrackAssessmentService { - constructor(private httpService: HttpService) {} - - url = process.env.DIKSHADEVBASEAPIURL; - public async getAssessment(assessmentId: any, request: any) { - var axios = require("axios"); - try { - var data = { - query: `query GetTrackAssessment($trackAssessmentId:uuid) { - trackassessment(where: {trackAssessmentId: {_eq: $trackAssessmentId}}) { - answersheet - filter - created_at - updated_at - trackAssessmentId - questions - score - totalScore - source - studentId - teacherId - groupId - subject - date - type - status - } - }`, - variables: { - trackAssessmentId: assessmentId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = await this.mappedResponse( - response.data.data.trackassessment - ); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } catch (e) { - return `${e}`; - } - } - - public async createAssessment( - request: any, - assessmentDto: TrackAssessmentDto - ) { - let variables: object; - try { - const axios = require("axios"); - if (!assessmentDto.status) { - // let's set it as "COMPLETED" by default - assessmentDto.status = Status.COMPLETED; - } - if (assessmentDto.status == Status.COMPLETED) { - const answer = JSON.stringify(assessmentDto.answersheet); - const jsonObj = JSON.parse(answer); - const params = JSON.parse(jsonObj); - - let sum = 0; - params.children.map((e: any) => { - sum += e.score; - return sum; - }); - assessmentDto.score = sum.toString(); - - const questionIds = assessmentDto.questions; - const totalScoreArray = []; - for (const value of questionIds) { - const config = { - method: "get", - url: `${this.url}/question/v1/read/${value}?fields=maxScore`, - }; - const response = await axios(config); - const data = response?.data; - const final = data.result.question; - - const scoreResponse = { - maxScore: final.maxScore, - }; - totalScoreArray.push(scoreResponse); - } - let totalScore = 0; - totalScoreArray.map((e: any) => { - totalScore += e.maxScore; - return totalScore; - }); - assessmentDto.totalScore = totalScore.toString(); - - variables = { - filter: assessmentDto.filter, - source: assessmentDto.source, - questions: assessmentDto.questions.toString(), - studentId: assessmentDto.studentId, - teacherId: assessmentDto.teacherId, - type: assessmentDto.type, - answersheet: assessmentDto.answersheet, - score: assessmentDto.score, - totalScore: assessmentDto.totalScore, - groupId: assessmentDto.groupId, - subject: assessmentDto.subject, - status: assessmentDto.status, - }; - } else { - variables = { - filter: null, - source: null, - questions: null, - studentId: assessmentDto.studentId, - teacherId: assessmentDto.teacherId, - type: assessmentDto.type, - answersheet: null, - score: null, - totalScore: null, - groupId: assessmentDto.groupId, - subject: null, - status: assessmentDto.status, - }; - } - - const data = { - query: `mutation CreateTrackAssessment($filter: String, $score: String, $totalScore:String, $source: String, $questions: String, $studentId: String, $teacherId: String, $type: String, $answersheet: String,$groupId:String, $subject:String, $status: String) { - insert_trackassessment_one(object:{filter: $filter, score: $score, totalScore:$totalScore, source: $source, questions: $questions, studentId: $studentId, teacherId: $teacherId, type: $type, answersheet: $answersheet,groupId:$groupId,subject:$subject, status: $status}) { - trackAssessmentId - } - }`, - variables: variables, - }; - - const config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: response.data, - }); - } catch (e) { - return `${e}`; - } - } - - public async searchAssessment( - fromDate: string, - toDate: string, - limit: string, - source: string, - studentId: string, - teacherId: string, - groupId: string, - subject: string, - page: number, - request: any - ) { - var axios = require("axios"); - - let offset = 0; - - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - let searchData = { - fromDate, - toDate, - source, - studentId, - teacherId, - groupId, - subject, - }; - - let query = ""; - if (searchData.fromDate && searchData.toDate) { - query += `date:{_gte: "${searchData.fromDate}"}, _and: {date: {_lte: "${searchData.toDate}"}} `; - } - const objectKeys = Object.keys(searchData); - objectKeys.forEach((e, index) => { - if ( - searchData[e] && - searchData[e] != "" && - !["fromDate", "toDate"].includes(e) - ) { - query += `${e}:{_eq:"${searchData[e]}"}`; - if (index !== objectKeys.length - 1) { - query += " "; - } - } - }); - - var data = { - query: `query searchTrackAssessment($offset:Int,$limit:Int) { - trackassessment_aggregate { - aggregate { - count - } - } - trackassessment(limit: $limit, offset: $offset, where: {${query}}) { - answersheet - filter - created_at - updated_at - trackAssessmentId - questions - score - totalScore - source - studentId - teacherId - groupId - subject - date - type - status - } -}`, - variables: { - limit: parseInt(limit), - offset: offset, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = await this.mappedResponse( - response.data.data.trackassessment - ); - const count = - response?.data?.data?.trackassessment_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result, - }); - } - - public async mappedResponse(result: any) { - const trackAssessmentResponse = result.map((obj: any) => { - const trackAssessmentMapping = { - id: obj?.trackAssessmentId ? `${obj.trackAssessmentId}` : "", - trackAssessmentId: obj?.trackAssessmentId - ? `${obj.trackAssessmentId}` - : "", - filter: obj?.filter ? `${obj.filter}` : "", - type: obj?.type ? `${obj.type}` : "", - questions: obj?.questions ? obj.questions : "", - source: obj?.source ? `${obj.source}` : "", - answersheet: obj?.answersheet ? `${obj.answersheet}` : "", - score: obj?.score ? `${obj.score}` : "", - totalScore: obj?.totalScore ? `${obj.totalScore}` : "", - studentId: obj?.studentId ? `${obj.studentId}` : "", - teacherId: obj?.teacherId ? `${obj.teacherId}` : "", - groupId: obj?.groupId ? `${obj.groupId}` : "", - subject: obj?.subject ? `${obj.subject}` : "", - date: obj?.date ? `${obj.date}` : "", - status: obj?.status ? `${obj.status}` : "", - createdAt: obj?.created_at ? `${obj.created_at}` : "", - updatedAt: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new TrackAssessmentDto(trackAssessmentMapping); - }); - - return trackAssessmentResponse; - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 6148a71e..7e61be4b 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -5,7 +5,6 @@ import { AppService } from "./app.service"; // import { MulterModule } from "@nestjs/platform-express/multer"; // Below modules not in use for Shiksha 2.0 -import { TrackAssessmentModule } from "./trackAssessment/trackassessment.module"; /* import { ConfigurationModule } from "./configs/configuration.module"; import { AssessmentSetModule } from "./assessmentset/assessmentset.module"; diff --git a/src/trackAssessment/dto/trackassessment.dto.ts b/src/trackAssessment/dto/trackassessment.dto.ts deleted file mode 100644 index add9eb94..00000000 --- a/src/trackAssessment/dto/trackassessment.dto.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsIn, IsNotEmpty, IsString } from "class-validator"; -import { Status } from "../enums/statuses.enum"; - -export class TrackAssessmentDto { - @Expose() - id: string; - - @Expose() - trackAssessmentId: string; - - @ApiProperty({ - description: "JSON string of filters selected for the assessment ", - }) - @Expose() - filter: string; - - @ApiProperty({ - description: "Assessment type, spot assessment or exam", - }) - @Expose() - type: string; - - @ApiPropertyOptional({ - description: "Array of question Id's against the assessment is given", - }) - @Expose() - questions: [string]; - - @ApiPropertyOptional({ - description: "Assessment questions source", - }) - @Expose() - source: string; - - @ApiProperty({ - description: - "JSON encoded QUML player response against the given questions of the assessment", - }) - @Expose() - answersheet: string; - - @Expose() - score: string; - - @ApiProperty({ - description: "student Id who has given assessment", - }) - @Expose() - studentId: string; - - @ApiProperty({ - description: "Teacher Id who has assigned the assessment", - }) - @Expose() - teacherId: string; - - @ApiProperty({ - description: "GroupId of teacher", - }) - @Expose() - groupId: string; - - @ApiProperty({ - description: "subject", - }) - @Expose() - subject: string; - - @Expose() - totalScore: string; - - @Expose() - date: string; - - @IsString() - @IsIn([Status.NONE, Status.COMPLETED, Status.ABSENT]) - @ApiProperty({ - description: - "Assessment Status - whether student was absent or he has completed the assessment.", - enum: [Status.COMPLETED, Status.ABSENT], - required: true, - }) - @Expose() - status: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/trackAssessment/enums/statuses.enum.ts b/src/trackAssessment/enums/statuses.enum.ts deleted file mode 100644 index fe0033f8..00000000 --- a/src/trackAssessment/enums/statuses.enum.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum Status { - NONE = "", // can be empty to maintain backward compatibility - COMPLETED = "COMPLETED", - ABSENT = "ABSENT", -} diff --git a/src/trackAssessment/trackassessment.controller.ts b/src/trackAssessment/trackassessment.controller.ts deleted file mode 100644 index 88c1ff9d..00000000 --- a/src/trackAssessment/trackassessment.controller.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { - ApiTags, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiBody, - ApiQuery, - ApiOkResponse, - ApiExcludeController, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Request, - Post, - Body, - Query, - UsePipes, - ValidationPipe, -} from "@nestjs/common"; -import { TrackAssessmentService } from "src/adapters/hasura/trackassessment.adapter"; -import { TrackAssessmentDto } from "./dto/trackassessment.dto"; -import { isUUID } from "class-validator"; - -// @ApiTags("Track Assessment") -@ApiExcludeController() -@Controller("trackassessment") -export class AssessmentController { - constructor(private service: TrackAssessmentService) {} - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Track Assessment has been created successfully.", - // }) - // @ApiBody({ type: TrackAssessmentDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @UsePipes(new ValidationPipe({})) - public async createAssessment( - @Req() request: Request, - @Body() assessmentDto: TrackAssessmentDto - ) { - return this.service.createAssessment(request, assessmentDto); - } - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Track Assessment detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getAssessment( - @Param("id") assessmentId: string, - @Req() request: Request - ) { - return this.service.getAssessment(assessmentId, request); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Track Assessment list." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - // @ApiQuery({ name: "fromDate", required: false }) - // @ApiQuery({ name: "toDate", required: false }) - // @ApiQuery({ name: "limit", required: false }) - // @ApiQuery({ name: "source", required: false }) - // @ApiQuery({ name: "studentId", required: false }) - // @ApiQuery({ name: "teacherId", required: false }) - // @ApiQuery({ name: "groupId", required: false }) - // @ApiQuery({ name: "subject", required: false }) - // @ApiQuery({ name: "page", required: false }) - public async searchAssessment( - @Query("fromDate") date: string, - @Query("toDate") toDate: string, - @Query("limit") limit: string, - @Query("source") source: string, - @Query("studentId") studentId: string, - @Query("teacherId") teacherId: string, - @Query("groupId") groupId: string, - @Query("subject") subject: string, - @Query("page") page: number, - @Req() request: Request - ) { - return await this.service.searchAssessment( - date, - toDate, - limit, - source, - studentId, - teacherId, - groupId, - subject, - page, - request - ); - } -} diff --git a/src/trackAssessment/trackassessment.module.ts b/src/trackAssessment/trackassessment.module.ts deleted file mode 100644 index 86b4ec29..00000000 --- a/src/trackAssessment/trackassessment.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CacheModule, Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { ScheduleModule } from "@nestjs/schedule"; -import { TrackAssessmentService } from "src/adapters/hasura/trackassessment.adapter"; -import { AssessmentController } from "./trackassessment.controller"; - -@Module({ - imports: [HttpModule, ScheduleModule.forRoot()], - controllers: [AssessmentController], - providers: [TrackAssessmentService], -}) -export class TrackAssessmentModule {} From 4a7943dd2153cd53246db7f7bd3ac52cd1259d68 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:51:09 +0530 Subject: [PATCH 201/408] chore : removed assessment set module --- src/adapters/hasura/assessmentset.adapter.ts | 188 ------------------ src/app.module.ts | 1 - src/assessmentset/assessmentset.controller.ts | 91 --------- src/assessmentset/assessmentset.module.ts | 12 -- .../dto/assessmentset-search-dto.ts | 20 -- src/assessmentset/dto/assessmentset.dto.ts | 50 ----- 6 files changed, 362 deletions(-) delete mode 100644 src/adapters/hasura/assessmentset.adapter.ts delete mode 100644 src/assessmentset/assessmentset.controller.ts delete mode 100644 src/assessmentset/assessmentset.module.ts delete mode 100644 src/assessmentset/dto/assessmentset-search-dto.ts delete mode 100644 src/assessmentset/dto/assessmentset.dto.ts diff --git a/src/adapters/hasura/assessmentset.adapter.ts b/src/adapters/hasura/assessmentset.adapter.ts deleted file mode 100644 index e6c1bde8..00000000 --- a/src/adapters/hasura/assessmentset.adapter.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { AssessmentsetDto } from "src/assessmentset/dto/assessmentset.dto"; -@Injectable() -export class AssessmentsetService { - constructor(private httpService: HttpService) {} - - public async createAssessmentSet( - request: any, - assessmentsetDto: AssessmentsetDto - ) { - var axios = require("axios"); - try { - var data = { - query: `mutation CreateAssessmentset($gradeType:String,$options:String,$title:String,$type:String,$typeDetails:String) { - insert_assessmentset_one(object: {gradeType: $gradeType, options: $options, title: $title, type: $type, typeDetails: $typeDetails}) { - assessmentsetId - } -}`, - variables: { - gradeType: assessmentsetDto.gradeType, - options: assessmentsetDto.options, - title: assessmentsetDto.title, - type: assessmentsetDto.type, - typeDetails: assessmentsetDto.typeDetails, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: response.data, - }); - } catch (e) { - return `${e}`; - } - } - public async getAssessmentset(assessmentsetId: any, request: any) { - var axios = require("axios"); - try { - var data = { - query: `query GetAssessmentset($assessmentsetId:uuid) { - assessmentset(where: {assessmentsetId: {_eq: $assessmentsetId}}) { - assessmentsetId - gradeType - title - options - type - typeDetails - created_at - updated_at - } - }`, - variables: { assessmentsetId: assessmentsetId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = await this.mappedResponse( - response.data.data.assessmentset - ); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result[0], - }); - } catch (e) { - return `${e}`; - } - } - - public async searchAssessmentset( - limit: string, - assessmentsetId: string, - type: string, - title: string, - gradeType: string, - request: any - ) { - var axios = require("axios"); - try { - const searchData = { - assessmentsetId, - type, - title, - gradeType, - }; - - let query = ""; - Object.keys(searchData).forEach((e) => { - if (searchData[e] && searchData[e] != "") { - query += `${e}:{_eq:"${searchData[e]}"}`; - } - }); - - var data = { - query: `query GetAssessmentset($limit:Int) { - assessmentset_aggregate { - aggregate { - count - } - } - - assessmentset(limit:$limit,where: {${query}}) { - assessmentsetId - gradeType - title - options - type - typeDetails - created_at - updated_at - } - }`, - variables: { limit: parseInt(limit) }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = await this.mappedResponse(response.data.data.assessmentset); - - const count = - response?.data?.data?.assessmentset_aggregate?.aggregate?.count; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result, - }); - } catch (e) { - return `${e}`; - } - } - - public async mappedResponse(result: any) { - const assessmentSetResponse = result.map((obj: any) => { - const assessmentSetMapping = { - id: obj?.assessmentsetId ? `${obj.assessmentsetId}` : "", - assessmentsetId: obj?.assessmentsetId ? `${obj.assessmentsetId}` : "", - title: obj?.title ? `${obj.title}` : "", - type: obj?.type ? obj.type : "", - typeDetails: obj?.typeDetails ? obj.typeDetails : "", - gradeType: obj?.gradeType ? `${obj.gradeType}` : "", - options: obj?.options ? `${obj.options}` : "", - createdAt: obj?.created_at ? `${obj.created_at}` : "", - updatedAt: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new AssessmentsetDto(assessmentSetMapping); - }); - - return assessmentSetResponse; - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 7e61be4b..6fecf2f1 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { AssessmentSetModule } from "./assessmentset/assessmentset.module"; import { MentorTrackingModule } from "./mentorTracking/mentorTracking.module"; import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module"; import { AnnouncementsModule } from "./announcements/announcements.module"; diff --git a/src/assessmentset/assessmentset.controller.ts b/src/assessmentset/assessmentset.controller.ts deleted file mode 100644 index 64e56e59..00000000 --- a/src/assessmentset/assessmentset.controller.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { - ApiTags, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiBody, - ApiQuery, - ApiExcludeController, -} from "@nestjs/swagger"; -import { - Controller, - Get, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Request, - Post, - Body, - Query, -} from "@nestjs/common"; -import { AssessmentsetDto } from "./dto/assessmentset.dto"; -import { AssessmentsetService } from "src/adapters/hasura/assessmentset.adapter"; - -// @ApiTags("Assessmentset") -@ApiExcludeController() -@Controller("assessmentset") -export class AssessmentsetController { - constructor(private service: AssessmentsetService) {} - - @Post("/assessmentset") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Assessment set has been created successfully.", - // }) - // @ApiBody({ type: AssessmentsetDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createAssessmentSet( - @Req() request: Request, - @Body() assessmentsetDto: AssessmentsetDto - ) { - return this.service.createAssessmentSet(request, assessmentsetDto); - } - @Get("assessmentset/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Assessment set detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getAssessmentset( - @Param("id") assessmentsetId: string, - @Req() request: Request - ) { - return this.service.getAssessmentset(assessmentsetId, request); - } - - @Post("assessmentset/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Assessment set list." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiQuery({ name: "limit", required: false }) - @ApiQuery({ name: "assessmentsetId", required: false }) - @ApiQuery({ name: "type", required: false }) - @ApiQuery({ name: "title", required: false }) - @ApiQuery({ name: "gradeType", required: false }) - public async searchAssessmentset( - @Req() request: Request, - @Query("limit") limit: string, - @Query("assessmentsetId") assessmentsetId: string, - @Query("type") type: string, - @Query("title") title: string, - @Query("gradeType") gradeType: string - ) { - return await this.service.searchAssessmentset( - limit, - assessmentsetId, - type, - title, - gradeType, - request - ); - } -} diff --git a/src/assessmentset/assessmentset.module.ts b/src/assessmentset/assessmentset.module.ts deleted file mode 100644 index f55d25f1..00000000 --- a/src/assessmentset/assessmentset.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { ScheduleModule } from "@nestjs/schedule"; -import { AssessmentsetController } from "./assessmentset.controller"; -import { AssessmentsetService } from "src/adapters/hasura/assessmentset.adapter"; - -@Module({ - imports: [HttpModule, ScheduleModule.forRoot()], - controllers: [AssessmentsetController], - providers: [AssessmentsetService], -}) -export class AssessmentSetModule {} diff --git a/src/assessmentset/dto/assessmentset-search-dto.ts b/src/assessmentset/dto/assessmentset-search-dto.ts deleted file mode 100644 index 5fa957d3..00000000 --- a/src/assessmentset/dto/assessmentset-search-dto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class AssessmentSetSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; - - @ApiProperty({ - type: Object, - description: "Filters", - }) - @ApiPropertyOptional() - filters: object; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/assessmentset/dto/assessmentset.dto.ts b/src/assessmentset/dto/assessmentset.dto.ts deleted file mode 100644 index a18acbee..00000000 --- a/src/assessmentset/dto/assessmentset.dto.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class AssessmentsetDto { - @Expose() - id: string; - - @Expose() - assessmentsetId: string; - - @ApiProperty({ - description: "Assessment set title ", - }) - @Expose() - title: string; - - @ApiPropertyOptional({ - description: "Assessment set Type", - }) - @Expose() - type: string; - - @ApiProperty({ - description: "Assessmentset type, Ex - marks, boolean, grade", - }) - @Expose() - typeDetails: string; - - @ApiProperty({ - description: "Assessmentset type details", - }) - @Expose() - gradeType: string; - - @ApiProperty({ - description: "Extra data against assessment sent", - }) - @Expose() - options: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} From 6388730ba754209c8d6aa13bac356c1f027a9044 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:52:32 +0530 Subject: [PATCH 202/408] chore : removed mentor tracking module --- src/adapters/hasura/mentorTracking.adapter.ts | 311 ------------------ src/app.module.ts | 1 - src/mentorTracking/dto/feedback-create.dto.ts | 13 - src/mentorTracking/dto/mentorTracking.dto.ts | 70 ---- src/mentorTracking/dto/visitStatus.enum.ts | 4 - .../mentorTracking.controller.ts | 161 --------- src/mentorTracking/mentorTracking.module.ts | 11 - src/mentorTracking/utils/file-upload.utils.ts | 18 - 8 files changed, 589 deletions(-) delete mode 100644 src/adapters/hasura/mentorTracking.adapter.ts delete mode 100644 src/mentorTracking/dto/feedback-create.dto.ts delete mode 100644 src/mentorTracking/dto/mentorTracking.dto.ts delete mode 100644 src/mentorTracking/dto/visitStatus.enum.ts delete mode 100644 src/mentorTracking/mentorTracking.controller.ts delete mode 100644 src/mentorTracking/mentorTracking.module.ts delete mode 100644 src/mentorTracking/utils/file-upload.utils.ts diff --git a/src/adapters/hasura/mentorTracking.adapter.ts b/src/adapters/hasura/mentorTracking.adapter.ts deleted file mode 100644 index 8192a036..00000000 --- a/src/adapters/hasura/mentorTracking.adapter.ts +++ /dev/null @@ -1,311 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable } from "@nestjs/common"; -import { SuccessResponse } from "src/success-response"; -import { MentorTrackingDto } from "src/mentorTracking/dto/mentorTracking.dto"; -import * as FormData from "form-data"; -import { FeedbackCreateDto } from "src/mentorTracking/dto/feedback-create.dto"; -@Injectable() -export class MentorTrackingService { - constructor(private httpService: HttpService) {} - - public async getMentorTracking(mentorId: string, request: any) { - var axios = require("axios"); - - var data = { - query: `query getMentorTracking($mentorTrackingId: uuid!) { - mentortracking(where: {mentorTrackingId: {_eq: $mentorTrackingId}}) { - mentorTrackingId - created_at - feedback - mentorId - scheduleVisitDate - status - teacherId - schoolId - updated_at - visitDate - lastVisited - } -}`, - variables: { mentorTrackingId: mentorId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = await this.mappedResponse(response.data.data.mentortracking); - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async createMentorTracking( - request: any, - mentorTrackingDto: MentorTrackingDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(mentorTrackingDto).forEach((e) => { - if (mentorTrackingDto[e] && mentorTrackingDto[e] != "") { - query += `${e}: "${mentorTrackingDto[e]}", `; - } - }); - var data = { - query: `mutation createMentorTracking { - insert_mentortracking_one(object: {${query}}) { - mentorTrackingId - } -}`, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data.insert_mentortracking_one; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateMentorTracking( - mentorTrackingId: string, - request: any, - mentorTrackingDto: MentorTrackingDto - ) { - const mentorSchema = new MentorTrackingDto(mentorTrackingDto); - let query = ""; - Object.keys(mentorTrackingDto).forEach((e) => { - if ( - mentorTrackingDto[e] && - mentorTrackingDto[e] != "" && - Object.keys(mentorSchema).includes(e) - ) { - if (Array.isArray(mentorTrackingDto[e])) { - query += `${e}: ${JSON.stringify(mentorTrackingDto[e])}, `; - } else { - query += `${e}: "${mentorTrackingDto[e]}", `; - } - } - }); - - var axios = require("axios"); - var data = { - query: `mutation updateMentorTracking($mentorTrackingId: uuid) { - update_mentortracking(where: {mentorTrackingId: {_eq: $mentorTrackingId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - mentorTrackingId: mentorTrackingId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async feedback( - mentorTrackingId: string, - feedbackCreateDto: FeedbackCreateDto, - request: any - ) { - let mentorTrackingDto = feedbackCreateDto; - const mentorSchema = new FeedbackCreateDto(mentorTrackingDto); - let query = ""; - Object.keys(mentorTrackingDto).forEach((e) => { - if ( - mentorTrackingDto[e] && - mentorTrackingDto[e] != "" && - Object.keys(mentorSchema).includes(e) - ) { - if (Array.isArray(mentorTrackingDto[e])) { - query += `${e}: ${JSON.stringify(mentorTrackingDto[e])}, `; - } else { - query += `${e}: ${JSON.stringify(mentorTrackingDto[e])}, `; - } - } - }); - - var axios = require("axios"); - var data = { - query: `mutation updateMentorTracking($mentorTrackingId: uuid) { - update_mentortracking(where: {mentorTrackingId: {_eq: $mentorTrackingId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - mentorTrackingId: mentorTrackingId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async searchMentorTracking( - limit: string, - mentorTrackingId: string, - mentorId: string, - teacherId: string, - schoolId: string, - scheduleVisitDate: Date, - visitDate: Date, - page: number, - status: string, - request: any - ) { - var axios = require("axios"); - - const searchData = { - mentorTrackingId, - mentorId, - teacherId, - schoolId, - scheduleVisitDate, - visitDate, - status, - }; - let offset = 0; - - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - - let query = ""; - Object.keys(searchData).forEach((e) => { - if (searchData[e] && searchData[e] != "") { - query += `${e}:{_eq:"${searchData[e]}"}`; - } - }); - - var data = { - query: `query searchMentorTracking($offset:Int,$limit:Int) { - mentortracking_aggregate { - aggregate { - count - } - } - mentortracking(limit: $limit, offset: $offset, where: {${query}}) { - mentorTrackingId - created_at - feedback - mentorId - scheduleVisitDate - status - teacherId - schoolId - updated_at - visitDate - lastVisited - } -}`, - variables: { - limit: parseInt(limit), - offset: offset, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = await this.mappedResponse(response.data.data.mentortracking); - const count = - response?.data?.data?.mentortracking_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result, - }); - } - - public async mappedResponse(result: any) { - const mentorResponse = result.map((obj: any) => { - const mentorMapping = { - id: obj?.mentorTrackingId ? `${obj.mentorTrackingId}` : "", - mentorTrackingId: obj?.mentorTrackingId - ? `${obj.mentorTrackingId}` - : "", - mentorId: obj?.mentorId ? `${obj.mentorId}` : "", - teacherId: obj?.teacherId ? `${obj.teacherId}` : "", - schoolId: obj?.schoolId ? `${obj.schoolId}` : "", - scheduleVisitDate: obj?.scheduleVisitDate - ? `${obj.scheduleVisitDate}` - : "", - visitDate: obj?.visitDate ? `${obj.visitDate}` : "", - feedback: obj?.feedback ? `${obj.feedback}` : "", - status: obj?.status ? obj.status : "", - lastVisited: obj?.lastVisited ? obj.lastVisited : "", - createdAt: obj?.created_at ? `${obj.created_at}` : "", - updatedAt: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new MentorTrackingDto(mentorMapping); - }); - - return mentorResponse; - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 6fecf2f1..00b01792 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { MentorTrackingModule } from "./mentorTracking/mentorTracking.module"; import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module"; import { AnnouncementsModule } from "./announcements/announcements.module"; import { WorkHistoryModule } from "./workHistory/workHistory.module"; diff --git a/src/mentorTracking/dto/feedback-create.dto.ts b/src/mentorTracking/dto/feedback-create.dto.ts deleted file mode 100644 index 2707c62a..00000000 --- a/src/mentorTracking/dto/feedback-create.dto.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import * as FormData from "form-data"; -export class FeedbackCreateDto { - @ApiProperty({}) - feedback: FormData; - - @ApiProperty({ type: "string", format: "binary" }) - image: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/mentorTracking/dto/mentorTracking.dto.ts b/src/mentorTracking/dto/mentorTracking.dto.ts deleted file mode 100644 index 49461ad5..00000000 --- a/src/mentorTracking/dto/mentorTracking.dto.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsEnum, IsIn, IsNotEmpty, IsString } from "class-validator"; -import { VisitStatus } from "./visitStatus.enum"; - -export class MentorTrackingDto { - @Expose() - id: string; - - @Expose() - mentorTrackingId: string; - - @ApiProperty({}) - @Expose() - mentorId: string; - - @ApiProperty({}) - @Expose() - teacherId: string; - - @ApiProperty({}) - @Expose() - schoolId: string; - - @ApiProperty({ - default: new Date().toISOString().split("T")[0], - }) - @Expose() - scheduleVisitDate: string; - - @ApiProperty({ - default: new Date().toISOString().split("T")[0], - }) - @Expose() - visitDate: string; - - @ApiProperty({}) - @Expose() - feedback: string; - - @IsString() - @IsNotEmpty() - @IsIn([VisitStatus.pending, VisitStatus.visited]) - @IsEnum(VisitStatus) - @ApiPropertyOptional({ - enum: [VisitStatus.pending, VisitStatus.visited], - }) - @Expose() - status: string; - - @ApiProperty({ default: new Date().toISOString().split("T")[0] }) - @Expose() - lastVisited: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/mentorTracking/dto/visitStatus.enum.ts b/src/mentorTracking/dto/visitStatus.enum.ts deleted file mode 100644 index 6a8dc426..00000000 --- a/src/mentorTracking/dto/visitStatus.enum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum VisitStatus { - pending = "pending", - visited = "visited", -} diff --git a/src/mentorTracking/mentorTracking.controller.ts b/src/mentorTracking/mentorTracking.controller.ts deleted file mode 100644 index 2f1a4e7a..00000000 --- a/src/mentorTracking/mentorTracking.controller.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Query, - ValidationPipe, - UsePipes, - UploadedFile, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, - ApiConsumes, - ApiExcludeController, -} from "@nestjs/swagger"; -import { Request } from "@nestjs/common"; -import { MentorTrackingDto } from "./dto/mentorTracking.dto"; -import { MentorTrackingService } from "src/adapters/hasura/mentorTracking.adapter"; -import { FileInterceptor } from "@nestjs/platform-express"; -import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; -import { diskStorage } from "multer"; -import { FeedbackCreateDto } from "./dto/feedback-create.dto"; -// @ApiTags("Mentor Tracking") -@ApiExcludeController() -@Controller("mentortracking") -export class MentorTrackingController { - constructor(private readonly service: MentorTrackingService) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Mentor Tracking detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getMentor(@Param("id") mentorId: string, @Req() request: Request) { - return this.service.getMentorTracking(mentorId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Mentor Tracking has been created successfully.", - // }) - // @ApiBody({ type: MentorTrackingDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @UsePipes(new ValidationPipe({})) - public async createMentor( - @Req() request: Request, - @Body() mentorDto: MentorTrackingDto - ) { - return this.service.createMentorTracking(request, mentorDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Mentor Tracking has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @UsePipes(new ValidationPipe({})) - public async updateMentor( - @Param("id") mentorTrackingId: string, - @Req() request: Request, - @Body() mentorTrackingDto: MentorTrackingDto - ) { - return await this.service.updateMentorTracking( - mentorTrackingId, - request, - mentorTrackingDto - ); - } - - @Put("feedback/:id") - // @ApiConsumes("multipart/form-data") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Group has been updated successfully." }) - @UseInterceptors( - FileInterceptor("image", { - storage: diskStorage({ - destination: process.env.IMAGEPATH, - filename: editFileName, - }), - fileFilter: imageFileFilter, - }) - ) - // @ApiBody({ type: FeedbackCreateDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async feedback( - @Param("id") mentorTrackingId: string, - @Req() request: Request, - @Body() feedbackCreateDto: FeedbackCreateDto, - @UploadedFile() image - ) { - const response = { - image: image?.filename, - }; - Object.assign(feedbackCreateDto, response); - - return await this.service.feedback( - mentorTrackingId, - feedbackCreateDto, - request - ); - } - - @Post("/search") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: " Ok." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "limit", required: false }) - // @ApiQuery({ name: "mentorTrackingId", required: false }) - // @ApiQuery({ name: "mentorId", required: false }) - // @ApiQuery({ name: "teacherId", required: false }) - // @ApiQuery({ name: "schoolId", required: false }) - // @ApiQuery({ name: "scheduleVisitDate", required: false }) - // @ApiQuery({ name: "visitDate", required: false }) - // @ApiQuery({ name: "page", required: false }) - // @ApiQuery({ name: "status", required: false }) - public async searchMentorTracking( - @Query("limit") limit: string, - @Query("mentorTrackingId") mentorTrackingId: string, - @Query("mentorId") mentorId: string, - @Query("teacherId") teacherId: string, - @Query("schoolId") schoolId: string, - @Query("scheduleVisitDate") scheduleVisitDate: Date, - @Query("visitDate") visitDate: Date, - @Query("page") page: number, - @Query("status") status: string, - @Req() request: Request - ) { - return this.service.searchMentorTracking( - limit, - mentorTrackingId, - mentorId, - teacherId, - schoolId, - scheduleVisitDate, - visitDate, - page, - status, - request - ); - } -} diff --git a/src/mentorTracking/mentorTracking.module.ts b/src/mentorTracking/mentorTracking.module.ts deleted file mode 100644 index e0e6078c..00000000 --- a/src/mentorTracking/mentorTracking.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { CacheModule, Module } from "@nestjs/common"; -import { MentorTrackingService } from "src/adapters/hasura/mentorTracking.adapter"; -import { MentorTrackingController } from "./mentorTracking.controller"; - -@Module({ - imports: [HttpModule], - controllers: [MentorTrackingController], - providers: [MentorTrackingService], -}) -export class MentorTrackingModule {} diff --git a/src/mentorTracking/utils/file-upload.utils.ts b/src/mentorTracking/utils/file-upload.utils.ts deleted file mode 100644 index 6bd794ca..00000000 --- a/src/mentorTracking/utils/file-upload.utils.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { extname } from "path"; - -export const imageFileFilter = (req, file, callback) => { - if (!file.originalname.match(/.(jpg|jpeg|png|gif|pdf)$/)) { - return callback(new Error("!"), false); - } - callback(null, true); -}; - -export const editFileName = (req, file, callback) => { - const name = file.originalname.split(".")[0]; - const fileExtName = extname(file.originalname); - const randomName = Array(4) - .fill(null) - .map(() => Math.round(Math.random() * 16).toString(16)) - .join(""); - callback(null, `${name}-${randomName}${fileExtName}`); -}; From 7c723775b7ab4d5df72e93a78ec80df846f38497 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:54:08 +0530 Subject: [PATCH 203/408] chore : removed monitor tracking module --- .../hasura/monitorTracking.adapter.ts | 241 ------------------ src/app.module.ts | 1 - .../dto/monitorTracking.dto.ts | 70 ----- src/monitorTracking/dto/visitStatus.enum.ts | 4 - .../monitorTracking.controller.ts | 119 --------- src/monitorTracking/monitorTracking.module.ts | 12 - 6 files changed, 447 deletions(-) delete mode 100644 src/adapters/hasura/monitorTracking.adapter.ts delete mode 100644 src/monitorTracking/dto/monitorTracking.dto.ts delete mode 100644 src/monitorTracking/dto/visitStatus.enum.ts delete mode 100644 src/monitorTracking/monitorTracking.controller.ts delete mode 100644 src/monitorTracking/monitorTracking.module.ts diff --git a/src/adapters/hasura/monitorTracking.adapter.ts b/src/adapters/hasura/monitorTracking.adapter.ts deleted file mode 100644 index e4312b9a..00000000 --- a/src/adapters/hasura/monitorTracking.adapter.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { HttpService } from "@nestjs/axios"; -import { Injectable } from "@nestjs/common"; -import { SuccessResponse } from "src/success-response"; -import { MonitorTrackingDto } from "src/monitorTracking/dto/monitorTracking.dto"; -@Injectable() -export class MonitorTrackingService { - constructor(private httpService: HttpService) {} - - public async getMonitorTracking(monitorId: string, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetMonitorTracking($monitorTrackingId:uuid) { - monitortracking(where: {monitorTrackingId: {_eq:$monitorTrackingId }}) { - created_at - feedback - monitorTrackingId - scheduleVisitDate - schoolId - monitorId - status - updated_at - visitDate - lastVisited - } - }`, - variables: { monitorTrackingId: monitorId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = await this.mappedResponse(response.data.data.monitortracking); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async createMonitorTracking( - request: any, - monitorTrackingDto: MonitorTrackingDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(monitorTrackingDto).forEach((e) => { - if (monitorTrackingDto[e] && monitorTrackingDto[e] != "") { - query += `${e}: "${monitorTrackingDto[e]}", `; - } - }); - var data = { - query: `mutation CreateMonitorTracking { - insert_monitortracking_one(object: {${query}}) { - monitorTrackingId - } - }`, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data.insert_monitortracking_one; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateMonitorTracking( - monitorTrackingId: string, - request: any, - monitorTrackingDto: MonitorTrackingDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(monitorTrackingDto).forEach((e) => { - if (monitorTrackingDto[e] && monitorTrackingDto[e] != "") { - query += `${e}:"${monitorTrackingDto[e]}"`; - } - }); - - var data = { - query: `mutation UpdatedMonitorTracking($monitorTrackingId:uuid) { - update_monitortracking(where: {monitorTrackingId: {_eq: $monitorTrackingId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - monitorTrackingId: monitorTrackingId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async searchMonitorTracking( - limit: string, - monitorTrackingId: string, - monitorId: string, - schoolId: string, - groupId: string, - scheduleVisitDate: Date, - visitDate: Date, - page: number, - request: any - ) { - var axios = require("axios"); - let offset = 0; - - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - const searchData = { - monitorTrackingId, - monitorId, - schoolId, - groupId, - scheduleVisitDate, - visitDate, - }; - - let query = ""; - Object.keys(searchData).forEach((e) => { - if (searchData[e] && searchData[e] != "") { - query += `${e}:{_eq:"${searchData[e]}"}`; - } - }); - - var data = { - query: `query SearchMonitorTracking($offset:Int,$limit:Int) { - monitortracking_aggregate { - aggregate { - count - } - } - monitortracking(where:{ ${query}}, offset: $offset,limit: $limit) { - created_at - feedback - monitorTrackingId - scheduleVisitDate - status - schoolId - groupId - monitorId - updated_at - visitDate - lastVisited - } - }`, - variables: { limit: parseInt(limit), offset: offset }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = await this.mappedResponse(response.data.data.monitortracking); - const count = - response?.data?.data?.monitortracking_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result, - }); - } - - public async mappedResponse(result: any) { - const monitorResponse = result.map((obj: any) => { - const monitorMapping = { - id: obj?.monitorTrackingId ? `${obj.monitorTrackingId}` : "", - monitorTrackingId: obj?.monitorTrackingId - ? `${obj.monitorTrackingId}` - : "", - monitorId: obj?.monitorId ? `${obj.monitorId}` : "", - schoolId: obj?.schoolId ? `${obj.schoolId}` : "", - groupId: obj?.groupId ? `${obj.groupId}` : "", - scheduleVisitDate: obj?.scheduleVisitDate - ? `${obj.scheduleVisitDate}` - : "", - visitDate: obj?.visitDate ? `${obj.visitDate}` : "", - feedback: obj?.feedback ? `${obj.feedback}` : "", - status: obj?.status ? `${obj.status}` : "", - - lastVisited: obj?.lastVisited ? `${obj.lastVisited}` : "", - createdAt: obj?.created_at ? `${obj.created_at}` : "", - updatedAt: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new MonitorTrackingDto(monitorMapping); - }); - - return monitorResponse; - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 00b01792..34099e75 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { MonitorTrackingModule } from "./monitorTracking/monitorTracking.module"; import { AnnouncementsModule } from "./announcements/announcements.module"; import { WorkHistoryModule } from "./workHistory/workHistory.module"; */ diff --git a/src/monitorTracking/dto/monitorTracking.dto.ts b/src/monitorTracking/dto/monitorTracking.dto.ts deleted file mode 100644 index 79e03261..00000000 --- a/src/monitorTracking/dto/monitorTracking.dto.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; -import { VisitStatus } from "./visitStatus.enum"; -import { IsEnum, IsIn, IsNotEmpty, IsString } from "class-validator"; - -export class MonitorTrackingDto { - @Expose() - id: string; - - @Expose() - monitorTrackingId: string; - - @ApiProperty({}) - @Expose() - monitorId: string; - - @ApiProperty({}) - @Expose() - schoolId: string; - - @ApiProperty({ description: "Group ID (class ID)" }) - @Expose() - groupId: string; - - @ApiProperty({ - default: new Date().toISOString().split("T")[0], - }) - @Expose() - scheduleVisitDate: string; - - @ApiProperty({ - default: new Date().toISOString().split("T")[0], - }) - @Expose() - visitDate: string; - - @ApiProperty({}) - @Expose() - feedback: string; - - @IsString() - @IsNotEmpty() - @IsIn([VisitStatus.pending, VisitStatus.visited]) - @IsEnum(VisitStatus) - @ApiProperty({ - enum: [VisitStatus.pending, VisitStatus.visited], - }) - @Expose() - status: string; - - @ApiProperty({ default: new Date().toISOString().split("T")[0] }) - @Expose() - lastVisited: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - @Expose() - createdBy: string; - - @Expose() - updatedBy: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/monitorTracking/dto/visitStatus.enum.ts b/src/monitorTracking/dto/visitStatus.enum.ts deleted file mode 100644 index 6a8dc426..00000000 --- a/src/monitorTracking/dto/visitStatus.enum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum VisitStatus { - pending = "pending", - visited = "visited", -} diff --git a/src/monitorTracking/monitorTracking.controller.ts b/src/monitorTracking/monitorTracking.controller.ts deleted file mode 100644 index 4b42a3d9..00000000 --- a/src/monitorTracking/monitorTracking.controller.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Put, - Param, - UseInterceptors, - ClassSerializerInterceptor, - SerializeOptions, - Req, - Query, - ValidationPipe, - UsePipes, -} from "@nestjs/common"; -import { - ApiTags, - ApiBody, - ApiOkResponse, - ApiForbiddenResponse, - ApiCreatedResponse, - ApiBasicAuth, - ApiQuery, - ApiExcludeController, -} from "@nestjs/swagger"; -import { Request } from "@nestjs/common"; -import { MonitorTrackingDto } from "./dto/monitorTracking.dto"; -import { MonitorTrackingService } from "src/adapters/hasura/monitorTracking.adapter"; - -// @ApiTags("Monitor Tracking") -@ApiExcludeController() -@Controller("monitortracking") -export class MonitorTrackingController { - constructor(private readonly service: MonitorTrackingService) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Monitor Tracking detail." }) - @SerializeOptions({ - strategy: "excludeAll", - }) - getMonitor(@Param("id") monitorTrackingId: string, @Req() request: Request) { - return this.service.getMonitorTracking(monitorTrackingId, request); - } - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Monitor Tracking has been created successfully.", - // }) - // @ApiBody({ type: MonitorTrackingDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @UsePipes(new ValidationPipe({})) - public async createMonitor( - @Req() request: Request, - @Body() monitorDto: MonitorTrackingDto - ) { - return this.service.createMonitorTracking(request, monitorDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Monitor Tracking has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - @UsePipes(new ValidationPipe({})) - public async updateMonitor( - @Param("id") monitorTrackingId: string, - @Req() request: Request, - @Body() monitorDto: MonitorTrackingDto - ) { - return await this.service.updateMonitorTracking( - monitorTrackingId, - request, - monitorDto - ); - } - - @Post("/search") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: " Ok." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @ApiQuery({ name: "limit", required: false }) - // @ApiQuery({ name: "monitorTrackingId", required: false }) - // @ApiQuery({ name: "monitorId", required: false }) - // @ApiQuery({ name: "schoolId", required: false }) - // @ApiQuery({ name: "groupId", required: false }) - // @ApiQuery({ name: "scheduleVisitDate", required: false }) - // @ApiQuery({ name: "visitDate", required: false }) - // @ApiQuery({ name: "page", required: false }) - public async searchMonitorTracking( - @Query("limit") limit: string, - @Query("monitorTrackingId") monitorTrackingId: string, - @Query("monitorId") monitorId: string, - @Query("schoolId") schoolId: string, - @Query("groupId") groupId: string, - @Query("scheduleVisitDate") scheduleVisitDate: Date, - @Query("visitDate") visitDate: Date, - @Query("page") page: number, - @Req() request: Request - ) { - return this.service.searchMonitorTracking( - limit, - monitorTrackingId, - monitorId, - schoolId, - groupId, - scheduleVisitDate, - visitDate, - page, - request - ); - } -} diff --git a/src/monitorTracking/monitorTracking.module.ts b/src/monitorTracking/monitorTracking.module.ts deleted file mode 100644 index 5dbdab04..00000000 --- a/src/monitorTracking/monitorTracking.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { HttpModule } from "@nestjs/axios"; -import { CacheModule, Module } from "@nestjs/common"; -import { MonitorTrackingService } from "src/adapters/hasura/monitorTracking.adapter"; - -import { MonitorTrackingController } from "./monitorTracking.controller"; - -@Module({ - imports: [HttpModule], - controllers: [MonitorTrackingController], - providers: [MonitorTrackingService], -}) -export class MonitorTrackingModule {} From fdae12284b9b50198b9e698e30d070e6e8669c66 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 8 Apr 2024 18:55:01 +0530 Subject: [PATCH 204/408] add correct error message --- src/user/user.controller.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 916e9471..fe519838 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -84,10 +84,17 @@ export class UserController { result = await this.userAdapter.buildUserAdapter().getUsersDetailsById( userData, response); } - if (userData.cohortId !== null) { + else if (userData.cohortId !== null) { result = await this.userAdapter.buildUserAdapter().getUsersDetailsByCohortId( userData, response); } + if (userData.userId == null && userData.cohortId == null) { + return response.status(400).json({ + statusCode: 400, + error: "Please entire userId or cohortId in query parameters" + }); + } + return response.status(result.statusCode).json(result); } From 5344a1651be6aaa7e410ae664e6db069bd3a2fea Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:57:08 +0530 Subject: [PATCH 205/408] chore : removed announcements module --- src/adapters/announcementsservicelocator.ts | 14 - src/adapters/hasura/announcements.adapter.ts | 313 ------------------ .../announcements.controller.spec.ts | 18 - src/announcements/announcements.controller.ts | 111 ------- src/announcements/announcements.module.ts | 21 -- .../dto/announcements-filter.dto.ts | 84 ----- src/announcements/dto/announcements.dto.ts | 88 ----- src/app.module.ts | 1 - 8 files changed, 650 deletions(-) delete mode 100644 src/adapters/announcementsservicelocator.ts delete mode 100644 src/adapters/hasura/announcements.adapter.ts delete mode 100644 src/announcements/announcements.controller.spec.ts delete mode 100644 src/announcements/announcements.controller.ts delete mode 100644 src/announcements/announcements.module.ts delete mode 100644 src/announcements/dto/announcements-filter.dto.ts delete mode 100644 src/announcements/dto/announcements.dto.ts diff --git a/src/adapters/announcementsservicelocator.ts b/src/adapters/announcementsservicelocator.ts deleted file mode 100644 index 43786ef8..00000000 --- a/src/adapters/announcementsservicelocator.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AnnouncementsFilterDto } from "src/announcements/dto/announcements-filter.dto"; -import { AnnouncementsDto } from "src/announcements/dto/announcements.dto"; - -export interface IServicelocator { - getAnnouncement(announcementId: any, request: any); - getAnnouncementSet(request: any, filters?: AnnouncementsFilterDto); - updateAnnouncement( - announcementId: string, - request: any, - announcementData: AnnouncementsDto - ); - createAnnouncement(request: any, announcementData: AnnouncementsDto); - deleteAnnouncement(announcementId: string, request: any); -} diff --git a/src/adapters/hasura/announcements.adapter.ts b/src/adapters/hasura/announcements.adapter.ts deleted file mode 100644 index a374f53f..00000000 --- a/src/adapters/hasura/announcements.adapter.ts +++ /dev/null @@ -1,313 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { IServicelocator } from "../announcementsservicelocator"; -import { AnnouncementsDto } from "src/announcements/dto/announcements.dto"; -import { AnnouncementsFilterDto } from "src/announcements/dto/announcements-filter.dto"; - -export const AnnouncementsToken = "Announcements"; -// TODO: Refactor as per Shiksha 2.0 -@Injectable() -export class AnnouncementsService implements IServicelocator { - constructor(private httpService: HttpService) {} - baseURL = process.env.REGISTRYHASURA; - adminSecret = process.env.REGISTRYHASURAADMINSECRET; - - //to get details of a given announcement - public async getAnnouncement(announcementId: string, request: any) { - var axios = require("axios"); - var data = { - query: `query getAnnouncement($id:Int!) { - announcements(where: {id: {_eq: $id}}) { - id, - title, - status, - type, - modified_at, - data, - is_pinned, - is_dismissable, - additional_tags, - } - }`, - variables: { - id: announcementId, - }, - }; - var config = { - method: "post", - url: this.baseURL, - headers: { - "x-hasura-admin-secret": this.adminSecret, - "Content-Type": "application/json", - }, - data: data, - }; - - const responseData = await axios(config); - const response = responseData.data.data.announcements; - - let responsedata = await this.mappedResponse(response); - let x = new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: responsedata, - }); - return x; - } - - //to get the data of announcements by page - public async getAnnouncementSet( - request: any, - filters: AnnouncementsFilterDto - ) { - var axios = require("axios"); - - //adding select clause to filters - let selectClause = ``, - queryVar = ``; - let variables = {}; - - //add corr select and data statement to query - if (filters?.pageSize) { - variables["_limit"] = parseInt(filters.pageSize); - } - if (filters?.pageIndex) { - variables["_offset"] = parseInt(filters.pageIndex); - } - if (filters?.title) { - variables["_title"] = `%${filters.title}%`; - queryVar += `$_title: String,`; - selectClause += `title: {_ilike: $_title}`; - } - if (filters?.author) { - variables["_author"] = filters.author; - queryVar += `$_author: [String],`; - selectClause += `author:{_in: $_author},`; - } - if (filters?.isPinned) { - variables["_isPinned"] = filters?.isPinned; - queryVar += `$_isPinned: Boolean,`; - selectClause += `is_pinned: {_eq: $_isPinned},`; - } - if (filters?.pinnedAnnouncementProperties) { - variables["_isDismissable"] = - filters?.pinnedAnnouncementProperties?.isDismissable; - queryVar += `$_isDismissable: Boolean,`; - selectClause += `is_dismissable: {_eq: $_isDismissable},`; - } - if (filters?.status) { - variables["_status"] = filters?.status; - queryVar += `$_status: String,`; - selectClause += `status: {_ilike: $_status},`; - } - if (filters?.announcementType) { - variables["_type"] = filters?.announcementType; - queryVar += `$_type: [String]`; - selectClause += `type: {_in: $_type},`; - } - if (filters?.startDate && filters?.endDate) { - variables["_startDate"] = filters?.startDate; - variables["_endDate"] = filters?.endDate; - queryVar += `$_startDate: timestamptz, $_endDate: timestamptz,`; - selectClause += `modified_at: {_gte: $_startDate, _lte: $_endDate},`; - } - - let data = { - query: `query get_announcement_set($_limit: Int, $_offset: Int, ${queryVar}) { - announcements(limit: $_limit, offset: $_offset, order_by: {modified_at: desc}, where: { ${selectClause} }) { - additional_tags - author - data - id - is_dismissable - is_pinned - modified_at - status - title - type - } - announcements_aggregate(where: {${selectClause}}) { - aggregate { - count - } - } - } - `, - variables: variables, - }; - var config = { - method: "post", - url: this.baseURL, - headers: { - "x-hasura-admin-secret": this.adminSecret, - "Content-Type": "application/json", - }, - data: data, - }; - - const responseData = await axios(config); - const response = responseData.data.data.announcements; - let responsedata = await this.mappedResponse(response); - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: { - count: responseData.data.data.announcements_aggregate.aggregate.count, - data: responsedata, - }, - }); - } - - //to update a given announcement - public async updateAnnouncement( - announcementId: string, - request: any, - announcementsData: AnnouncementsDto - ) { - var axios = require("axios"); - let isPresent: any; - - var updateData = { - query: `mutation updateAnnouncements($id: Int!, $additional_tags: _text = "", $data: String = "", $is_dismissable: Boolean = false, $is_pinned: Boolean = false, $modified_at: timestamptz, $status: String = "",$author: String = "", $title: String = "", $type: String = "") { - update_announcements(_set: {additional_tags: $additional_tags, data: $data, is_dismissable: $is_dismissable, is_pinned: $is_pinned, modified_at: $modified_at, status: $status,author: $author, title: $title, type: $type}, where: {id: {_eq: $id}}) { - affected_rows - }}`, - variables: { - id: parseInt(announcementId), - additional_tags: `{${announcementsData.additionalTags.toString()}}`, - data: announcementsData.data, - is_dismissable: - announcementsData.pinnedAnnouncementProperties?.is_dismissable, - is_pinned: announcementsData.isPinned, - modified_at: announcementsData.dateModified, - status: announcementsData.status, - author: announcementsData.author, - title: announcementsData.title, - type: announcementsData.announcementType, - }, - }; - var updateConfig = { - method: "post", - url: this.baseURL, - headers: { - "x-hasura-admin-secret": this.adminSecret, - "Content-Type": "application/json", - }, - data: updateData, - }; - - const responseData = await axios(updateConfig); - const response = responseData.data; - - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: response, - }); - } - - //to create an announcement - public async createAnnouncement(request: any, announcementsData: any) { - var axios = require("axios"); - var data = { - query: `mutation createAnnouncement($additional_tags: _text, $data: String = "", $is_dismissable: Boolean = false, $is_pinned: Boolean = false, $status: String = "", $title: String = "", $type: String = "") { - insert_announcements_one(object: {additional_tags: $additional_tags, data: $data, is_dismissable: $is_dismissable, is_pinned: $is_pinned, status: $status, title: $title, type: $type}) { - id - } - } - `, - variables: { - additional_tags: `{${announcementsData?.additionalTags?.toString()}}`, - data: announcementsData.data, - is_dismissable: - announcementsData.pinnedAnnouncementProperties?.is_dismissable, - is_pinned: announcementsData.isPinned, - status: announcementsData.status, - title: announcementsData.title, - type: announcementsData.announcementType, - }, - }; - - var config = { - method: "post", - url: this.baseURL, - headers: { - "x-hasura-admin-secret": this.adminSecret, - "Content-Type": "application/json", - }, - data: data, - }; - - const responseData = await axios(config); - const response = responseData.data; - let final = { - ...response, - result: { - Announcements: { osid: response.data.insert_announcements_one.id }, - }, - }; - - return new SuccessResponse({ - statusCode: 200, - message: "ok.", - data: final, - }); - } - - //to delete an announcement - public async deleteAnnouncement(announcementId: string, request: any) { - var axios = require("axios"); - var data = { - query: `mutation delete_announcement($id: Int!) { - delete_announcements_by_pk(id: $id){ - id - } - } - `, - variables: { - id: announcementId, - }, - }; - var config = { - method: "post", - url: this.baseURL, - headers: { - "x-hasura-admin-secret": this.adminSecret, - "Content-Type": "application/json", - }, - data: data, - }; - - const responseData = await axios(config); - const response = responseData.data.data; - let x = new SuccessResponse({ - statusCode: 200, - message: "Deleted announcement successfully", - data: response, - }); - return x; - } - - public async mappedResponse(result: any) { - const announcementResponse = result.map((obj: any) => { - const announcementMapping = { - announcementId: obj?.id ? `${obj.id}` : "", - title: obj?.title ? `${obj.title}` : "", - status: obj?.status ? `${obj.status}` : "", - author: obj?.author ? `${obj.author}` : "", - announcementType: obj?.type ? `${obj.type}` : "", - dateModified: obj?.modified_at ? `${obj.modified_at}` : "", - data: obj?.data ? `${obj.data}` : "", - isPinned: obj?.is_pinned ? obj.is_pinned : false, - additionalTags: obj?.additional_tags ? obj.additional_tags : [], - pinnedAnnouncementProperties: { - isDismissable: obj?.is_dismissable ?? false, - }, - }; - return new AnnouncementsDto(announcementMapping); - }); - - return announcementResponse; - } -} diff --git a/src/announcements/announcements.controller.spec.ts b/src/announcements/announcements.controller.spec.ts deleted file mode 100644 index 25f0980d..00000000 --- a/src/announcements/announcements.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from "@nestjs/testing"; -import { AnnouncementsController } from "./announcements.controller"; - -describe("AnnouncementsController", () => { - let controller: AnnouncementsController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [AnnouncementsController], - }).compile(); - - controller = module.get(AnnouncementsController); - }); - - it("should be defined", () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/announcements/announcements.controller.ts b/src/announcements/announcements.controller.ts deleted file mode 100644 index 582efda5..00000000 --- a/src/announcements/announcements.controller.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { - Body, - ClassSerializerInterceptor, - Controller, - Delete, - Get, - Inject, - Param, - Post, - Put, - Query, - Req, - Request, - UseInterceptors, -} from "@nestjs/common"; -import { - ApiBasicAuth, - ApiBody, - ApiConsumes, - ApiCreatedResponse, - ApiExcludeController, - ApiForbiddenResponse, - ApiOkResponse, -} from "@nestjs/swagger"; -import { IServicelocator } from "src/adapters/announcementsservicelocator"; -import { - AnnouncementsService, - AnnouncementsToken, -} from "src/adapters/hasura/announcements.adapter"; -import { AnnouncementsFilterDto } from "./dto/announcements-filter.dto"; -import { AnnouncementsDto } from "./dto/announcements.dto"; -@ApiExcludeController() -@Controller("announcements") -export class AnnouncementsController { - constructor( - private hasuraService: AnnouncementsService, - @Inject(AnnouncementsToken) private provider: IServicelocator - ) {} - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Get announcement detail" }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - public async getAnnouncement( - @Param("id") announcementId: string, - @Req() request: Request - ) { - return this.hasuraService.getAnnouncement(announcementId, request); - } - - @Get("") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Get announcements" }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - public async getAnnouncementSet( - @Query() query: AnnouncementsFilterDto, - @Req() request: Request - ) { - return this.hasuraService.getAnnouncementSet(request, query); - } - - @Put("/:id") - // @ApiConsumes("multipart/form-data") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Announcement has been Updated successfully.", - // }) - // @ApiBody({ type: AnnouncementsDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateAnnouncement( - @Param("id") announcementId: string, - @Req() request: Request, - @Body() announcementData: any - ) { - const updatedData = JSON.parse(announcementData?.data); - return this.hasuraService.updateAnnouncement( - announcementId, - request, - updatedData - ); - } - - @Post() - // @ApiConsumes("multipart/form-data") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Announcement has been created successfully.", - // }) - // @ApiBody({ type: AnnouncementsDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - public async createAnnouncement( - @Req() request: Request, - @Body() announcementData: AnnouncementsDto - ) { - return this.hasuraService.createAnnouncement(request, announcementData); - } - - @Delete("/:id") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: "Deleted the announcement " }) - public async deleteAnnouncement( - @Param("id") announcementId: string, - @Req() request: Request - ) { - return this.hasuraService.deleteAnnouncement(announcementId, request); - } -} diff --git a/src/announcements/announcements.module.ts b/src/announcements/announcements.module.ts deleted file mode 100644 index 622c3c19..00000000 --- a/src/announcements/announcements.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { ScheduleModule } from "@nestjs/schedule"; -import { - AnnouncementsService, - AnnouncementsToken, -} from "../adapters/hasura/announcements.adapter"; -import { AnnouncementsController } from "./announcements.controller"; - -@Module({ - imports: [HttpModule, ScheduleModule.forRoot()], - providers: [ - AnnouncementsService, - { - provide: AnnouncementsToken, - useClass: AnnouncementsService, - }, - ], - controllers: [AnnouncementsController], -}) -export class AnnouncementsModule {} diff --git a/src/announcements/dto/announcements-filter.dto.ts b/src/announcements/dto/announcements-filter.dto.ts deleted file mode 100644 index d02a58f9..00000000 --- a/src/announcements/dto/announcements-filter.dto.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiPropertyOptional } from "@nestjs/swagger"; - -export class AnnouncementsFilterDto { - @ApiPropertyOptional({ - type: String, - description: "Page size(limit) for the announcement set", - }) - @Expose() - pageSize: string; - - @ApiPropertyOptional({ - type: String, - description: "Page index(offset) for the announcement", - }) - @Expose() - pageIndex: string; - - @ApiPropertyOptional({ - type: String, - description: "The title of announcement", - default: "", - }) - @Expose() - title: string; - - @ApiPropertyOptional({ - type: Array, - description: "The author of announcement", - default: "", - }) - @Expose() - author: string[]; - - @ApiPropertyOptional({ - type: Boolean, - description: "Whether announcement is pinned or not", - default: false, - }) - @Expose() - isPinned: boolean; - - @ApiPropertyOptional({ - type: Object, - description: "Additional properties for pinned announcements", - default: {}, - }) - @Expose() - pinnedAnnouncementProperties: any; - - @ApiPropertyOptional({ - type: String, - description: "The status of the announcement-draft or published", - default: "", - }) - @Expose() - status: string; - - @ApiPropertyOptional({ - type: Array, - description: "The type of announcement", - default: "", - }) - @Expose() - announcementType: string[]; - - @ApiPropertyOptional({ - type: String, - description: "Start date for filtering announcement", - }) - @Expose() - startDate: string; - - @ApiPropertyOptional({ - type: String, - description: "End date for filtering announcement", - }) - @Expose() - endDate: string; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/announcements/dto/announcements.dto.ts b/src/announcements/dto/announcements.dto.ts deleted file mode 100644 index d1f334f7..00000000 --- a/src/announcements/dto/announcements.dto.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - -export class AnnouncementsDto { - @ApiProperty({ - type: String, - description: "The id of the announcement ", - default: "", - }) - @Expose() - announcementId: string; - - @ApiPropertyOptional({ - type: String, - description: "The data of the announcement", - default: "", - }) - @Expose() - data: string; - - @ApiProperty({ - type: String, - description: "The type of announcement", - default: "", - }) - @Expose() - announcementType: string; - - @ApiProperty({ - type: String, - description: "The title of announcement", - default: "", - }) - @Expose() - title: string; - - @ApiProperty({ - type: String, - description: "The date modified", - default: "", - }) - @Expose() - dateModified: string; - - @ApiPropertyOptional({ - type: Array, - description: "Additional properties of an announcement", - default: "", - }) - @Expose() - additionalTags: string[]; - - @ApiProperty({ - type: Boolean, - description: "Whether announcement is pinned or not", - default: false, - }) - @Expose() - isPinned: boolean; - - @ApiProperty({ - type: String, - description: "The status of the announcement-draft or published", - default: "", - }) - @Expose() - status: string; - - @ApiProperty({ - type: String, - description: "The author of the announcement", - default: "", - }) - @Expose() - author: string; - - @ApiPropertyOptional({ - type: Object, - description: "Additional properties for pinned announcements", - default: {}, - }) - @Expose() - pinnedAnnouncementProperties: any; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 34099e75..0067f7b0 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { AnnouncementsModule } from "./announcements/announcements.module"; import { WorkHistoryModule } from "./workHistory/workHistory.module"; */ // In use for Shiksha 2.0 From 0e845b34234aeab0079523407ff5b89de824a759 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 8 Apr 2024 18:58:35 +0530 Subject: [PATCH 206/408] chore : removed workHistory module --- src/adapters/hasura/workhistory.adapter.ts | 263 -------------- src/app.module.ts | 1 - src/workHistory/dto/user-work-history.dto.ts | 354 ------------------- src/workHistory/dto/work-history.dto.ts | 104 ------ src/workHistory/workHistory.controller.ts | 110 ------ src/workHistory/workHistory.module.ts | 11 - 6 files changed, 843 deletions(-) delete mode 100644 src/adapters/hasura/workhistory.adapter.ts delete mode 100644 src/workHistory/dto/user-work-history.dto.ts delete mode 100644 src/workHistory/dto/work-history.dto.ts delete mode 100644 src/workHistory/workHistory.controller.ts delete mode 100644 src/workHistory/workHistory.module.ts diff --git a/src/adapters/hasura/workhistory.adapter.ts b/src/adapters/hasura/workhistory.adapter.ts deleted file mode 100644 index 9e258984..00000000 --- a/src/adapters/hasura/workhistory.adapter.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { WorkHistoryDto } from "../../workHistory/dto/work-history.dto"; - -@Injectable() -export class WorkHistoryService { - constructor(private httpService: HttpService) {} - - public async createWorkHistory(request: any, workHistoryDto: WorkHistoryDto) { - var axios = require("axios"); - - let query = ""; - Object.keys(workHistoryDto).forEach((e) => { - if (workHistoryDto[e] && workHistoryDto[e] != "") { - query += `${e}: "${workHistoryDto[e]}", `; - } - }); - - var data = { - query: `mutation CreateWorkHistory { - insert_workhistory_one(object: {${query}}) { - workHistoryId - } - } - `, - variables: {}, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - const result = response.data.data.insert_workhistory_one; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async updateWorkHistory( - id: string, - request: any, - workHistoryDto: WorkHistoryDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(workHistoryDto).forEach((e) => { - if (workHistoryDto[e] && workHistoryDto[e] != "") { - query += `${e}: "${workHistoryDto[e]}", `; - } - }); - - var data = { - query: `mutation UpdateWorkHistory($workHistoryId:uuid) { - update_workhistory(where: {workHistoryId: {_eq: $worksHitoryId}}, _set: {${query}}) { - affected_rows - } -}`, - variables: { - workHistoryId: id, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - const result = response.data.data; - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async getWorkHistory(workHistoryId: any, request: any) { - var axios = require("axios"); - - var data = { - query: `query GetWorkHistory($workHistoryId:uuid) { - workhistory(where: {workHistoryId: {_eq: $workHistoryId}}) { - workHistoryId - cadre - created_at - dateOfJoining - dateOfOrder - dateOfRelieving - joiningDesignation - leavingDesignation - modeOfPosting - placeOfPosting - reason - remark - role - transferOrderNumber - updated_at - userId - organizationName - } - } - `, - variables: { workHistoryId: workHistoryId }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - let result = await this.mappedResponse(response?.data?.data?.workhistory); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } - - public async searchWorkHistory( - limit: string, - workHistoryId: string, - userId: string, - dateOfJoining: string, - dateOfRelieving: string, - page: number, - request: any - ) { - var axios = require("axios"); - - let offset = 0; - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - - const searchData = { - workHistoryId: workHistoryId, - userId: userId, - dateOfJoining: dateOfJoining, - dateOfRelieving: dateOfRelieving, - }; - - let query = ""; - Object.keys(searchData).forEach((e) => { - if (searchData[e] && searchData[e] != "") { - query += `${e}:{_eq:"${searchData[e]}"}`; - } - }); - - var data = { - query: `query SearchWorkHistory($limit:Int, $offset:Int) { - workhistory_aggregate { - aggregate { - count - } - } - workhistory(where:{ ${query}}, limit: $limit, offset: $offset,) { - workHistoryId - cadre - created_at - dateOfJoining - dateOfOrder - dateOfRelieving - joiningDesignation - leavingDesignation - modeOfPosting - placeOfPosting - reason - remark - role - transferOrderNumber - updated_at - userId - organizationName - } - }`, - variables: { - limit: parseInt(limit), - offset: offset, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - let result = await this.mappedResponse(response.data.data.workhistory); - const count = response?.data?.data?.workhistory_aggregate?.aggregate?.count; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result, - }); - } - - public async mappedResponse(result: any) { - const workHistoryResponse = result.map((obj: any) => { - const workHistoryMapping = { - id: obj?.workHistoryId ? `${obj.workHistoryId}` : "", - workHistoryId: obj?.workHistoryId ? `${obj.workHistoryId}` : "", - userId: obj?.userId ? `${obj.userId}` : "", - role: obj?.role ? `${obj.role}` : "", - joiningDesignation: obj?.joiningDesignation - ? `${obj.joiningDesignation}` - : "", - leavingDesignation: obj?.leavingDesignation - ? `${obj.leavingDesignation}` - : "", - dateOfJoining: obj?.dateOfJoining ? obj.dateOfJoining : "", - dateOfRelieving: obj?.dateOfRelieving ? obj.dateOfRelieving : "", - reason: obj?.reason ? `${obj.reason}` : "", - remark: obj?.remark ? `${obj.remark}` : "", - cadre: obj?.cadre ? `${obj.cadre}` : "", - transferOrderNumber: obj?.transferOrderNumber - ? `${obj.transferOrderNumber}` - : "", - placeOfPosting: obj?.placeOfPosting ? `${obj.placeOfPosting}` : "", - dateOfOrder: obj?.dateOfOrder ? obj.dateOfOrder : "", - modeOfPosting: obj?.modeOfPosting ? `${obj.modeOfPosting}` : "", - organizationName: obj?.organizationName - ? `${obj.organizationName}` - : "", - createdAt: obj?.created_at ? `${obj.created_at}` : "", - updatedAt: obj?.updated_at ? `${obj.updated_at}` : "", - }; - return new WorkHistoryDto(workHistoryMapping); - }); - - return workHistoryResponse; - } -} diff --git a/src/app.module.ts b/src/app.module.ts index 0067f7b0..e2e05bae 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,6 @@ import { AppService } from "./app.service"; /* import { ConfigurationModule } from "./configs/configuration.module"; -import { WorkHistoryModule } from "./workHistory/workHistory.module"; */ // In use for Shiksha 2.0 import { DatabaseModule } from "./common/database.module"; diff --git a/src/workHistory/dto/user-work-history.dto.ts b/src/workHistory/dto/user-work-history.dto.ts deleted file mode 100644 index 9886c824..00000000 --- a/src/workHistory/dto/user-work-history.dto.ts +++ /dev/null @@ -1,354 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsEmail } from "class-validator"; - -export class UserWorkHistoryDto { - @Expose() - workHistoryId: string; - - @ApiProperty({ - type: String, - description: "ID of the user for which posting info is stored", - }) - @Expose() - userId: string; - - @ApiProperty({ - type: String, - description: "role of the user ", - }) - @Expose() - role: string; - - @ApiProperty({ - type: String, - description: "Designation of the user at time of joining that posting", - }) - @Expose() - joiningDesignation: string; - - @ApiProperty({ - type: String, - description: "Designation of the user while leaving that posting", - }) - @Expose() - leavingDesignation: string; - - @ApiProperty({ - type: String, - description: "Date of joining in that posting", - default: new Date().toISOString().split("T")[0], - }) - @Expose() - dateOfJoining: Date; - - @ApiProperty({ - type: String, - description: "Date of relieving from that posting", - default: new Date().toISOString().split("T")[0], - }) - @Expose() - dateOfRelieving: Date; - - @ApiProperty({ - type: String, - description: "Reason of closure of that posting", - }) - @Expose() - reason: string; - - @ApiProperty({ - type: String, - description: "any remark", - }) - @Expose() - remark: string; - - @ApiProperty({}) - @Expose() - cadre: string; - - @ApiProperty({}) - @Expose() - transferOrderNumber: string; - - @ApiProperty({}) - @Expose() - placeOfPosting: string; - - @ApiProperty({ - default: new Date().toISOString().split("T")[0], - }) - @Expose() - dateOfOrder: string; - - @ApiProperty({}) - @Expose() - modeOfPosting: string; - - @ApiProperty() - @Expose() - refId1: string; - - @ApiProperty() - @Expose() - refId2: string; - - @ApiProperty() - @Expose() - refId3: string; - - @ApiProperty({ - type: String, - description: "The first name of the user", - }) - @Expose() - firstName: string; - - @ApiProperty({ - type: String, - description: "The middle name of the user", - }) - @Expose() - middleName: string; - - @ApiProperty({ - type: String, - description: "The lastname of the user", - }) - @Expose() - lastName: string; - - @ApiProperty({ - type: String, - description: "The contact number of the user", - }) - @Expose() - phoneNumber: string; - - @ApiProperty({ - type: String, - description: "The email of the user", - }) - @Expose() - @IsEmail() - email: string; - - @ApiProperty() - @Expose() - aadhaar: string; - - @ApiProperty({ - type: String, - description: "The gender of the user", - }) - @Expose() - gender: string; - - @ApiProperty({ - type: String, - description: "The socialCategory of the user", - }) - @Expose() - socialCategory: string; - - @ApiProperty({ - type: String, - description: "The birthDate of the user", - }) - @Expose() - birthDate: string; - - @ApiProperty({ - type: String, - description: "The designation of the user", - }) - @Expose() - designation: string; - - @ApiProperty({ - type: String, - description: "The profQualification of the user", - }) - @Expose() - profQualification: string; - - @ApiProperty({ - type: String, - description: "The joiningDate of the user", - }) - @Expose() - joiningDate: string; - - @ApiProperty({ - type: [String], - description: "The subjectId of the user", - }) - @Expose() - subjectIds: [string]; - - @ApiProperty({ - type: String, - description: "The bloodGroup of the user", - }) - @Expose() - bloodGroup: string; - - @ApiProperty({ - type: String, - description: "The maritalStatus of the user", - }) - @Expose() - maritalStatus: string; - - @ApiProperty({ - type: String, - description: "The compSkills of the user", - }) - @Expose() - compSkills: string; - - @ApiProperty({ - type: String, - description: "The disability of the user", - }) - @Expose() - disability: string; - - @ApiProperty({ - type: String, - description: "The religion of the user", - }) - @Expose() - religion: string; - - @ApiProperty({ - type: String, - description: "The homeDistance of the user", - }) - @Expose() - homeDistance: string; - - @ApiProperty({ - type: String, - description: "The schoolId of the user", - }) - @Expose() - schoolId: string; - - @ApiPropertyOptional() - @Expose() - address: string; - - @ApiProperty() - @Expose() - village: string; - - @ApiProperty() - @Expose() - block: string; - - @ApiProperty() - @Expose() - district: string; - - @ApiProperty() - @Expose() - stateId: string; - - @ApiProperty() - @Expose() - pincode: string; - - @ApiProperty() - @Expose() - locationId: string; - - @ApiProperty({ - type: String, - description: "The retirementDate of the user", - }) - @Expose() - retirementDate: string; - - @ApiProperty({ - type: String, - description: "The workingStatus of the user", - }) - @Expose() - workingStatus: string; - - @ApiProperty({ - type: String, - description: "The image of the user", - }) - @Expose() - image: string; - - @ApiProperty({ - type: String, - description: "The employmentType of the user", - }) - @Expose() - employmentType: string; - - @ApiProperty({ - type: String, - description: "The status of the user", - }) - @Expose() - status: string; - - @ApiProperty({ - type: String, - description: "The deactivation reason of the user", - }) - @Expose() - deactivationReason: string; - - @Expose() - workHistory: string; - - @ApiProperty() - @Expose() - reportsTo: string; - - @ApiPropertyOptional() - @Expose() - metaData: [string]; - - @ApiPropertyOptional() - @Expose() - fcmToken: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - this.workHistoryId = obj?.workHistoryId ? `${obj.workHistoryId}` : ""; - this.userId = obj?.userId ? `${obj.userId}` : ""; - this.role = obj?.role ? `${obj.role}` : ""; - this.joiningDesignation = obj?.joiningDesignation - ? `${obj.joiningDesignation}` - : ""; - this.leavingDesignation = obj?.leavingDesignation - ? `${obj.leavingDesignation}` - : ""; - this.dateOfJoining = obj?.dateOfJoining ? obj.dateOfJoining : ""; - this.dateOfRelieving = obj?.dateOfRelieving ? obj.dateOfRelieving : ""; - this.reason = obj?.reason ? `${obj.reason}` : ""; - this.remark = obj?.remark ? `${obj.remark}` : ""; - this.cadre = obj?.cadre ? `${obj.cadre}` : ""; - this.transferOrderNumber = obj?.transferOrderNumber - ? `${obj.transferOrderNumber}` - : ""; - this.placeOfPosting = obj?.placeOfPosting ? `${obj.placeOfPosting}` : ""; - this.dateOfOrder = obj?.dateOfOrder ? obj.dateOfOrder : ""; - this.modeOfPosting = obj?.modeOfPosting ? `${obj.modeOfPosting}` : ""; - this.createdAt = obj?.created_at ? `${obj.created_at}` : ""; - this.updatedAt = obj?.updated_at ? `${obj.updated_at}` : ""; - } -} diff --git a/src/workHistory/dto/work-history.dto.ts b/src/workHistory/dto/work-history.dto.ts deleted file mode 100644 index dd4ae301..00000000 --- a/src/workHistory/dto/work-history.dto.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; - -export class WorkHistoryDto { - @Expose() - workHistoryId: string; - - @Expose() - id: string; - - @ApiProperty({ - type: String, - description: "ID of the user for which posting info is stored", - }) - @Expose() - userId: string; - - @ApiProperty({ - type: String, - description: "role of the user ", - }) - @Expose() - role: string; - - @ApiProperty({ - type: String, - description: "Designation of the user at time of joining that posting", - }) - @Expose() - joiningDesignation: string; - - @ApiProperty({ - type: String, - description: "Designation of the user while leaving that posting", - }) - @Expose() - leavingDesignation: string; - - @ApiProperty({ - type: String, - description: "Date of joining in that posting", - default: new Date().toISOString().split("T")[0], - }) - @Expose() - dateOfJoining: Date; - - @ApiProperty({ - type: String, - description: "Date of relieving from that posting", - default: new Date().toISOString().split("T")[0], - }) - @Expose() - dateOfRelieving: Date; - - @ApiProperty({ - type: String, - description: "Reason of closure of that posting", - }) - @Expose() - reason: string; - - @ApiProperty({ - type: String, - description: "any remark", - }) - @Expose() - remark: string; - - @ApiProperty({}) - @Expose() - cadre: string; - - @ApiProperty({}) - @Expose() - transferOrderNumber: string; - - @ApiProperty({}) - @Expose() - placeOfPosting: string; - - @ApiProperty({ - default: new Date().toISOString().split("T")[0], - }) - @Expose() - dateOfOrder: string; - - @ApiProperty({}) - @Expose() - modeOfPosting: string; - - @ApiProperty({}) - @Expose() - organizationName: string; - - @Expose() - createdAt: string; - - @Expose() - updatedAt: string; - - constructor(obj: any) { - Object.assign(this, obj); - } -} diff --git a/src/workHistory/workHistory.controller.ts b/src/workHistory/workHistory.controller.ts deleted file mode 100644 index 3f822c79..00000000 --- a/src/workHistory/workHistory.controller.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - ApiBasicAuth, - ApiBody, - ApiCreatedResponse, - ApiExcludeController, - ApiForbiddenResponse, - ApiOkResponse, - ApiQuery, - ApiTags, -} from "@nestjs/swagger"; -import { - Body, - ClassSerializerInterceptor, - Controller, - Get, - Param, - Query, - Post, - Put, - Req, - SerializeOptions, - UseInterceptors, - Request, -} from "@nestjs/common"; - -import { WorkHistoryService } from "../adapters/hasura/workhistory.adapter"; -import { WorkHistoryDto } from "./dto/work-history.dto"; - -// @ApiTags("Work History") -@ApiExcludeController() -@Controller("workhistory") -export class WorkHistoryController { - constructor(private service: WorkHistoryService) {} - - @Post() - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Work History has been created successfully.", - // }) - // @ApiBody({ type: WorkHistoryDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async createWorkHistory( - @Req() request: Request, - @Body() workHistoryDto: WorkHistoryDto - ) { - return this.service.createWorkHistory(request, workHistoryDto); - } - - @Put("/:id") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ - // description: "Work History has been updated successfully.", - // }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateWorkHistory( - @Param("id") id: string, - @Req() request: Request, - @Body() workHistoryDto: WorkHistoryDto - ) { - return await this.service.updateWorkHistory(id, request, workHistoryDto); - } - - @Get("/:id") - @UseInterceptors(ClassSerializerInterceptor) - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Work History detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - public async getWorkHistory( - @Param("id") workHistoryId: string, - @Req() request: Request - ) { - return await this.service.getWorkHistory(workHistoryId, request); - } - - @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "Work History list." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) - // @ApiQuery({ name: "limit", required: false }) - // @ApiQuery({ name: "workHistoryId", required: false }) - // @ApiQuery({ name: "userId", required: false }) - // @ApiQuery({ name: "dateOfJoining", required: false }) - // @ApiQuery({ name: "dateOfRelieving", required: false }) - // @ApiQuery({ name: "page", required: false }) - public async searchWorkHistory( - @Query("limit") limit: string, - @Query("workHistoryId") workHistoryId: string, - @Query("userId") userId: string, - @Query("dateOfJoining") dateOfJoining: string, - @Query("dateOfRelieving") dateOfRelieving: string, - @Query("page") page: number, - @Req() request: Request - ) { - return await this.service.searchWorkHistory( - limit, - workHistoryId, - userId, - dateOfJoining, - dateOfRelieving, - page, - request - ); - } -} diff --git a/src/workHistory/workHistory.module.ts b/src/workHistory/workHistory.module.ts deleted file mode 100644 index 6c8eeeaf..00000000 --- a/src/workHistory/workHistory.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from "@nestjs/common"; -import { HttpModule } from "@nestjs/axios"; -import { WorkHistoryService } from "../adapters/hasura/workhistory.adapter"; -import { WorkHistoryController } from "./workHistory.controller"; - -@Module({ - imports: [HttpModule], - controllers: [WorkHistoryController], - providers: [WorkHistoryService], -}) -export class WorkHistoryModule {} From 4afe34f518c664ee96dabe34e401b0de7f41709d Mon Sep 17 00:00:00 2001 From: Manoj L Date: Wed, 10 Apr 2024 10:29:46 +0530 Subject: [PATCH 207/408] Create .coderabbit.yaml --- .coderabbit.yaml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..236b5a78 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,38 @@ +language: "en" + +early_access: false + +reviews: + request_changes_workflow: true + high_level_summary: true + poem: false + review_status: true + collapse_walkthrough: false + path_filters: + - "!**/.xml" + path_instructions: + - path: "**/*.js" + instructions: "Review the JavaScript code for conformity with the Google JavaScript style guide, highlighting any deviations." + - path: "**/*.ts" + instructions: | + "Review the JavaScript code for conformity with the Google JavaScript style guide, highlighting any deviations. Ensure that: + - The code adheres to best practices associated with nodejs. + - The code adheres to best practices associated with nestjs framework. + - The code adheres to best practices recommended for performance. + - The code adheres to similar naming conventions for controllers, models, services, methods, variables." + auto_review: + enabled: true + ignore_title_keywords: + - "WIP" + - "DO NOT MERGE" + drafts: false + base_branches: + - "master" + - "dev" + - "feat/*" + - "feat-*" + - "release-*" + - "Shiksha-2.0" + +chat: + auto_reply: true From 577890319b1b425b425f0e020b49afe642d723b1 Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 10 Apr 2024 11:44:42 +0530 Subject: [PATCH 208/408] Role API Fixed --- src/rbac/role/dto/role.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rbac/role/dto/role.dto.ts b/src/rbac/role/dto/role.dto.ts index 93d7950e..c254a6ff 100644 --- a/src/rbac/role/dto/role.dto.ts +++ b/src/rbac/role/dto/role.dto.ts @@ -3,8 +3,8 @@ import { ApiProperty } from "@nestjs/swagger"; import {IsNotEmpty,IsString, IsUUID} from "class-validator" export class RoleDto { + @Expose() - @IsUUID() roleId: string; @ApiProperty({ From 0886f782ed37d565f5cec9dd3cd60b6e8dee1ec0 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 10 Apr 2024 12:48:38 +0530 Subject: [PATCH 209/408] RBAC: Set condition on save data --- src/adapters/postgres/rbac/role-adapter.ts | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index 62ee33c0..ec9cc1df 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -15,12 +15,31 @@ export class PostgresRoleService { ) { } public async createRole(request: any, roleDto: RoleDto) { try { - const response = await this.roleRepository.save(roleDto); - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Ok.", - data: response, - }); + // Convert role name to lowercase + roleDto.roleName = roleDto.roleName.toLowerCase(); + + // Check if role name already exists + const existingRole = await this.roleRepository.findOne({ where: { roleName: roleDto.roleName } }) + if (existingRole) { + return new SuccessResponse({ + statusCode: HttpStatus.FORBIDDEN, + message: "Role name already exists.", + data: existingRole, + }); + }else{ + // Convert roleDto to lowercase + const roleDtoLowercase = { + ...roleDto, + roleName: roleDto.roleName.toLowerCase() + }; + + const response = await this.roleRepository.save(roleDtoLowercase); + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: response, + }); + } } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, From d364740c14efcf96466da1aa7f3d627d19926669 Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 10 Apr 2024 14:19:50 +0530 Subject: [PATCH 210/408] Updated Create user Reponse --- src/adapters/postgres/user-adapter.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index dad205a1..058accaf 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -284,18 +284,18 @@ export class PostgresUserService { const token = keycloakResponse.data.access_token; let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) if (checkUserinKeyCloakandDb) { - return new ErrorResponse({ - errorCode: "400", - errorMessage: "User Already Exists", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.FORBIDDEN, + errorMessage: "User Already Exist", }); } resKeycloak = await createUserInKeyCloak(userSchema, token).catch( (error) => { errKeycloak = error.response?.data.errorMessage; - return new ErrorResponse({ - errorCode: "500", - errorMessage: "Someting went wrong", + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, }); } ); @@ -313,9 +313,9 @@ export class PostgresUserService { } let result = await this.updateCustomFields(userId, fieldData); if (!result) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: `Error is ${result}`, + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: `Error is ${result}`, }); } } @@ -326,9 +326,9 @@ export class PostgresUserService { data: result, }); } catch (e) { - return new ErrorResponse({ - errorCode: "500", - errorMessage: `Error is ${e}`, + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: `Error is ${e}`, }); } } From 04eae3586f2bce1124ec9e050e023eee58f71746 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 10 Apr 2024 17:52:12 +0530 Subject: [PATCH 211/408] Fix[Privilege CRUD API] --- src/adapters/hasura/rbac/privilege.adapter.ts | 9 +- .../postgres/rbac/privilege-adapter.ts | 179 ++++++++++++++++++ src/adapters/privilegeservicelocator.ts | 14 ++ src/rbac/privilege/dto/privilege.dto.ts | 12 +- .../privilege/entities/privilege.entity.ts | 3 + src/rbac/privilege/privilege.controller.ts | 84 ++++++++ src/rbac/privilege/privilegeadapter.ts | 14 +- 7 files changed, 304 insertions(+), 11 deletions(-) create mode 100644 src/adapters/privilegeservicelocator.ts diff --git a/src/adapters/hasura/rbac/privilege.adapter.ts b/src/adapters/hasura/rbac/privilege.adapter.ts index bf5904b4..0649eba2 100644 --- a/src/adapters/hasura/rbac/privilege.adapter.ts +++ b/src/adapters/hasura/rbac/privilege.adapter.ts @@ -1,9 +1,16 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; +import { PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; @Injectable() export class HasuraPrivilegeService { constructor(private httpService: HttpService) {} - + + public async createPrivilege(request: any, privilegeDto: PrivilegeDto) {} + public async getPrivilege(roleId: string, request: any) {} + public async updatePrivilege(privilegeId, request, privilegeDto){} + public async getAllPrivilege(request){} + public async deletePrivilege(privilegeId, request, privilegeDto){} + } diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index f4bd872b..b169b415 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -3,10 +3,189 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; +import { PrivilegeDto } from 'src/rbac/privilege/dto/privilege.dto'; +import { isUUID } from 'class-validator'; @Injectable() export class PostgresPrivilegeService { + constructor( + @InjectRepository(Privilege) + private privilegeRepository: Repository + ) { } + public async createPrivilege(request: any, privilegeDto: PrivilegeDto) { + try { + + const label = privilegeDto.privilegeName.split(' ').join(''); + + + // const privilegeNameLowercase = privilegeDto.privilegeName.toLowerCase(); + + + const result = await this.checkExistingPrivilege(label) + + if (result) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: "Privilege with the same name already exists.", + }); + } + + // Create new privilege + const privilege = this.privilegeRepository.create({ + ...privilegeDto, + privilegeName: privilegeDto.privilegeName, + label:label + }); + const response = await this.privilegeRepository.save(privilege); + + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Privilege created successfully.", + data: response, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } +} + +async checkExistingPrivilege(label){ + const existingPrivilege = await this.privilegeRepository.findOne({ where: { label:label } }); + return existingPrivilege; +} + +public async getPrivilege(privilegeId: string, request: any) { + + + try { + + if (!isUUID(privilegeId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid PrivilegeId (UUID)", + }); + } + + const privilege = await this.privilegeRepository.findOne({ where: { privilegeId }} ); + if (!privilege) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Privilege not found", + }); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + // totalCount, + data: privilege, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + +} + + + +public async updatePrivilege(privilegeId: string, request: any, privilegeDto: PrivilegeDto) { + try { + // Get the privilege using the getPrivilege method + const existingPrivilegeResponse = await this.getPrivilege(privilegeId, request); + + if (existingPrivilegeResponse instanceof ErrorResponseTypeOrm) { + return existingPrivilegeResponse; + } + + // Cast the data property of the SuccessResponse to a Privilege object + const existingPrivilege: Privilege = existingPrivilegeResponse.data as Privilege; + + const newLabel = privilegeDto.privilegeName.split(' ').join(''); + + + const result = await this.checkExistingPrivilege(newLabel) + + if (result) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: "Privilege with the same name already exists.", + }); + } + // Merge the updated data into the existing privilege + const mergedPrivilege = this.privilegeRepository.merge(existingPrivilege, privilegeDto); + + mergedPrivilege.label = newLabel; + // Save the updated privilege record + const updatedPrivilegeRecord = await this.privilegeRepository.save(mergedPrivilege); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Privilege updated successfully", + data: updatedPrivilegeRecord + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: "Internal server error", + }); + } +} + +public async getAllPrivilege(request){ + + try { + const [result,count] = await this.privilegeRepository.findAndCount(); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok", + totalCount:count, + data: result + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: "Internal server error", + }); + } } + public async deletePrivilege(privilegeId, request, privilegeDto){ + + try { + + const existingPrivilegeResponse = await this.getPrivilege(privilegeId, request); + + if (existingPrivilegeResponse instanceof ErrorResponseTypeOrm) { + return existingPrivilegeResponse; + } + const result = await this.privilegeRepository.delete(privilegeId); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Privilege Deleted successfully", + data: { + affectedRows: result // Return the number of affected rows + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: "Internal server error", + }); + } + } + +} + + + + diff --git a/src/adapters/privilegeservicelocator.ts b/src/adapters/privilegeservicelocator.ts new file mode 100644 index 00000000..a0c811f2 --- /dev/null +++ b/src/adapters/privilegeservicelocator.ts @@ -0,0 +1,14 @@ +import { PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; + +export interface IServicelocator { + createPrivilege(request: any, privilegeDto: PrivilegeDto); + getPrivilege( + privilegeId?: string, + request?: any, + ); + updatePrivilege(privilegeId, request, privilegeDto) + getAllPrivilege(request) + deletePrivilege(privilegeId, request, privilegeDto) + + +} diff --git a/src/rbac/privilege/dto/privilege.dto.ts b/src/rbac/privilege/dto/privilege.dto.ts index 13615ab9..a2b711f9 100644 --- a/src/rbac/privilege/dto/privilege.dto.ts +++ b/src/rbac/privilege/dto/privilege.dto.ts @@ -1,11 +1,9 @@ -// export class CreatePrivilegeDto {} import { Expose } from "class-transformer"; import { ApiProperty } from "@nestjs/swagger"; -import {IsNotEmpty,IsString, IsUUID} from "class-validator" +import {IsNotEmpty,IsString, IsUUID, Matches} from "class-validator" export class PrivilegeDto { @Expose() - @IsUUID() privilegeId: string; @ApiProperty({ @@ -17,6 +15,14 @@ export class PrivilegeDto { @IsNotEmpty() privilegeName: string; + @ApiProperty({ + type: String, + description: "label", + default: "", + }) + @Expose() + label: string; + constructor(obj: any) { Object.assign(this, obj); } diff --git a/src/rbac/privilege/entities/privilege.entity.ts b/src/rbac/privilege/entities/privilege.entity.ts index 592d88c6..ba26946b 100644 --- a/src/rbac/privilege/entities/privilege.entity.ts +++ b/src/rbac/privilege/entities/privilege.entity.ts @@ -8,4 +8,7 @@ export class Privilege { @Column() privilegeName: string; + + @Column() + label:string } diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index 19660da1..f555fc32 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -29,10 +29,94 @@ import { Request } from "@nestjs/common"; import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { PrivilegeAdapter } from './privilegeadapter'; +import { UUID } from 'crypto'; + +@UseGuards(JwtAuthGuard) +@ApiTags("rbac") @Controller('privilege') export class PrivilegeController { constructor(private readonly privilegeAdapter: PrivilegeAdapter) {} + @Get("/:privilegeId") + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Privilege Detail." }) + @ApiHeader({ name: "tenantid" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({strategy: "excludeAll",}) + public async getPrivilege( + @Param("privilegeId") privilegeId: string, + @Req() request: Request, + @Res() response: Response + ) { + const result = await this.privilegeAdapter.buildPrivilegeAdapter().getPrivilege(privilegeId, request); + return response.status(result.statusCode).json(result); + } + + + + + @Post() + @UsePipes(new ValidationPipe()) + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Privilege has been created successfully." }) + @ApiBody({ type: PrivilegeDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid" }) + public async createPrivilege( + @Req() request: Request, + @Body() privilegeDto: PrivilegeDto, + @Res() response: Response + ) { + const result = await this.privilegeAdapter.buildPrivilegeAdapter().createPrivilege(request, privilegeDto); + return response.status(result.statusCode).json(result); + } + + + @Put("/:id") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Role updated successfully." }) + @ApiBody({ type:PrivilegeDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid", }) + public async updatePrivilege( + @Param("id") privilegeId: string, + @Req() request: Request, + @Body() privilegeDto: PrivilegeDto, + @Res() response: Response + ) { + const result = await this.privilegeAdapter.buildPrivilegeAdapter().updatePrivilege(privilegeId, request, privilegeDto); + return response.status(result.statusCode).json(result); + } + + @Get() + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Privilege Detail." }) + @ApiHeader({ name: "tenantid" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({strategy: "excludeAll",}) + public async getAllPrivilege( + @Req() request: Request, + @Res() response: Response + ) { + const result = await this.privilegeAdapter.buildPrivilegeAdapter().getAllPrivilege(request); + return response.status(result.statusCode).json(result); + } + + @Delete("/:id") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Role updated successfully." }) + @ApiBody({ type:PrivilegeDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid", }) + public async deletePrivilege( + @Param("id") privilegeId: string, + @Req() request: Request, + @Body() privilegeDto: PrivilegeDto, + @Res() response: Response + ) { + const result = await this.privilegeAdapter.buildPrivilegeAdapter().deletePrivilege(privilegeId, request, privilegeDto); + return response.status(result.statusCode).json(result); + } } diff --git a/src/rbac/privilege/privilegeadapter.ts b/src/rbac/privilege/privilegeadapter.ts index 873074ae..f12253ef 100644 --- a/src/rbac/privilege/privilegeadapter.ts +++ b/src/rbac/privilege/privilegeadapter.ts @@ -1,14 +1,14 @@ import { Injectable } from "@nestjs/common"; -import { IServicelocatorRbac } from "../../adapters/rbacservicelocator"; -import { HasuraRoleService } from "../../adapters/hasura/rbac/role.adapter"; -import { PostgresRoleService } from "../../adapters/postgres/rbac/role-adapter"; +import { HasuraPrivilegeService } from "src/adapters/hasura/rbac/privilege.adapter"; +import { IServicelocator } from "src/adapters/privilegeservicelocator"; +import { PostgresPrivilegeService } from "src/adapters/postgres/rbac/privilege-adapter"; @Injectable() export class PrivilegeAdapter { - constructor(private hasuraProvider: HasuraRoleService, - private postgresProvider:PostgresRoleService) {} - buildRbacAdapter(): IServicelocatorRbac { - let adapter: IServicelocatorRbac; + constructor(private hasuraProvider: HasuraPrivilegeService, + private postgresProvider:PostgresPrivilegeService) {} + buildPrivilegeAdapter(): IServicelocator { + let adapter: IServicelocator; switch (process.env.ADAPTERSOURCE) { case "hasura": From 3c2f07453359d8ab05d91f5c224e9a366337679a Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 10 Apr 2024 19:18:10 +0530 Subject: [PATCH 212/408] Task #216924: Created Aisgn Role CRUD Apis. --- src/adapters/assignroleservicelocater.ts | 7 ++ .../hasura/rbac/assignrole.adapter.ts | 12 ++ .../postgres/rbac/assignrole-adapter.ts | 109 ++++++++++++++++++ src/adapters/postgres/rbac/role-adapter.ts | 3 - src/cohort/cohortadapter.ts | 2 +- src/rbac/assign-role/assign-role.apater.ts | 22 ++++ .../assign-role/assign-role.controller.ts | 54 +++++++++ src/rbac/assign-role/assign-role.module.ts | 15 +++ .../assign-role/dto/create-assign-role.dto.ts | 29 +++++ .../entities/assign-role.entity.ts | 24 ++++ src/rbac/rbac.module.ts | 7 +- src/rbac/role/entities/rbac.entity.ts | 1 + src/user/entities/user-entity.ts | 1 + 13 files changed, 278 insertions(+), 8 deletions(-) create mode 100644 src/adapters/assignroleservicelocater.ts create mode 100644 src/adapters/hasura/rbac/assignrole.adapter.ts create mode 100644 src/adapters/postgres/rbac/assignrole-adapter.ts create mode 100644 src/rbac/assign-role/assign-role.apater.ts create mode 100644 src/rbac/assign-role/assign-role.controller.ts create mode 100644 src/rbac/assign-role/assign-role.module.ts create mode 100644 src/rbac/assign-role/dto/create-assign-role.dto.ts create mode 100644 src/rbac/assign-role/entities/assign-role.entity.ts diff --git a/src/adapters/assignroleservicelocater.ts b/src/adapters/assignroleservicelocater.ts new file mode 100644 index 00000000..4530c771 --- /dev/null +++ b/src/adapters/assignroleservicelocater.ts @@ -0,0 +1,7 @@ +import { CreateAssignRoleDto } from "src/rbac/assign-role/dto/create-assign-role.dto"; + +export interface IServicelocatorassignRole { + createAssignRole(request: any, createAssignRoleDto:CreateAssignRoleDto); + getassignedRole(userId, request); + deleteassignedRole(roleId); +} \ No newline at end of file diff --git a/src/adapters/hasura/rbac/assignrole.adapter.ts b/src/adapters/hasura/rbac/assignrole.adapter.ts new file mode 100644 index 00000000..ac23e77a --- /dev/null +++ b/src/adapters/hasura/rbac/assignrole.adapter.ts @@ -0,0 +1,12 @@ +import { HttpService } from "@nestjs/axios"; +import { Injectable } from "@nestjs/common"; +import { CreateAssignRoleDto } from "src/rbac/assign-role/dto/create-assign-role.dto"; + + +@Injectable() +export class HasuraAssignRoleService { + constructor(private httpService: HttpService) {} + public async createAssignRole(request: any, createAssignRoleDto:CreateAssignRoleDto){}; + public async getassignedRole(request: any, createAssignRoleDto:CreateAssignRoleDto){}; + public async deleteassignedRole(userId){}; +} \ No newline at end of file diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts new file mode 100644 index 00000000..3bee36b7 --- /dev/null +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -0,0 +1,109 @@ +import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { SuccessResponse } from 'src/success-response'; +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { CreateAssignRoleDto } from 'src/rbac/assign-role/dto/create-assign-role.dto'; +import { UserRoleMapping } from 'src/rbac/assign-role/entities/assign-role.entity'; +import { IsAlpha, IsUUID, isUUID } from 'class-validator'; + +@Injectable() +export class PostgresAssignroleService { + constructor( + @InjectRepository(UserRoleMapping) + private userRoleMappingRepository: Repository + ){} + public async createAssignRole(request: Request,createAssignRoleDto:CreateAssignRoleDto){ + try { + let findExistingRole = await this.userRoleMappingRepository.findOne({ + where:{ + userId:createAssignRoleDto?.userId, + roleId:createAssignRoleDto?.roleId + } + }) + if(findExistingRole){ + return new SuccessResponse({ + statusCode: HttpStatus.FORBIDDEN, + message: "Role Already Assigned to This User.", + }); + } + let data = await this.userRoleMappingRepository.save(createAssignRoleDto) + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: data, + }); + } catch (error) { + console.log(error); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: JSON.stringify(error) + }); + } + } + + public async getassignedRole(userId:string,request: Request){ + try { + if (!isUUID(userId)) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'Please Enter Valid User ID', + }); + } + let result = await this.checkExistingRole(userId); + if(!result){ + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'No Role assigned to user', + data: result, + }); + } + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: result, + }); + } catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + + } + + public async deleteassignedRole(userId){ + try { + let result = await this.checkExistingRole(userId); + if(!result){ + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'No Role assigned to user', + data: result, + }); + } + let response = await this.userRoleMappingRepository.delete(userId) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Role deleted successfully.', + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async checkExistingRole(userId){ + const result= await this.userRoleMappingRepository.findOne({ + where: { userId }, + relations:['user'] + }) + return result; + } + +} \ No newline at end of file diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index 62ee33c0..e67817c4 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -47,9 +47,6 @@ export class PostgresRoleService { errorMessage: e, }); } - - - } public async updateRole(roleId: string, request: any, roleDto: RoleDto) { diff --git a/src/cohort/cohortadapter.ts b/src/cohort/cohortadapter.ts index fbfd2b71..0ed45cf6 100644 --- a/src/cohort/cohortadapter.ts +++ b/src/cohort/cohortadapter.ts @@ -13,7 +13,7 @@ export class CohortAdapter { case "hasura": adapter = this.hasuraProvider; break; - case "hasura": + case "postgres": adapter = this.postgresProvider; break; } diff --git a/src/rbac/assign-role/assign-role.apater.ts b/src/rbac/assign-role/assign-role.apater.ts new file mode 100644 index 00000000..b17988b9 --- /dev/null +++ b/src/rbac/assign-role/assign-role.apater.ts @@ -0,0 +1,22 @@ +import { Injectable } from "@nestjs/common"; +import { PostgresAssignroleService } from "src/adapters/postgres/rbac/assignrole-adapter"; +import { HasuraAssignRoleService } from "src/adapters/hasura/rbac/assignrole.adapter"; +import { IServicelocatorassignRole } from "src/adapters/assignroleservicelocater"; + +@Injectable() +export class AssignRoleAdapter { + constructor(private hasuraProvider: HasuraAssignRoleService, + private postgresProvider:PostgresAssignroleService) {} + buildassignroleAdapter(): IServicelocatorassignRole { + let adapter: IServicelocatorassignRole; + + switch (process.env.ADAPTERSOURCE) { + case "hasura": + adapter = this.hasuraProvider; + break; + case "postgres": + adapter = this.postgresProvider; + } + return adapter; + } +} diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts new file mode 100644 index 00000000..f8c5d18f --- /dev/null +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -0,0 +1,54 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions } from '@nestjs/common'; +import { AssignRoleAdapter } from './assign-role.apater'; +import { CreateAssignRoleDto } from './dto/create-assign-role.dto'; +import { Response, response } from "express"; +import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse } from '@nestjs/swagger'; + + + +@Controller('assignrole') +export class AssignRoleController { + constructor(private readonly assignRoleapater: AssignRoleAdapter) {} + + @Post() + @UsePipes(new ValidationPipe()) + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Role has been Assigned successfully." }) + @ApiBody({ type: CreateAssignRoleDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid" }) + public async create(@Req() request: Request, + @Body() createAssignRoleDto:CreateAssignRoleDto , + @Res() response: Response) { + const result = await this.assignRoleapater.buildassignroleAdapter().createAssignRole(request,createAssignRoleDto); + return response.status(result.statusCode).json(result); + } + + @Get("/:id") + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Role Detail." }) + @ApiHeader({ name: "tenantid" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({strategy: "excludeAll",}) + public async getRole( + @Param("id") userId: string, + @Req() request: Request, + @Res() response: Response + ) { + const result = await this.assignRoleapater.buildassignroleAdapter().getassignedRole(userId, request); + return response.status(result.statusCode).json(result); + } + + @Delete("/:id") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Assigend Role deleted successfully." }) + @ApiForbiddenResponse({ description: "Forbidden" }) + public async deleteRole( + @Param("id") userId: string, + @Res() response: Response + ) { + const result = await this.assignRoleapater.buildassignroleAdapter().deleteassignedRole(userId); + return response.status(result.statusCode).json(result); + } + +} diff --git a/src/rbac/assign-role/assign-role.module.ts b/src/rbac/assign-role/assign-role.module.ts new file mode 100644 index 00000000..06f521bd --- /dev/null +++ b/src/rbac/assign-role/assign-role.module.ts @@ -0,0 +1,15 @@ +import { Module } from '@nestjs/common'; +import { AssignRoleAdapter } from './assign-role.apater'; +import { AssignRoleController } from './assign-role.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { UserRoleMapping } from './entities/assign-role.entity'; +import { PostgresAssignroleService } from 'src/adapters/postgres/rbac/assignrole-adapter'; +import { HasuraAssignRoleService } from 'src/adapters/hasura/rbac/assignrole.adapter'; +import { HttpModule } from '@nestjs/axios'; + +@Module({ + imports:[TypeOrmModule.forFeature([UserRoleMapping]),HttpModule], + controllers: [AssignRoleController], + providers: [AssignRoleAdapter,HasuraAssignRoleService,PostgresAssignroleService] +}) +export class AssignRoleModule {} diff --git a/src/rbac/assign-role/dto/create-assign-role.dto.ts b/src/rbac/assign-role/dto/create-assign-role.dto.ts new file mode 100644 index 00000000..a11c4d06 --- /dev/null +++ b/src/rbac/assign-role/dto/create-assign-role.dto.ts @@ -0,0 +1,29 @@ +// export class CreatePrivilegeDto {} +import { Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; +import {IsNotEmpty,IsString, IsUUID} from "class-validator" + +export class CreateAssignRoleDto { + @ApiProperty({ + type: String, + description: "User Id of User", + default: "", + }) + @Expose() + @IsUUID() + userId: string; + + @ApiProperty({ + type: String, + description: "Assigned Role Id", + default: "", + }) + @Expose() + @IsUUID() + @IsNotEmpty() + roleId: string; + + constructor(obj: any) { + Object.assign(this, obj); + } +} diff --git a/src/rbac/assign-role/entities/assign-role.entity.ts b/src/rbac/assign-role/entities/assign-role.entity.ts new file mode 100644 index 00000000..b31d9b54 --- /dev/null +++ b/src/rbac/assign-role/entities/assign-role.entity.ts @@ -0,0 +1,24 @@ +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn } from 'typeorm'; +import { User } from 'src/user/entities/user-entity'; +import { Role } from '../../role/entities/rbac.entity'; + +@Entity({ name: 'User_Role_Mapping' }) +export class UserRoleMapping { + @PrimaryGeneratedColumn('uuid') + Id: string; + + @Column('uuid') + userId: string; + + @Column('uuid') + roleId: string; + + @ManyToOne(() => User, user => user.userRoleMappings) + @JoinColumn({ name: 'userId' }) + user: User; + + @ManyToOne(() => Role, role => role.userRoleMappings) + @JoinColumn({ name: 'roleId' }) + role: Role; +} + diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index d86c975b..74f55991 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -1,14 +1,13 @@ import { Module } from "@nestjs/common"; import { RoleModule } from "./role/role.module"; import { PrivilegeModule } from './privilege/privilege.module'; -import { TypeOrmModule } from "@nestjs/typeorm"; -import { Privilege } from "./privilege/entities/privilege.entity"; -import { Role } from "./role/entities/rbac.entity"; +import { AssignRoleModule } from './assign-role/assign-role.module'; @Module({ imports: [ RoleModule, - PrivilegeModule + PrivilegeModule, + AssignRoleModule ], }) export class RbacModule {} diff --git a/src/rbac/role/entities/rbac.entity.ts b/src/rbac/role/entities/rbac.entity.ts index 67064749..6383424f 100644 --- a/src/rbac/role/entities/rbac.entity.ts +++ b/src/rbac/role/entities/rbac.entity.ts @@ -7,4 +7,5 @@ export class Role { @Column() roleName: string; + userRoleMappings: any; } diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts index dc401c2f..5381286b 100644 --- a/src/user/entities/user-entity.ts +++ b/src/user/entities/user-entity.ts @@ -52,4 +52,5 @@ export class User { @Column({ default: "active" }) status: string; + userRoleMappings: any; } From a85028e87f6721390d03a20fdd699c0ce68d7153 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 11 Apr 2024 10:28:18 +0530 Subject: [PATCH 213/408] Removed Unnecceray logs and Fixed some Typo --- src/rbac/assign-role/assign-role.controller.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index f8c5d18f..27515a73 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -8,7 +8,7 @@ import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHea @Controller('assignrole') export class AssignRoleController { - constructor(private readonly assignRoleapater: AssignRoleAdapter) {} + constructor(private readonly assignRoleAdpater: AssignRoleAdapter) {} @Post() @UsePipes(new ValidationPipe()) @@ -20,7 +20,7 @@ export class AssignRoleController { public async create(@Req() request: Request, @Body() createAssignRoleDto:CreateAssignRoleDto , @Res() response: Response) { - const result = await this.assignRoleapater.buildassignroleAdapter().createAssignRole(request,createAssignRoleDto); + const result = await this.assignRoleAdpater.buildassignroleAdapter().createAssignRole(request,createAssignRoleDto); return response.status(result.statusCode).json(result); } @@ -35,7 +35,7 @@ export class AssignRoleController { @Req() request: Request, @Res() response: Response ) { - const result = await this.assignRoleapater.buildassignroleAdapter().getassignedRole(userId, request); + const result = await this.assignRoleAdpater.buildassignroleAdapter().getAssignedRole(userId, request); return response.status(result.statusCode).json(result); } @@ -47,7 +47,7 @@ export class AssignRoleController { @Param("id") userId: string, @Res() response: Response ) { - const result = await this.assignRoleapater.buildassignroleAdapter().deleteassignedRole(userId); + const result = await this.assignRoleAdpater.buildassignroleAdapter().deleteAssignedRole(userId); return response.status(result.statusCode).json(result); } From 35dd512ef56f69ab577d6e1774a84b4702ac92a3 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 11 Apr 2024 10:28:52 +0530 Subject: [PATCH 214/408] Fixed Console Log and Some Typo --- src/adapters/assignroleservicelocater.ts | 4 ++-- src/adapters/hasura/rbac/assignrole.adapter.ts | 4 ++-- src/adapters/postgres/rbac/assignrole-adapter.ts | 5 ++--- src/rbac/assign-role/assign-role.apater.ts | 3 +++ src/rbac/role/entities/rbac.entity.ts | 2 +- src/user/entities/user-entity.ts | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/adapters/assignroleservicelocater.ts b/src/adapters/assignroleservicelocater.ts index 4530c771..2d4619f5 100644 --- a/src/adapters/assignroleservicelocater.ts +++ b/src/adapters/assignroleservicelocater.ts @@ -2,6 +2,6 @@ import { CreateAssignRoleDto } from "src/rbac/assign-role/dto/create-assign-role export interface IServicelocatorassignRole { createAssignRole(request: any, createAssignRoleDto:CreateAssignRoleDto); - getassignedRole(userId, request); - deleteassignedRole(roleId); + getAssignedRole(userId, request); + deleteAssignedRole(userId); } \ No newline at end of file diff --git a/src/adapters/hasura/rbac/assignrole.adapter.ts b/src/adapters/hasura/rbac/assignrole.adapter.ts index ac23e77a..24481f21 100644 --- a/src/adapters/hasura/rbac/assignrole.adapter.ts +++ b/src/adapters/hasura/rbac/assignrole.adapter.ts @@ -7,6 +7,6 @@ import { CreateAssignRoleDto } from "src/rbac/assign-role/dto/create-assign-role export class HasuraAssignRoleService { constructor(private httpService: HttpService) {} public async createAssignRole(request: any, createAssignRoleDto:CreateAssignRoleDto){}; - public async getassignedRole(request: any, createAssignRoleDto:CreateAssignRoleDto){}; - public async deleteassignedRole(userId){}; + public async getAssignedRole(request: any, createAssignRoleDto:CreateAssignRoleDto){}; + public async deleteAssignedRole(userId){}; } \ No newline at end of file diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts index 3bee36b7..39e2802f 100644 --- a/src/adapters/postgres/rbac/assignrole-adapter.ts +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -34,7 +34,6 @@ export class PostgresAssignroleService { data: data, }); } catch (error) { - console.log(error); return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: JSON.stringify(error) @@ -42,7 +41,7 @@ export class PostgresAssignroleService { } } - public async getassignedRole(userId:string,request: Request){ + public async getAssignedRole(userId:string,request: Request){ try { if (!isUUID(userId)) { return new SuccessResponse({ @@ -72,7 +71,7 @@ export class PostgresAssignroleService { } - public async deleteassignedRole(userId){ + public async deleteAssignedRole(userId){ try { let result = await this.checkExistingRole(userId); if(!result){ diff --git a/src/rbac/assign-role/assign-role.apater.ts b/src/rbac/assign-role/assign-role.apater.ts index b17988b9..da7ac3d0 100644 --- a/src/rbac/assign-role/assign-role.apater.ts +++ b/src/rbac/assign-role/assign-role.apater.ts @@ -16,6 +16,9 @@ export class AssignRoleAdapter { break; case "postgres": adapter = this.postgresProvider; + break; + default: + throw new Error("Invalid ADAPTERSOURCE environment variable. Please specify either 'hasura' or 'postgres'."); } return adapter; } diff --git a/src/rbac/role/entities/rbac.entity.ts b/src/rbac/role/entities/rbac.entity.ts index 6383424f..3654324a 100644 --- a/src/rbac/role/entities/rbac.entity.ts +++ b/src/rbac/role/entities/rbac.entity.ts @@ -7,5 +7,5 @@ export class Role { @Column() roleName: string; - userRoleMappings: any; + userRoleMappings: Role; } diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts index 5381286b..a6963982 100644 --- a/src/user/entities/user-entity.ts +++ b/src/user/entities/user-entity.ts @@ -52,5 +52,5 @@ export class User { @Column({ default: "active" }) status: string; - userRoleMappings: any; + userRoleMappings: User; } From a09a2c237ed087d14d68fb612b8dfcc81173b5c8 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 11 Apr 2024 15:08:49 +0530 Subject: [PATCH 215/408] remove extra code --- src/adapters/postgres/rbac/role-adapter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index ec9cc1df..6ee2f908 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -16,10 +16,10 @@ export class PostgresRoleService { public async createRole(request: any, roleDto: RoleDto) { try { // Convert role name to lowercase - roleDto.roleName = roleDto.roleName.toLowerCase(); + const roleNameInLower = roleDto.roleName.toLowerCase(); // Check if role name already exists - const existingRole = await this.roleRepository.findOne({ where: { roleName: roleDto.roleName } }) + const existingRole = await this.roleRepository.findOne({ where: { roleName: roleNameInLower } }) if (existingRole) { return new SuccessResponse({ statusCode: HttpStatus.FORBIDDEN, @@ -30,7 +30,7 @@ export class PostgresRoleService { // Convert roleDto to lowercase const roleDtoLowercase = { ...roleDto, - roleName: roleDto.roleName.toLowerCase() + roleName: roleNameInLower }; const response = await this.roleRepository.save(roleDtoLowercase); From 8a3d1a8d3301ef78df1c5ba3c4ab7d0cc5660ce9 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 11 Apr 2024 21:29:49 +0530 Subject: [PATCH 216/408] Changed API EndPoint for User Detail and Added Swagger. --- src/auth/auth.controller.ts | 2 +- src/rbac/assign-role/assign-role.controller.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 4cfd0650..ecac1df9 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -42,7 +42,7 @@ export class AuthController { return this.authService.login(authDto); } - @Get("/getUserDetails") + @Get("/user") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index 27515a73..d98bf171 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -2,11 +2,12 @@ import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, Validation import { AssignRoleAdapter } from './assign-role.apater'; import { CreateAssignRoleDto } from './dto/create-assign-role.dto'; import { Response, response } from "express"; -import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse } from '@nestjs/swagger'; +import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger'; @Controller('assignrole') +@ApiTags('rbac') export class AssignRoleController { constructor(private readonly assignRoleAdpater: AssignRoleAdapter) {} From 6516136d07eb173bf029fa320b07393b6e0b3053 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 12 Apr 2024 10:02:30 +0530 Subject: [PATCH 217/408] Fix[swagger Fix] --- src/rbac/privilege/dto/privilege.dto.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/rbac/privilege/dto/privilege.dto.ts b/src/rbac/privilege/dto/privilege.dto.ts index a2b711f9..404afd4f 100644 --- a/src/rbac/privilege/dto/privilege.dto.ts +++ b/src/rbac/privilege/dto/privilege.dto.ts @@ -15,11 +15,7 @@ export class PrivilegeDto { @IsNotEmpty() privilegeName: string; - @ApiProperty({ - type: String, - description: "label", - default: "", - }) + @Expose() label: string; From 7e021b539d9e58d26397c54e51ad13cba3634565 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 12 Apr 2024 11:56:03 +0530 Subject: [PATCH 218/408] Fix[Attendance Changes] --- src/adapters/postgres/attendance-adapter.ts | 91 +++++++++++++++++---- src/attendance/attendance.controller.ts | 1 + 2 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index ab596eae..46a9cb33 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -5,7 +5,7 @@ import { Client } from 'pg'; import jwt_decode from "jwt-decode"; import { InjectRepository } from "@nestjs/typeorm"; import { AttendanceEntity } from "../../attendance/entities/attendance.entity"; -import { Repository } from "typeorm"; +import { EntityMetadata, QueryRunner, Repository } from "typeorm"; import { BadRequestException, HttpException, HttpStatus, Injectable } from "@nestjs/common"; import { AttendanceSearchDto } from "../../attendance/dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; @@ -15,13 +15,18 @@ import { Between } from 'typeorm'; import { AttendanceStatsDto } from '../../attendance/dto/attendance-stats.dto'; import { format } from 'date-fns' import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; const moment = require('moment'); @Injectable() export class PostgresAttendanceService { constructor(private configService: ConfigService, @InjectRepository(AttendanceEntity) - private readonly attendanceRepository: Repository, + private attendanceRepository: Repository, + @InjectRepository(User) + private userRepository: Repository, + @InjectRepository(CohortMembers) + private cohortMembersRepository: Repository ) { } @@ -45,26 +50,69 @@ export class PostgresAttendanceService { if (page > 1) { offset = parseInt(limit) * (page - 1); } - const whereClause = {}; + + const UserKeys = this.userRepository.metadata.columns.map((column) => column.propertyName); + const AttendaceKeys = this.attendanceRepository.metadata.columns.map((column) => column.propertyName); + const CohortMembersKeys = this.cohortMembersRepository.metadata.columns.map((column) => column.propertyName); + + let whereClause = `u."tenantId" = '${tenantId}'`; // Default WHERE clause for filtering by tenantId + let attendanceList = '' if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } - else { - whereClause['tenantId'] = tenantId; + // Construct additional WHERE conditions based on filters + for (const [key, value] of Object.entries(filters)) { + // Check if the key exists in UserKeys, AttendanceKeys, or CohortMembersKeys + if (UserKeys.includes(key)) { + whereClause += ` AND u."${key}" = '${value}'`; + } else if (AttendaceKeys.includes(key)) { + if(key==="attendanceDate"){ + attendanceList = ` AND (a."attendanceDate" = '${value}' OR a."attendanceDate" IS NULL)` + continue + } + whereClause += ` AND a."${key}" = '${value}'`; + } else if (CohortMembersKeys.includes(key)) { + whereClause += ` AND cm."${key}" = '${value}'`; + } + else{ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `${key} Invalid key`, + }); + +} + }; } - const [results, totalCount] = await this.attendanceRepository.findAndCount({ - where: whereClause, - take: parseInt(limit), - skip: offset, - }); - const mappedResponse = await this.mappedResponse(results); + + + + + console.log(attendanceList,whereClause,"Shubham"); + const query =`SELECT + u.*, + cm.*, + a.* + FROM + "Users" u + LEFT JOIN + "CohortMembers" cm ON cm."userId" = u."userId" + LEFT JOIN + "Attendance" a ON a."userId" = cm."userId" ${attendanceList} + where + ${whereClause} + ` +console.log(query,"query") + + + + const results = await this.userRepository.query(query); + + // console.log(results,"results") + const mappedResponse = await this.mappedResponse(results); + return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', - totalCount, + // totalCount, data: mappedResponse, }); } catch (error) { @@ -162,7 +210,7 @@ export class PostgresAttendanceService { }); } - + } else if (report === false) { if (attendanceDate) { @@ -214,11 +262,14 @@ export class PostgresAttendanceService { public async mappedResponse(result: any) { const attendanceResponse = result.map((item: any) => { + + const dateObject = new Date(item.attendanceDate); + const formattedDate = moment(dateObject).format('YYYY-MM-DD'); const attendanceMapping = { tenantId: item?.tenantId ? `${item.tenantId}` : "", attendanceId: item?.attendanceId ? `${item.attendanceId}` : "", userId: item?.userId ? `${item.userId}` : "", - attendanceDate: item?.attendanceDate ? `${item.attendanceDate}` : "", + attendanceDate: item.attendanceDate ? formattedDate : null, attendance: item?.attendance ? `${item.attendance}` : "", remark: item?.remark ? `${item.remark}` : "", latitude: item?.latitude ? item.latitude : 0, @@ -233,8 +284,12 @@ export class PostgresAttendanceService { updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", createdBy: item?.createdBy ? `${item.createdBy}` : "", updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", + username:item?.username ? `${item.username}` : "", + role:item?.role ? `${item.role}` : "", + }; + return new AttendanceDto(attendanceMapping); }); diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index bef92c09..b231321a 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -26,6 +26,7 @@ import { ValidationPipe, Res, UseGuards, + HttpStatus, } from "@nestjs/common"; import { AttendanceDto, BulkAttendanceDTO } from "./dto/attendance.dto"; import { FileInterceptor } from "@nestjs/platform-express"; From a82086a4ab2927ed72f0538be95d06647d6d6080 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Sun, 14 Apr 2024 01:08:26 +0530 Subject: [PATCH 219/408] Update privilege.controller.ts --- src/rbac/privilege/privilege.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index f555fc32..35c4ae05 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -29,7 +29,7 @@ import { Request } from "@nestjs/common"; import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { PrivilegeAdapter } from './privilegeadapter'; -import { UUID } from 'crypto'; +import { v4 as uuidv4 } from 'uuid'; @UseGuards(JwtAuthGuard) From 67784d5e13e06e9401d5b16a9c7b96d386ed2dfa Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:47:50 +0530 Subject: [PATCH 220/408] Update Jenkinsfile --- Jenkinsfile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0cc24c52..ac30d910 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,10 +19,16 @@ pipeline { stage ('Deploy') { steps { - - sh 'docker-compose up -d --force-recreate --no-deps backend' } } + post { + always { + // Send notification to Slack + slackSend(channel: '#your_channel_name', color: 'good', message: "Build ${currentBuild.result}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})") + } } -} \ No newline at end of file + + + } +} From fbb42a5a9e5ab3e368c0f838030b760c31687374 Mon Sep 17 00:00:00 2001 From: PrasadAthani <150219751+PrasadAthani@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:54:32 +0530 Subject: [PATCH 221/408] Update Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index ac30d910..4ae6904f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,7 +23,7 @@ pipeline { } } post { - always { + stage ('Deploy') { // Send notification to Slack slackSend(channel: '#your_channel_name', color: 'good', message: "Build ${currentBuild.result}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})") } From 34b064ec9c528ca48449e7b8ddc96516c105a78d Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 15 Apr 2024 12:19:38 +0530 Subject: [PATCH 222/408] Task #217036: CRUD Apis for Assign Privilege APIS --- src/adapters/assignprivilegelocater.ts | 7 ++ .../hasura/rbac/privilegerole.adapter.ts | 12 ++ .../postgres/rbac/assignrole-adapter.ts | 16 ++- .../postgres/rbac/privilegerole.adapter.ts | 114 ++++++++++++++++++ src/auth/auth.service.ts | 2 +- .../assign-privilege.apater.ts | 26 ++++ .../assign-privilege.controller.ts | 54 +++++++++ .../assign-privilege.module.ts | 16 +++ .../dto/create-assign-privilege.dto.ts | 28 +++++ .../entities/assign-privilege.entity.ts | 25 ++++ .../entities/assign-role.entity.ts | 2 +- src/rbac/rbac.module.ts | 4 +- src/rbac/role/entities/rbac.entity.ts | 1 + 13 files changed, 303 insertions(+), 4 deletions(-) create mode 100644 src/adapters/assignprivilegelocater.ts create mode 100644 src/adapters/hasura/rbac/privilegerole.adapter.ts create mode 100644 src/adapters/postgres/rbac/privilegerole.adapter.ts create mode 100644 src/rbac/assign-privilege/assign-privilege.apater.ts create mode 100644 src/rbac/assign-privilege/assign-privilege.controller.ts create mode 100644 src/rbac/assign-privilege/assign-privilege.module.ts create mode 100644 src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts create mode 100644 src/rbac/assign-privilege/entities/assign-privilege.entity.ts diff --git a/src/adapters/assignprivilegelocater.ts b/src/adapters/assignprivilegelocater.ts new file mode 100644 index 00000000..d71c321a --- /dev/null +++ b/src/adapters/assignprivilegelocater.ts @@ -0,0 +1,7 @@ +import { CreatePrivilegeRoleDto } from "src/rbac/assign-privilege/dto/create-assign-privilege.dto"; + +export interface IServicelocatorprivilegeRole { + createPrivilegeRole(request: any, createPrivilegeRole:CreatePrivilegeRoleDto); + getPrivilegeRole(userId, request); + deletePrivilegeRole(userId); +} \ No newline at end of file diff --git a/src/adapters/hasura/rbac/privilegerole.adapter.ts b/src/adapters/hasura/rbac/privilegerole.adapter.ts new file mode 100644 index 00000000..1ec35c75 --- /dev/null +++ b/src/adapters/hasura/rbac/privilegerole.adapter.ts @@ -0,0 +1,12 @@ +import { HttpService } from "@nestjs/axios"; +import { Injectable } from "@nestjs/common"; +import { CreatePrivilegeRoleDto } from "src/rbac/assign-privilege/dto/create-assign-privilege.dto"; + + +@Injectable() +export class HasuraAssignPrivilegeService { + constructor(private httpService: HttpService) {} + public async createPrivilegeRole(request: any, createAssignRoleDto:CreatePrivilegeRoleDto){}; + public async getPrivilegeRole(request: any, createAssignRoleDto:CreatePrivilegeRoleDto){}; + public async deletePrivilegeRole(userId){}; +} \ No newline at end of file diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts index 39e2802f..85e4e41a 100644 --- a/src/adapters/postgres/rbac/assignrole-adapter.ts +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -6,6 +6,7 @@ import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { CreateAssignRoleDto } from 'src/rbac/assign-role/dto/create-assign-role.dto'; import { UserRoleMapping } from 'src/rbac/assign-role/entities/assign-role.entity'; import { IsAlpha, IsUUID, isUUID } from 'class-validator'; +import { executionAsyncResource } from 'async_hooks'; @Injectable() export class PostgresAssignroleService { @@ -34,6 +35,12 @@ export class PostgresAssignroleService { data: data, }); } catch (error) { + if(error.code === '23503'){ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: `User Id or Role Id Doesn't Exist in Database ` + }); + } return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: JSON.stringify(error) @@ -97,8 +104,15 @@ export class PostgresAssignroleService { } } +// async checkAndAddUserRole(data){ +// let existingUser = await this.checkExistingRole(data.userId) ; +// if(existingUser){ +// let update = +// } +// } + async checkExistingRole(userId){ - const result= await this.userRoleMappingRepository.findOne({ + const result= await this.userRoleMappingRepository.findOne({ where: { userId }, relations:['user'] }) diff --git a/src/adapters/postgres/rbac/privilegerole.adapter.ts b/src/adapters/postgres/rbac/privilegerole.adapter.ts new file mode 100644 index 00000000..d1905278 --- /dev/null +++ b/src/adapters/postgres/rbac/privilegerole.adapter.ts @@ -0,0 +1,114 @@ +import { HttpStatus, Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { SuccessResponse } from 'src/success-response'; +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { CreatePrivilegeRoleDto } from 'src/rbac/assign-privilege/dto/create-assign-privilege.dto'; +import { RolePrivilegeMapping } from 'src/rbac/assign-privilege/entities/assign-privilege.entity'; +import { isUUID } from 'class-validator'; + +@Injectable() +export class PostgresAssignPrivilegeService { + constructor( + @InjectRepository(RolePrivilegeMapping) + private rolePrivilegeMappingRepository: Repository + ){} + public async createPrivilegeRole(request: Request,createPrivilegeRoleDto:CreatePrivilegeRoleDto){ + try { + let findExistingPrivilege = await this.rolePrivilegeMappingRepository.findOne({ + where:{ + privilegeId:createPrivilegeRoleDto?.privilegeId, + roleId:createPrivilegeRoleDto?.roleId + } + }) + if(findExistingPrivilege){ + return new SuccessResponse({ + statusCode: HttpStatus.FORBIDDEN, + message: "Privilege Already Assigned to This Role.", + }); + } + let data = await this.rolePrivilegeMappingRepository.save(createPrivilegeRoleDto) + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: data, + }); + } catch (error) { + if(error.code === '23503'){ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: `Privilege Id or Role Id Doesn't Exist in Database ` + }); + } + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: JSON.stringify(error) + }); + } + } + + public async getPrivilegeRole(userId:string,request: Request){ + try { + if (!isUUID(userId)) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'Please Enter Valid User ID', + }); + } + let result = await this.checkExistingRole(userId); + if(!result){ + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'No Role assigned to user', + data: result, + }); + } + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: result, + }); + } catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + + } + + public async deletePrivilegeRole(userId){ + try { + let result = await this.checkExistingRole(userId); + if(!result){ + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'No Role assigned to user', + data: result, + }); + } + let response = await this.rolePrivilegeMappingRepository.delete(userId) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Role deleted successfully.', + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async checkExistingRole(privilegeId){ + const result= await this.rolePrivilegeMappingRepository.findOne({ + where: { privilegeId}, + relations:['user'] + }) + return result; + } + +} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 6fd7ea10..f3299564 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -46,7 +46,7 @@ export class AuthService { try { const decoded: any = jwt_decode(request.headers.authorization); const username = decoded.preferred_username; - let data = await this.useradapter.buildUserAdapter().findUserDetails(null, username); + let data = await this.useradapter.buildUserAdapter().findUserDetails(null, username); return response .status(HttpStatus.OK) .send(APIResponse.success(apiId, data, "OK")); diff --git a/src/rbac/assign-privilege/assign-privilege.apater.ts b/src/rbac/assign-privilege/assign-privilege.apater.ts new file mode 100644 index 00000000..84625e6a --- /dev/null +++ b/src/rbac/assign-privilege/assign-privilege.apater.ts @@ -0,0 +1,26 @@ +import { Injectable } from "@nestjs/common"; +import { PostgresAssignPrivilegeService } from "src/adapters/postgres/rbac/privilegerole.adapter"; +import { HasuraAssignPrivilegeService } from "src/adapters/hasura/rbac/privilegerole.adapter"; +import { IServicelocatorassignRole } from "src/adapters/assignroleservicelocater"; +import { IServicelocatorprivilegeRole } from "src/adapters/assignprivilegelocater"; + +@Injectable() +export class AssignPrivilegeAdapter { + constructor(private hasuraProvider: HasuraAssignPrivilegeService, + private postgresProvider:PostgresAssignPrivilegeService) {} + buildPrivilegeRoleAdapter(): IServicelocatorprivilegeRole { + let adapter: IServicelocatorprivilegeRole; + + switch (process.env.ADAPTERSOURCE) { + case "hasura": + adapter = this.hasuraProvider; + break; + case "postgres": + adapter = this.postgresProvider; + break; + default: + throw new Error("Invalid ADAPTERSOURCE environment variable. Please specify either 'hasura' or 'postgres'."); + } + return adapter; + } +} diff --git a/src/rbac/assign-privilege/assign-privilege.controller.ts b/src/rbac/assign-privilege/assign-privilege.controller.ts new file mode 100644 index 00000000..b06f377f --- /dev/null +++ b/src/rbac/assign-privilege/assign-privilege.controller.ts @@ -0,0 +1,54 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions } from '@nestjs/common'; +import { AssignPrivilegeAdapter } from './assign-privilege.apater'; +import { CreatePrivilegeRoleDto } from './dto/create-assign-privilege.dto'; +import { Response} from "express"; +import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger'; + + +@ApiTags('rbac') +@Controller('assignprivilege') +export class AssignPrivilegeController { + constructor(private readonly assignPrivilegeAdpater: AssignPrivilegeAdapter) {} + + @Post() + @UsePipes(new ValidationPipe()) + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Privilege has been Assigned successfully." }) + @ApiBody({ type: CreatePrivilegeRoleDto }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid" }) + public async create(@Req() request: Request, + @Body() createAssignPrivilegeDto:CreatePrivilegeRoleDto , + @Res() response: Response) { + const result = await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().createPrivilegeRole(request,createAssignPrivilegeDto); + return response.status(result.statusCode).json(result); + } + + @Get("/:id") + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Privilege Details." }) + @ApiHeader({ name: "tenantid" }) + @ApiForbiddenResponse({ description: "Forbidden" }) + @SerializeOptions({strategy: "excludeAll",}) + public async getRole( + @Param("id") userId: string, + @Req() request: Request, + @Res() response: Response + ) { + const result = await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().getPrivilegeRole(userId, request); + return response.status(result.statusCode).json(result); + } + + @Delete("/:id") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Assigend Privililege has been deleted successfully." }) + @ApiForbiddenResponse({ description: "Forbidden" }) + public async deletePrivilegeRole( + @Param("id") userId: string, + @Res() response: Response + ) { + const result = await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().deletePrivilegeRole(userId); + return response.status(result.statusCode).json(result); + } + +} diff --git a/src/rbac/assign-privilege/assign-privilege.module.ts b/src/rbac/assign-privilege/assign-privilege.module.ts new file mode 100644 index 00000000..5daef2a9 --- /dev/null +++ b/src/rbac/assign-privilege/assign-privilege.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { AssignPrivilegeAdapter } from './assign-privilege.apater'; +import { AssignPrivilegeController } from './assign-privilege.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { PostgresAssignPrivilegeService } from 'src/adapters/postgres/rbac/privilegerole.adapter'; +import { HasuraAssignPrivilegeService } from 'src/adapters/hasura/rbac/privilegerole.adapter'; +import { HttpModule } from '@nestjs/axios'; +import { RolePrivilegeMapping } from './entities/assign-privilege.entity'; + + +@Module({ + imports:[TypeOrmModule.forFeature([RolePrivilegeMapping]),HttpModule], + controllers: [AssignPrivilegeController], + providers: [AssignPrivilegeAdapter,HasuraAssignPrivilegeService,PostgresAssignPrivilegeService] +}) +export class AssignPrivilegeModule {} diff --git a/src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts b/src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts new file mode 100644 index 00000000..878a866a --- /dev/null +++ b/src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts @@ -0,0 +1,28 @@ +import { Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; +import {IsNotEmpty,IsString, IsUUID} from "class-validator" + +export class CreatePrivilegeRoleDto { + @ApiProperty({ + type: String, + description: "Privilege Id", + default: "", + }) + @Expose() + @IsUUID() + privilegeId: string; + + @ApiProperty({ + type: String, + description: "Role Id", + default: "", + }) + @Expose() + @IsUUID() + @IsNotEmpty() + roleId: string; + + constructor(obj: any) { + Object.assign(this, obj); + } +} diff --git a/src/rbac/assign-privilege/entities/assign-privilege.entity.ts b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts new file mode 100644 index 00000000..3b97429c --- /dev/null +++ b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts @@ -0,0 +1,25 @@ +import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; +import { Role } from 'src/rbac/role/entities/rbac.entity'; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn} from 'typeorm'; + +@Entity({ name: 'Role_Privilege_Mapping' }) +export class RolePrivilegeMapping { + @PrimaryGeneratedColumn('uuid') + Id: string; + + @Column('uuid') + roleId: string; + + @Column('uuid') + privilegeId: string; + + @ManyToOne(() => Privilege) + @JoinColumn({ name: 'privilege' }) + privilege: Privilege; + + @ManyToOne(() => Role, {nullable:true}) + @JoinColumn({ name: 'roleId' }) + role: Role; +} + + diff --git a/src/rbac/assign-role/entities/assign-role.entity.ts b/src/rbac/assign-role/entities/assign-role.entity.ts index b31d9b54..3c4617dd 100644 --- a/src/rbac/assign-role/entities/assign-role.entity.ts +++ b/src/rbac/assign-role/entities/assign-role.entity.ts @@ -9,7 +9,7 @@ export class UserRoleMapping { @Column('uuid') userId: string; - + @Column('uuid') roleId: string; diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index 74f55991..043963cf 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -2,12 +2,14 @@ import { Module } from "@nestjs/common"; import { RoleModule } from "./role/role.module"; import { PrivilegeModule } from './privilege/privilege.module'; import { AssignRoleModule } from './assign-role/assign-role.module'; +import { AssignPrivilegeModule } from "./assign-privilege/assign-privilege.module"; @Module({ imports: [ RoleModule, PrivilegeModule, - AssignRoleModule + AssignRoleModule, + AssignPrivilegeModule ], }) export class RbacModule {} diff --git a/src/rbac/role/entities/rbac.entity.ts b/src/rbac/role/entities/rbac.entity.ts index 3654324a..d25dcafa 100644 --- a/src/rbac/role/entities/rbac.entity.ts +++ b/src/rbac/role/entities/rbac.entity.ts @@ -8,4 +8,5 @@ export class Role { @Column() roleName: string; userRoleMappings: Role; + privilegeRoleMappings: Role } From de30a52a41aea66e0b09a9e016fbb1476f0b14a4 Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 15 Apr 2024 15:01:13 +0530 Subject: [PATCH 223/408] Task #217036: Made Minor Changes In user Module --- src/adapters/hasura/user.adapter.ts | 8 +++--- src/adapters/postgres/user-adapter.ts | 24 ++++++---------- src/adapters/userservicelocator.ts | 2 +- src/auth/auth.service.ts | 40 +++++++++++++++++---------- src/common/utils/keycloak.service.ts | 2 -- src/user/dto/user-create.dto.ts | 7 ++++- src/user/user.controller.ts | 8 +++--- 7 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 73ad7050..9681ebb7 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -16,6 +16,7 @@ import { } from "../../common/utils/keycloak.adapter.util"; import { UserCreateDto } from "src/user/dto/user-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { Response } from "express"; @Injectable() export class HasuraUserService implements IServicelocator { @@ -362,9 +363,8 @@ export class HasuraUserService implements IServicelocator { } public async updateUser( - userId: string, - request: any, - userUpdateDto: UserCreateDto + userUpdateDto: UserCreateDto, + userData ) { let query = ""; Object.keys(userUpdateDto).forEach((e) => { @@ -399,7 +399,7 @@ export class HasuraUserService implements IServicelocator { } `, variables: { - userId: userId, + userId: userUpdateDto.userId, }, }; diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 058accaf..6f089566 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -204,7 +204,6 @@ export class PostgresUserService { } async updateUser(userDto, response) { - const apiId = 'api.users.UpdateUserDetails' try { let updatedData = {}; if (userDto.userData || Object.keys(userDto.userData).length > 0) { @@ -221,20 +220,16 @@ export class PostgresUserService { } } } - return response - .status(HttpStatus.OK) - .send(APIResponse.success(apiId, updatedData, 'OK')); + return new SuccessResponse({ + statusCode: 200, + message: "ok", + data: updatedData, + }); } catch (e) { - response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - 'Something went wrong In finding UserDetails', - e, - 'INTERNAL_SERVER_ERROR', - ), - ); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } } @@ -264,7 +259,6 @@ export class PostgresUserService { async createUser(request: any, userCreateDto: UserCreateDto) { // It is considered that if user is not present in keycloak it is not present in database as well - let apiId = 'api.user.creatUser' try { const decoded: any = jwt_decode(request.headers.authorization); const userId = decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index 2059553b..41e218a4 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -13,7 +13,7 @@ export interface IServicelocator { // ); getUsersDetailsById(userData: Record, response:any); getUsersDetailsByCohortId(userData: Record, response:any); - updateUser(id?: string, request?: any, userDto?: any,response?: any); + updateUser(userDto?: any,response?: any); createUser(request: any, userDto: UserCreateDto); findUserDetails(userID:any,username:String) // searchUser( diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index f3299564..9572c864 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Injectable, UnauthorizedException } from "@nestjs/common"; +import { HttpStatus, Injectable, NotFoundException, UnauthorizedException } from "@nestjs/common"; import { UserAdapter } from "src/user/useradapter"; import axios from "axios"; import jwt_decode from "jwt-decode"; @@ -24,21 +24,31 @@ export class AuthService { async login(authDto) { const { username, password } = authDto; - const { - access_token, - expires_in, - refresh_token, - refresh_expires_in, - token_type, - } = await this.keycloakService.login(username, password).catch(() => {throw new UnauthorizedException();}); - return { - access_token, - refresh_token, - expires_in, - refresh_expires_in, - token_type, - }; + try { + const { + access_token, + expires_in, + refresh_token, + refresh_expires_in, + token_type + } = await this.keycloakService.login(username, password); + + return { + access_token, + refresh_token, + expires_in, + refresh_expires_in, + token_type + }; + } catch (error) { + if (error.response && error.response.status === 401) { + throw new NotFoundException("Invalid username or password"); + } else { + throw error; + } + } } + public async getUserByAuth(request: any, response) { diff --git a/src/common/utils/keycloak.service.ts b/src/common/utils/keycloak.service.ts index a72e205e..b291f3b3 100644 --- a/src/common/utils/keycloak.service.ts +++ b/src/common/utils/keycloak.service.ts @@ -54,9 +54,7 @@ export class KeycloakService { }, data: data, }; - console.log(axiosConfig); const res = await this.axios(axiosConfig); - console.log(res); return res.data; } diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 8589b24c..7b0a73c6 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -1,4 +1,4 @@ -import { Exclude, Expose } from "class-transformer"; +import {Expose } from "class-transformer"; import { MaxLength, IsNotEmpty, @@ -18,6 +18,7 @@ export class UserCreateDto { @ApiProperty({ type: () => User }) @Expose() + @IsNotEmpty() username: string; // @ApiProperty({ @@ -33,6 +34,7 @@ export class UserCreateDto { description: "The role of the user", }) @Expose() + @IsNotEmpty() role: string; @ApiPropertyOptional({ @@ -55,12 +57,14 @@ export class UserCreateDto { }) @Expose() @IsEmail() + @IsNotEmpty() email: string; @ApiProperty({ type: String, description: "The password of the user", }) + @IsNotEmpty() @Expose() password: string; @@ -109,6 +113,7 @@ export class UserCreateDto { description: "The cohort id of the user", }) @Expose() + @IsNotEmpty() cohortId: string; //fieldValues diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index fe519838..e7108bd5 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -11,6 +11,8 @@ import { Patch, UseGuards, Query, + UsePipes, + ValidationPipe, } from "@nestjs/common"; import { Request } from "@nestjs/common"; @@ -68,7 +70,6 @@ export class UserController { @Query("role") role: string | null = null, @Query("fieldvalue") fieldvalue: string | null = null ) { - // const tenantId = headers["tenantid"]; Can be Used In future // Context and ContextType can be taken from .env later let userData: any = { @@ -78,7 +79,6 @@ export class UserController { contextType: role && typeof role === 'string' && role !== ',' && role !== '{role}' ? role : null, fieldValue: fieldvalue && typeof fieldvalue === 'string' && fieldvalue !== ',' && fieldvalue !== '{fieldvalue}' ? fieldvalue : null }; - let result; if (userData.userId !== null) { result = await this.userAdapter.buildUserAdapter().getUsersDetailsById( @@ -115,11 +115,11 @@ export class UserController { @Post() @UseGuards(JwtAuthGuard) + @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User has been created successfully." }) @ApiBody({ type: UserCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -151,7 +151,7 @@ export class UserController { ) { // userDto.tenantId = headers["tenantid"]; userUpdateDto.userId = userId; - const result = await this.userAdapter.buildUserAdapter().updateUser(userId,request,userUpdateDto,response); + const result = await this.userAdapter.buildUserAdapter().updateUser(userUpdateDto,response); return response.status(result.statusCode).json(result); } From b17e25393e3bf68f68a194da75fb0a83b5122adc Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 15 Apr 2024 15:23:06 +0530 Subject: [PATCH 224/408] COHORT: Updating Cohort Data Without Modifying Field Values: Successful, Yet Encountering Errors --- src/adapters/cohortservicelocator.ts | 10 +-- src/adapters/hasura/cohort.adapter.ts | 97 +--------------------- src/adapters/postgres/cohort-adapter.ts | 104 +++++++++--------------- src/cohort/cohort.controller.ts | 60 ++------------ src/cohort/cohort.module.ts | 3 +- 5 files changed, 50 insertions(+), 224 deletions(-) diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index 0e5130e8..67af3469 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -5,12 +5,8 @@ import { CohortDto } from "src/cohort/dto/cohort.dto"; export interface IServicelocatorcohort { createCohort(request: any, cohortDto: CohortCreateDto); // getCohort(tenantId, cohortId, request, res); - searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto, res); + searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto); updateCohort(cohortId: string, request: any, cohortDto: CohortCreateDto); - getCohortList( - tenantid, - id, - request, - response - ); + // getCohortList(tenantid,id,request,response); + updateCohortStatus(cohortId: string) } diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index ae1ba820..71eb2e61 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -260,101 +260,8 @@ export class HasuraCohortService implements IServicelocatorcohort { } } - public async searchCohort( - tenantId: string, - request: any, - cohortSearchDto: CohortSearchDto, - res: any - ) { - try{ - let entityFilter = cohortSearchDto; - let filedsFilter = entityFilter?.filters["fields"]; - //remove fields from filter - delete entityFilter.filters["fields"]; - let newCohortSearchDto = null; - //check fields value present or not - if (filedsFilter) { - //apply filter on fields value - let response_fields_value = - await this.fieldsService.searchFieldValuesFilter(request,filedsFilter); - if (response_fields_value?.data?.errors) { - return res.status(200).send({ - errorCode: response_fields_value?.data?.errors[0]?.extensions?.code, - errorMessage: response_fields_value?.data?.errors[0]?.message, - }); - } else { - //get filter result - let result_FieldValues = response_fields_value?.data?.data?.FieldValues; - //fetch cohot id list - let cohort_id_list = []; - for (let i = 0; i < result_FieldValues.length; i++) { - cohort_id_list.push(result_FieldValues[i].itemId); - } - //remove duplicate entries - cohort_id_list = cohort_id_list.filter( - (item, index) => cohort_id_list.indexOf(item) === index - ); - let cohort_filter = new Object(entityFilter.filters); - cohort_filter["cohortId"] = { - _in: cohort_id_list, - }; - newCohortSearchDto = new CohortSearchDto({ - limit: entityFilter.limit, - page: entityFilter.page, - filters: cohort_filter, - }); - } - } else { - newCohortSearchDto = new CohortSearchDto({ - limit: entityFilter.limit, - page: entityFilter.page, - filters: entityFilter.filters, - }); - } - if (newCohortSearchDto) { - const response = await this.searchCohortQuery( - request, - tenantId, - newCohortSearchDto - ); - if (response?.data?.errors) { - return res.status(200).send({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response?.data?.data?.Cohort; - let cohortResponse = await this.mappedResponse(result); - //const count = cohortResponse.length; - const count = result.length; - //get cohort fields value - let result_data = await this.searchCohortFields( - request, - tenantId, - cohortResponse - ); - return res.status(200).send({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: result_data, - }); - } - } else { - return res.status(200).send({ - errorCode: "filter invalid", - errorMessage: "filter invalid", - }); - } - }catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "401", - errorMessage: e, - }); - } - } - + public async searchCohort(tenantId: string,request: any,cohortSearchDto: CohortSearchDto) {} + public async updateCohortStatus(cohortId: string) {} public async updateCohort( cohortId: string, request: any, diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 046f1e58..e9a632ee 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -34,37 +34,6 @@ export class PostgresCohortService { private fieldsService: PostgresFieldsService, ) { } - public async getCohortsDetails(tenantId: string, - cohortId: string, - request: any, - response: any){ - const apiId = "api.concept.cohortDetails"; - let cohortName = await this.cohortRepository.findOne({ - where:{cohortId} - }) - // let result = { - // cohortData: [], - // }; - let cohortData = { - cohortId: cohortId, - name:cohortName.name, - parentId:cohortName.parentId, - customField:{} - }; - const getDetails = await this.getCohortListDetails(cohortId); - cohortData.customField=getDetails - // result.cohortData.push(cohortData); - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - cohortData, - "OK" - ) - ); - } - public async getCohortList( tenantId: string, userId: string, @@ -184,6 +153,7 @@ export class PostgresCohortService { cohortUpdateDto: CohortCreateDto ) { try { + const cohortUpdateData: any = {}; Object.keys(cohortUpdateDto).forEach((e) => { @@ -199,42 +169,42 @@ export class PostgresCohortService { const response = await this.cohortRepository.update(cohortId, cohortUpdateData); - - let field_value_array = cohortUpdateDto.fieldValues.split("|"); - - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - - let fieldValues = field_value_array[i].split(":"); - let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; - try { - const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) - const rowid = fieldVauesRowId.fieldValuesId; - - let fieldValueDto: FieldValuesDto = { - fieldValuesId: rowid, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.updateFieldValues(rowid, fieldValueDto); - }catch{ - let fieldValueDto: FieldValuesDto = { - fieldValuesId: null, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.createFieldValues(request, fieldValueDto); + if(cohortUpdateDto.fieldValues){ + let field_value_array = cohortUpdateDto.fieldValues.split("|"); + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + + let fieldValues = field_value_array[i].split(":"); + let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + try { + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + const rowid = fieldVauesRowId.fieldValuesId; + + let fieldValueDto: FieldValuesDto = { + fieldValuesId: rowid, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.updateFieldValues(rowid, fieldValueDto); + }catch{ + let fieldValueDto: FieldValuesDto = { + fieldValuesId: null, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.createFieldValues(request, fieldValueDto); + } } } } diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 02fc7003..d8dcd2f1 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -6,6 +6,7 @@ import { ApiBasicAuth, ApiConsumes, ApiHeader, + ApiOkResponse, } from "@nestjs/swagger"; import { Controller, @@ -34,7 +35,6 @@ import { diskStorage } from "multer"; import { Response, response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; -import { CohortService } from "./cohort.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { QueryParamsDto } from "./dto/query-params.dto"; @@ -42,7 +42,7 @@ import { QueryParamsDto } from "./dto/query-params.dto"; @Controller("cohort") @UseGuards(JwtAuthGuard) export class CohortController { - constructor(private readonly cohortService: CohortService,private readonly cohortAdapter:CohortAdapter) {} + constructor(private readonly cohortAdapter:CohortAdapter) {} //create cohort @Post() @ApiConsumes("multipart/form-data") @@ -82,44 +82,6 @@ export class CohortController { ); return response.status(result.statusCode).json(result); } - - @Get("cohortDetails?") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort details" }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", - }) - public async getCohortDetails( - @Headers() headers, - @Query() queryParams: QueryParamsDto, - @Req() request: Request, - @Res() response: Response - ) { - if(!Object.keys(queryParams).length){ - return response.status(400).json({ - message:"Please enter Query Params" - }) - } - queryParams.name = queryParams.name.toLocaleLowerCase(); - let data; - let tenantId = request.headers['tenantId'] - if (queryParams?.name=== 'user') { - data=queryParams - return this.cohortService.getCohortsDetails(data,request,response) - } else if (queryParams?.name === 'cohort') { - data=queryParams - return this.cohortService.getCohortsDetails(data,request,response) - } else { - return response.status(400).json({ - message:"Invaid Parameters.", - data:`Valid format should be name="cohortoruser" and id=value` - }) - } - } // search @Post("/search") @@ -142,7 +104,7 @@ export class CohortController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.cohortService.searchCohort( + const result = await this.cohortAdapter.buildCohortAdapter().searchCohort( tenantid, request, cohortSearchDto @@ -179,7 +141,7 @@ export class CohortController { }; Object.assign(cohortCreateDto, imgresponse); - const result = await this.cohortService.updateCohort( + const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( cohortId, request, cohortCreateDto @@ -187,26 +149,18 @@ export class CohortController { return response.status(result.statusCode).json(result); } + //delete cohort @Delete("/:id") - @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort has been deleted successfully." }) - @ApiBody({ type: CohortCreateDto }) + @ApiOkResponse({ description: "Cohort has been deleted successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) public async updateCohortStatus( @Param("id") cohortId: string, @Req() request: Request, - @Body() cohortCreateDto: CohortCreateDto, - @UploadedFile() image, @Res() response: Response ) { - const imgresponse = { - image: image?.filename, - }; - Object.assign(cohortCreateDto, imgresponse); - const result = await this.cohortService.updateCohortStatus(cohortId); + const result = await this.cohortAdapter.buildCohortAdapter().updateCohortStatus(cohortId); return response.status(result.statusCode).json(result); } } diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 1779fe4c..c4e9e15b 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -3,7 +3,6 @@ import { CohortController } from "./cohort.controller"; import { HttpModule } from "@nestjs/axios"; import { CohortAdapter } from "./cohortadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; -import { CohortService } from "./cohort.service"; import { TypeOrmModule } from "@nestjs/typeorm"; import { Cohort } from "./entities/cohort.entity"; import { FieldsService } from "../fields/fields.service"; @@ -21,6 +20,6 @@ import { PostgresCohortService } from "src/adapters/postgres/cohort-adapter"; PostgresModule ], controllers: [CohortController], - providers: [CohortAdapter, CohortService, FieldsService,PostgresCohortService], + providers: [CohortAdapter, FieldsService,PostgresCohortService], }) export class CohortModule {} From 5c9fe92500c13b347a19d25963e7e50699587246 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 15 Apr 2024 18:08:25 +0530 Subject: [PATCH 225/408] Fix[Search API changes] --- src/adapters/postgres/attendance-adapter.ts | 12 +++----- src/attendance/attendance.controller.ts | 2 +- src/attendance/dto/attendance-search.dto.ts | 33 ++++++++++++++++++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 46a9cb33..8543c1bb 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -58,9 +58,7 @@ export class PostgresAttendanceService { let whereClause = `u."tenantId" = '${tenantId}'`; // Default WHERE clause for filtering by tenantId let attendanceList = '' if (filters && Object.keys(filters).length > 0) { - // Construct additional WHERE conditions based on filters for (const [key, value] of Object.entries(filters)) { - // Check if the key exists in UserKeys, AttendanceKeys, or CohortMembersKeys if (UserKeys.includes(key)) { whereClause += ` AND u."${key}" = '${value}'`; } else if (AttendaceKeys.includes(key)) { @@ -71,6 +69,8 @@ export class PostgresAttendanceService { whereClause += ` AND a."${key}" = '${value}'`; } else if (CohortMembersKeys.includes(key)) { whereClause += ` AND cm."${key}" = '${value}'`; + } else if(filters.fromDate && filters.toDate ){ + whereClause += ` AND a."attendanceDate" BETWEEN '${filters['fromDate']}' AND '${filters['toDate']}'`; } else{ return new ErrorResponseTypeOrm({ @@ -92,18 +92,14 @@ export class PostgresAttendanceService { a.* FROM "Users" u - LEFT JOIN + INNER JOIN "CohortMembers" cm ON cm."userId" = u."userId" LEFT JOIN "Attendance" a ON a."userId" = cm."userId" ${attendanceList} where ${whereClause} ` -console.log(query,"query") - - - - const results = await this.userRepository.query(query); + const results = await this.attendanceRepository.query(query); // console.log(results,"results") const mappedResponse = await this.mappedResponse(results); diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index b231321a..83e9f095 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -166,7 +166,7 @@ export class AttendanceController { ) { let tenantid = headers["tenantid"]; - const result = this.attendaceAdapter.buildAttenceAdapter().searchAttendance( + const result = await this.attendaceAdapter.buildAttenceAdapter().searchAttendance( tenantid, request, studentSearchDto diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index 45c66fd5..d7210461 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -1,4 +1,28 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { Matches, Validate, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator"; +import { isBefore, isSameDay } from "date-fns"; + + +@ValidatorConstraint({ name: "validDateRange", async: false }) +export class ValidDateRangeConstraint implements ValidatorConstraintInterface { + validate(value: any, args: ValidationArguments) { + const { toDate, fromDate } = value; + + // If either fromDate or toDate is not provided, validation passes + if (!fromDate || !toDate) { + return true; + } + + return isBefore(new Date(fromDate), new Date(toDate)) || isSameDay(new Date(fromDate), new Date(toDate)); + } + + defaultMessage(args: ValidationArguments) { + return "Invalid date range. 'toDate' must be after or equal to 'fromDate'."; + } +} + + + export class AttendanceSearchDto { @ApiProperty({ @@ -18,7 +42,14 @@ export class AttendanceSearchDto { description: "Filters", }) @ApiPropertyOptional() - filters: object; + @Validate(ValidDateRangeConstraint, { message: "Invalid date range." }) + filters: { + fromDate?: string; + toDate?: string; + [key: string]: any; // Allows additional dynamic keys + }; + + constructor(partial: Partial) { Object.assign(this, partial); From a76a2edbb9a3059fcb053cd3cb0137baa00d0c6f Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 15 Apr 2024 18:11:39 +0530 Subject: [PATCH 226/408] Fix[removed console logs] --- src/adapters/postgres/attendance-adapter.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 8543c1bb..0a82e800 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -83,9 +83,6 @@ export class PostgresAttendanceService { } - - - console.log(attendanceList,whereClause,"Shubham"); const query =`SELECT u.*, cm.*, @@ -101,7 +98,6 @@ export class PostgresAttendanceService { ` const results = await this.attendanceRepository.query(query); - // console.log(results,"results") const mappedResponse = await this.mappedResponse(results); From f5eae4e6ad8d7bcb8df455f9592ec35953e7352e Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 15 Apr 2024 18:13:25 +0530 Subject: [PATCH 227/408] Fix[code change for filter] --- src/adapters/postgres/attendance-adapter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 0a82e800..cad98bb4 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -70,7 +70,7 @@ export class PostgresAttendanceService { } else if (CohortMembersKeys.includes(key)) { whereClause += ` AND cm."${key}" = '${value}'`; } else if(filters.fromDate && filters.toDate ){ - whereClause += ` AND a."attendanceDate" BETWEEN '${filters['fromDate']}' AND '${filters['toDate']}'`; + whereClause += ` AND a."attendanceDate" BETWEEN '${filters.fromDate}' AND '${filters.toDate}'`; } else{ return new ErrorResponseTypeOrm({ From b13987552df2b831b65c971c90875faf0268fbdf Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 15 Apr 2024 18:21:44 +0530 Subject: [PATCH 228/408] Get cohort Api changes --- src/adapters/cohortservicelocator.ts | 3 +- src/adapters/hasura/cohort.adapter.ts | 1 + src/adapters/postgres/cohort-adapter.ts | 103 ++++++++++++++++++++++-- src/cohort/cohort.controller.ts | 19 ++++- 4 files changed, 117 insertions(+), 9 deletions(-) diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index 67af3469..83263f56 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -7,6 +7,7 @@ export interface IServicelocatorcohort { // getCohort(tenantId, cohortId, request, res); searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto); updateCohort(cohortId: string, request: any, cohortDto: CohortCreateDto); + getCohortsDetails(cohortId: string); // getCohortList(tenantid,id,request,response); - updateCohortStatus(cohortId: string) + updateCohortStatus(cohortId: string); } diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index 71eb2e61..bf1e3a0c 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -262,6 +262,7 @@ export class HasuraCohortService implements IServicelocatorcohort { public async searchCohort(tenantId: string,request: any,cohortSearchDto: CohortSearchDto) {} public async updateCohortStatus(cohortId: string) {} + public async getCohortsDetails(cohortId: string) {} public async updateCohort( cohortId: string, request: any, diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index e9a632ee..2678ea81 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -12,6 +12,7 @@ import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; +import { Fields } from "src/fields/entities/fields.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { PostgresFieldsService } from "./fields-adapter" // import { FieldValues } from "src/fields/entities/field-values.entity"; @@ -31,6 +32,8 @@ export class PostgresCohortService { private cohortRepository: Repository, @InjectRepository(CohortMembers) private cohortMembersRepository: Repository, + @InjectRepository(Fields) + private fieldsRepository: Repository, private fieldsService: PostgresFieldsService, ) { } @@ -50,12 +53,12 @@ export class PostgresCohortService { for (let data of findCohortId) { let cohortData = { cohortId: data.cohortId, - name:data.name, - parentId:data.parentId, - customField:{} + name: data.name, + parentId: data.parentId, + customField: {} }; const getDetails = await this.getCohortListDetails(data.cohortId); - cohortData.customField=getDetails + cohortData.customField = getDetails result.cohortData.push(cohortData); } @@ -72,6 +75,92 @@ export class PostgresCohortService { } } + public async getCohortsDetails(cohortId: string) { + let apiId = "api.concept.getCohortDetails"; + try { + + const result = { + cohortData: { + } + }; + + let customFieldsArray = []; + + const [filledValues, cohortDetails] = await Promise.all([ + this.findFilledValues(cohortId), + this.findCohortDetails(cohortId) + ]); + const customFields = await this.findCustomFields() + + + result.cohortData = cohortDetails; + const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); + for (let data of customFields) { + const fieldValue = filledValuesMap.get(data.fieldId); + const customField = { + fieldId: data.fieldId, + label: data.label, + value: fieldValue || '', + options: data?.fieldParams?.['options'] || {}, + type: data.type || '' + }; + customFieldsArray.push(customField); + } + result.cohortData['customFields'] = customFieldsArray; + + // let cohortName = await this.cohortRepository.findOne({ + // where: { cohortId: cohortId }, + // select: ["name", "parentId"], + // }); + // let cohortData = { + // cohortId: cohortId, + // name: cohortName?.name, + // parentId: cohortName?.parentId, + // customField: {}, + // }; + // const getDetails = await this.getCohortListDetails(cohortId); + // cohortData.customField = getDetails; + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: result, + }); + + } catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + } + + async findFilledValues(cohortId: string) { + let query = `SELECT C."cohortId",F."fieldId",F."value" FROM public."Cohort" C + LEFT JOIN public."FieldValues" F + ON C."cohortId" = F."itemId" where C."cohortId" =$1`; + let result = await this.cohortRepository.query(query, [cohortId]); + return result; + } + + async findCohortDetails(cohortId: string) { + let whereClause: any = { cohortId: cohortId }; + let cohortDetails = await this.cohortRepository.findOne({ + where: whereClause + }) + return cohortDetails; + } + + async findCustomFields() { + let customFields = await this.fieldsRepository.find({ + where: { + context: 'COHORT', + contextType: 'COHORT' + } + }) + return customFields; + } + public async findCohortName(userId: any) { let query = `SELECT c."name",c."cohortId",c."parentId" FROM public."CohortMembers" AS cm @@ -153,7 +242,7 @@ export class PostgresCohortService { cohortUpdateDto: CohortCreateDto ) { try { - + const cohortUpdateData: any = {}; Object.keys(cohortUpdateDto).forEach((e) => { @@ -169,7 +258,7 @@ export class PostgresCohortService { const response = await this.cohortRepository.update(cohortId, cohortUpdateData); - if(cohortUpdateDto.fieldValues){ + if (cohortUpdateDto.fieldValues) { let field_value_array = cohortUpdateDto.fieldValues.split("|"); if (field_value_array.length > 0) { let field_values = []; @@ -192,7 +281,7 @@ export class PostgresCohortService { updatedAt: new Date().toISOString(), }; await this.fieldsService.updateFieldValues(rowid, fieldValueDto); - }catch{ + } catch { let fieldValueDto: FieldValuesDto = { fieldValuesId: null, value: fieldValues[1] ? fieldValues[1].trim() : "", diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index d8dcd2f1..5964538d 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -43,6 +43,7 @@ import { QueryParamsDto } from "./dto/query-params.dto"; @UseGuards(JwtAuthGuard) export class CohortController { constructor(private readonly cohortAdapter:CohortAdapter) {} + //create cohort @Post() @ApiConsumes("multipart/form-data") @@ -59,7 +60,6 @@ export class CohortController { ) @ApiBody({ type: CohortCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -83,6 +83,23 @@ export class CohortController { return response.status(result.statusCode).json(result); } + //Get Cohort Details + @Get("/:id") + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Cohort has been deleted successfully." }) + @ApiForbiddenResponse({ description: "Forbidden" }) + public async getCohortsDetails( + @Param("id") cohortId: string, + @Req() request: Request, + @Res() response: Response + ) { + + const result = await this.cohortAdapter.buildCohortAdapter().getCohortsDetails(cohortId); + return response.status(result.statusCode).json(result); + // return this.cohortAdapter.buildCohortAdapter.getCohortsDetails(data,request,response) + + } + // search @Post("/search") @ApiBasicAuth("access-token") From 3318d15b033d32efcdb5881e9de665940959156e Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 15 Apr 2024 18:40:18 +0530 Subject: [PATCH 229/408] Get cohort Api changes --- src/adapters/postgres/cohort-adapter.ts | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 2678ea81..c6c0be91 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -86,11 +86,11 @@ export class PostgresCohortService { let customFieldsArray = []; - const [filledValues, cohortDetails] = await Promise.all([ + const [filledValues, cohortDetails, customFields] = await Promise.all([ this.findFilledValues(cohortId), - this.findCohortDetails(cohortId) + this.findCohortDetails(cohortId), + this.findCustomFields() ]); - const customFields = await this.findCustomFields() result.cohortData = cohortDetails; @@ -108,19 +108,6 @@ export class PostgresCohortService { } result.cohortData['customFields'] = customFieldsArray; - // let cohortName = await this.cohortRepository.findOne({ - // where: { cohortId: cohortId }, - // select: ["name", "parentId"], - // }); - // let cohortData = { - // cohortId: cohortId, - // name: cohortName?.name, - // parentId: cohortName?.parentId, - // customField: {}, - // }; - // const getDetails = await this.getCohortListDetails(cohortId); - // cohortData.customField = getDetails; - return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", From f4898e9a7de68593409933028fe857f83c9b187e Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 16 Apr 2024 11:09:52 +0530 Subject: [PATCH 230/408] minor code changes --- src/adapters/cohortservicelocator.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index 83263f56..a756a9ca 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -4,10 +4,8 @@ import { CohortDto } from "src/cohort/dto/cohort.dto"; export interface IServicelocatorcohort { createCohort(request: any, cohortDto: CohortCreateDto); - // getCohort(tenantId, cohortId, request, res); searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto); updateCohort(cohortId: string, request: any, cohortDto: CohortCreateDto); getCohortsDetails(cohortId: string); - // getCohortList(tenantid,id,request,response); updateCohortStatus(cohortId: string); } From af65dc27bf68649ad8adf7fc7774d25103a1e4a6 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 16 Apr 2024 11:10:56 +0530 Subject: [PATCH 231/408] minor code changes --- src/adapters/cohortservicelocator.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index 67af3469..0eea3db0 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -4,9 +4,7 @@ import { CohortDto } from "src/cohort/dto/cohort.dto"; export interface IServicelocatorcohort { createCohort(request: any, cohortDto: CohortCreateDto); - // getCohort(tenantId, cohortId, request, res); searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto); updateCohort(cohortId: string, request: any, cohortDto: CohortCreateDto); - // getCohortList(tenantid,id,request,response); - updateCohortStatus(cohortId: string) + updateCohortStatus(cohortId: string); } From 71d12c750499ba9957d1c94656b07bf7a1759c55 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Tue, 16 Apr 2024 14:28:06 +0530 Subject: [PATCH 232/408] Fix[change for mark attendance API as search attendance API changed] --- src/adapters/postgres/attendance-adapter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index cad98bb4..a0459ccd 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -361,7 +361,7 @@ export class PostgresAttendanceService { } if ( - attendanceFound.data.length > 0 && + attendanceFound.data.length > 0 && attendanceFound.data[0].attendanceId != "" && attendanceFound.statusCode === 200 && attendanceFound instanceof SuccessResponse ) { From 0f888f788e12f3b961f5f863f043b8c78747668f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 16 Apr 2024 18:51:44 +0530 Subject: [PATCH 233/408] COHORT: Updated Swagger --- src/cohort/cohort.controller.ts | 42 +++++++++++++++++---------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 02fc7003..34198c5b 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -6,6 +6,9 @@ import { ApiBasicAuth, ApiConsumes, ApiHeader, + ApiBadRequestResponse, + ApiInternalServerErrorResponse, + ApiOkResponse, } from "@nestjs/swagger"; import { Controller, @@ -48,6 +51,9 @@ export class CohortController { @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort has been created successfully." }) + @ApiBadRequestResponse({description: "Bad request."}) + @ApiInternalServerErrorResponse({description: "Internal Server Error."}) + @UseInterceptors( FileInterceptor("image", { storage: diskStorage({ @@ -58,7 +64,7 @@ export class CohortController { }) ) @ApiBody({ type: CohortCreateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", @@ -85,8 +91,10 @@ export class CohortController { @Get("cohortDetails?") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort details" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiOkResponse({ description: "Cohort details" }) + @ApiBadRequestResponse({description: "Bad request."}) + @ApiInternalServerErrorResponse({description: "Internal Server Error."}) + @SerializeOptions({ strategy: "excludeAll", }) @@ -124,9 +132,10 @@ export class CohortController { // search @Post("/search") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort list." }) @ApiBody({ type: CohortSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiOkResponse({ description: "Cohort list" }) + @ApiBadRequestResponse({description: "Bad request."}) + @ApiInternalServerErrorResponse({description: "Internal Server Error."}) // @UseInterceptors(ClassSerializerInterceptor) @UsePipes(ValidationPipe) @SerializeOptions({ @@ -154,7 +163,6 @@ export class CohortController { @Put("/:id") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort has been updated successfully." }) @UseInterceptors( FileInterceptor("image", { storage: diskStorage({ @@ -165,8 +173,10 @@ export class CohortController { }) ) @ApiBody({ type: CohortCreateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) + @ApiOkResponse({ description: "Cohort has been updated successfully" }) + @ApiBadRequestResponse({description: "Bad request."}) + @ApiInternalServerErrorResponse({description: "Internal Server Error."}) + public async updateCohort( @Param("id") cohortId: string, @Req() request: Request, @@ -189,23 +199,15 @@ export class CohortController { //delete cohort @Delete("/:id") - @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Cohort has been deleted successfully." }) - @ApiBody({ type: CohortCreateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) + @ApiOkResponse({ description: "Cohort has been deleted successfully." }) + @ApiBadRequestResponse({description: "Bad request."}) + @ApiInternalServerErrorResponse({description: "Internal Server Error."}) public async updateCohortStatus( @Param("id") cohortId: string, - @Req() request: Request, - @Body() cohortCreateDto: CohortCreateDto, - @UploadedFile() image, @Res() response: Response ) { - const imgresponse = { - image: image?.filename, - }; - Object.assign(cohortCreateDto, imgresponse); + const result = await this.cohortService.updateCohortStatus(cohortId); return response.status(result.statusCode).json(result); } From ff8dcbcf69c4c39b316d5baf264c952588a7ebaa Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 17 Apr 2024 14:58:14 +0530 Subject: [PATCH 234/408] Task #217372: Added user seacrh API and Updated get User details API --- src/adapters/postgres/user-adapter.ts | 75 +++++++++++++++- src/adapters/userservicelocator.ts | 12 +-- src/cohort/cohort.controller.ts | 2 +- src/user/dto/user-update.dto.ts | 4 +- src/user/user.controller.ts | 123 +++++++++----------------- 5 files changed, 123 insertions(+), 93 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 6f089566..9678f7be 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -17,6 +17,8 @@ import APIResponse from '../../utils/response'; import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; import axios, { AxiosInstance, AxiosRequestConfig } from "axios" import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { isUUID } from 'class-validator'; +import { UserSearchDto } from 'src/user/dto/user-search.dto'; @Injectable() @@ -33,22 +35,89 @@ export class PostgresUserService { @InjectRepository(CohortMembers) private cohortMemberRepository: Repository ) { } + async searchUser(tenantId: string, + request: any, + response: any, + userSearchDto: UserSearchDto){ + try { + let findData = await this.findAllUserDetails(userSearchDto); + if(!findData){ + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'No Data Found For User',}); + } + console.log("Hi"); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: findData, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async findAllUserDetails(userSearchDto){ + let { limit, page, filters } = userSearchDto; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + const results = await this.usersRepository.find({ + where: whereClause, + skip: offset, + take: parseInt(limit), + }); + return results; + } + async getUsersDetailsById(userData: Record, response: any) { - let apiId = 'api.users.getUsersDetails' try { + if (!isUUID(userData.userId)) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'Please Enter Valid User ID', + }); + } const result = { userData: { } }; - let customFieldsArray = []; const [filledValues, userDetails] = await Promise.all([ this.findFilledValues(userData.userId), this.findUserDetails(userData.userId) ]); - + if(!userDetails){ + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'User Not Found', + }); + } + if(!userData.fieldValue){ + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: userDetails, + }); + } const customFields = await this.findCustomFields(userData, userDetails.role) result.userData = userDetails; diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index 41e218a4..3832723a 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -16,11 +16,11 @@ export interface IServicelocator { updateUser(userDto?: any,response?: any); createUser(request: any, userDto: UserCreateDto); findUserDetails(userID:any,username:String) - // searchUser( - // tenantId: string, - // request: any, - // response: any, - // userSearchDto: UserSearchDto - // ); + searchUser( + tenantId: string, + request: any, + response: any, + userSearchDto: UserSearchDto + ); resetUserPassword(request: any, username: string, newPassword: string); } diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 02fc7003..8146209a 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -39,7 +39,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") -@Controller("cohort") +@Controller("cohorts") @UseGuards(JwtAuthGuard) export class CohortController { constructor(private readonly cohortService: CohortService,private readonly cohortAdapter:CohortAdapter) {} diff --git a/src/user/dto/user-update.dto.ts b/src/user/dto/user-update.dto.ts index f7b58ea8..8079b6d3 100644 --- a/src/user/dto/user-update.dto.ts +++ b/src/user/dto/user-update.dto.ts @@ -1,5 +1,5 @@ import { IsString, IsOptional, IsArray, ValidateNested } from 'class-validator'; -import { Type } from 'class-transformer'; +import { Expose, Type } from 'class-transformer'; class UserDataDTO { @@ -67,7 +67,7 @@ export class UserUpdateDTO { @IsString() userId: string; - + @Expose() @ValidateNested() @Type(() => UserDataDTO) userData: UserDataDTO; diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index e7108bd5..4ddc280f 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -13,6 +13,7 @@ import { Query, UsePipes, ValidationPipe, + HttpStatus, } from "@nestjs/common"; import { Request } from "@nestjs/common"; @@ -24,8 +25,10 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiQuery, - ApiConsumes, ApiHeader, + ApiNotFoundResponse, + ApiInternalServerErrorResponse, + ApiBadRequestResponse, } from "@nestjs/swagger"; import { UserDto } from "./dto/user.dto"; @@ -35,83 +38,43 @@ import { UserCreateDto } from "./dto/user-create.dto"; import { UserUpdateDTO } from "./dto/user-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { Response } from "express"; +import { isUUID } from "class-validator"; +import { SuccessResponse } from "src/success-response"; @ApiTags("User") -@Controller("user") +@Controller("users") export class UserController { constructor( private userAdapter: UserAdapter, ) {} - /** - * Method to get The User Details and Custome Fields Data. - * - * @param userId $data User Id of User - * - * @return UserData Object containing all teh detals - * - * @since 1.6 - */ - @Get() + @Get('/:userId') @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "User detail." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiOkResponse({ description: "User detais Fetched Succcessfully" }) + @ApiNotFoundResponse({ description: "User Not Found" }) + @ApiInternalServerErrorResponse({description:"Internal Server Error" }) + @ApiBadRequestResponse({description:"Bad Request"}) @SerializeOptions({ strategy: "excludeAll", }) @ApiHeader({ name: "tenantid", }) - @ApiQuery({ name: 'userid', description: 'The user ID (optional)', required: false, }) - @ApiQuery({ name: 'cohortid', description: 'The cohort ID (optional)', required: false, }) - @ApiQuery({ name: 'role', description: 'The role (optional)', required: false, }) - @ApiQuery({ name: 'fieldvalue', description: 'The field Value (optional)', required: false }) + @ApiQuery({ name: 'fieldvalue', description: 'Send True to Fetch Custom Field of User', required: false }) public async getUser( @Headers() headers, @Req() request: Request, @Res() response: Response, - @Query("userid") userId: string | null = null, - @Query("cohortid") cohortId: string | null = null, - @Query("role") role: string | null = null, + @Param("userId") userId: string, @Query("fieldvalue") fieldvalue: string | null = null ) { // const tenantId = headers["tenantid"]; Can be Used In future // Context and ContextType can be taken from .env later - let userData: any = { + let userData = { context: "USERS", - userId: userId && typeof userId === 'string' && userId !== ',' && userId !== '{userid}' ? userId : null, - cohortId: cohortId && typeof cohortId === 'string' && cohortId !== ',' && cohortId !== '{cohortid}' ? cohortId : null, - contextType: role && typeof role === 'string' && role !== ',' && role !== '{role}' ? role : null, - fieldValue: fieldvalue && typeof fieldvalue === 'string' && fieldvalue !== ',' && fieldvalue !== '{fieldvalue}' ? fieldvalue : null - }; - let result; - if (userData.userId !== null) { - result = await this.userAdapter.buildUserAdapter().getUsersDetailsById( - userData, response); - } - else if (userData.cohortId !== null) { - result = await this.userAdapter.buildUserAdapter().getUsersDetailsByCohortId( - userData, response); + userId: userId, + fieldValue: fieldvalue } - if (userData.userId == null && userData.cohortId == null) { - return response.status(400).json({ - statusCode: 400, - error: "Please entire userId or cohortId in query parameters" - }); - } - + let result; + result = await this.userAdapter.buildUserAdapter().getUsersDetailsById(userData, response); return response.status(result.statusCode).json(result); } - // @Get() - // @ApiBasicAuth("access-token") - // @ApiOkResponse({ description: "User detail." }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @SerializeOptions({ - // strategy: "excludeAll", - // }) - // @ApiHeader({ - // name: "tenantid", - // }) - // public async getUserByAuth(@Headers() headers, @Req() request: Request) { - // const tenantId = headers["tenantid"]; - // return this.userAdapter.buildUserAdapter().getUserByAuth(tenantId, request); - // } @Post() @UseGuards(JwtAuthGuard) @@ -119,7 +82,8 @@ export class UserController { @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User has been created successfully." }) @ApiBody({ type: UserCreateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiForbiddenResponse({ description: "User Already Exists"}) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @ApiHeader({ name: "tenantid", }) @@ -137,6 +101,7 @@ export class UserController { @Patch("/:userid") @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") + @ApiBody({ type: UserUpdateDTO }) @ApiCreatedResponse({ description: "User has been updated successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ @@ -155,28 +120,26 @@ export class UserController { return response.status(result.statusCode).json(result); } - // @Post("/search") - // @ApiBasicAuth("access-token") - // @ApiCreatedResponse({ description: "User list." }) - // @ApiBody({ type: UserSearchDto }) - // @ApiForbiddenResponse({ description: "Forbidden" }) - // @SerializeOptions({ - // strategy: "excludeAll", - // }) - // @ApiHeader({ - // name: "tenantid", - // }) - // public async searchUser( - // @Headers() headers, - // @Req() request: Request, - // @Res() response: Response, - // @Body() userSearchDto: UserSearchDto - // ) { - // const tenantId = headers["tenantid"]; - // return await this.userAdapter - // .buildUserAdapter() - // .searchUser(tenantId, request, response, userSearchDto); - // } + @Post("/search") + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "User list." }) + @ApiBody({ type: UserSearchDto }) + @SerializeOptions({ + strategy: "excludeAll", + }) + @ApiHeader({ + name: "tenantid", + }) + public async searchUser( + @Headers() headers, + @Req() request: Request, + @Res() response: Response, + @Body() userSearchDto: UserSearchDto + ) { + const tenantId = headers["tenantid"]; + const result = await this.userAdapter.buildUserAdapter().searchUser(tenantId,request,response,userSearchDto); + return response.status(result.statusCode).json(result); + } @Post("/reset-password") @ApiBasicAuth("access-token") @@ -195,6 +158,4 @@ export class UserController { .buildUserAdapter() .resetUserPassword(request, reqBody.username, reqBody.newPassword); } - - } From 9c0571b2829f3ef7c0cea2c61b06c615d7b591a4 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 17 Apr 2024 18:07:46 +0530 Subject: [PATCH 235/408] Fix[Swagger related changes and added validation for valid combination of contextId and userId] --- src/adapters/hasura/attendance.adapter.ts | 6 +- src/adapters/postgres/attendance-adapter.ts | 59 ++++++++++++++----- src/attendance/attendance.controller.ts | 5 +- src/attendance/dto/attendance-search.dto.ts | 63 +++++++++++++++++---- src/attendance/dto/attendance.dto.ts | 16 +++++- 5 files changed, 117 insertions(+), 32 deletions(-) diff --git a/src/adapters/hasura/attendance.adapter.ts b/src/adapters/hasura/attendance.adapter.ts index a6a029c7..2ca696f0 100644 --- a/src/adapters/hasura/attendance.adapter.ts +++ b/src/adapters/hasura/attendance.adapter.ts @@ -206,7 +206,7 @@ export class AttendanceHasuraService implements IServicelocator { parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); } - attendanceSearchDto.filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + attendanceSearchDto.filters["tenantId"] = tenantId ? tenantId : ""; Object.keys(attendanceSearchDto.filters).forEach((item) => { Object.keys(attendanceSearchDto.filters[item]).forEach((e) => { if (!e.startsWith("_")) { @@ -401,8 +401,8 @@ export class AttendanceHasuraService implements IServicelocator { const attendanceToSearch = new AttendanceSearchDto({}); attendanceToSearch.filters = { - attendanceDate: { _eq: attendanceDto.attendanceDate }, - userId: { _eq: attendanceDto.userId }, + attendanceDate: attendanceDto.attendanceDate, // Assign the value directly + userId: attendanceDto.userId, }; const attendanceFound: any = await this.searchAttendance( diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index a0459ccd..43ba2f42 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -326,19 +326,25 @@ export class PostgresAttendanceService { */ public async updateAttendanceRecord( - request: any, + loginUserId, attendanceDto: AttendanceDto ) { try { - const decoded: any = jwt_decode(request?.headers?.authorization); - const userId = - decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - const attendanceToSearch = new AttendanceSearchDto({}); + const Isvalid = await this.validateUserForCohort(attendanceDto.userId,attendanceDto.contextId) + + if(!Isvalid){ + + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Invalid combination of contextId and userId", + }); + } + const attendanceToSearch = new AttendanceSearchDto({}); attendanceToSearch.filters = { attendanceDate: attendanceDto.attendanceDate, @@ -348,7 +354,7 @@ export class PostgresAttendanceService { const attendanceFound: any = await this.searchAttendance( attendanceDto.tenantId, - request, + loginUserId, attendanceToSearch ); @@ -364,15 +370,16 @@ export class PostgresAttendanceService { attendanceFound.data.length > 0 && attendanceFound.data[0].attendanceId != "" && attendanceFound.statusCode === 200 && attendanceFound instanceof SuccessResponse ) { - + attendanceDto.updatedBy = loginUserId return await this.updateAttendance( attendanceFound.data[0].attendanceId, - request, + loginUserId, attendanceDto ); } else { - - return await this.createAttendance(request, attendanceDto); + attendanceDto.createdBy = loginUserId; + attendanceDto.updatedBy = loginUserId; + return await this.createAttendance(loginUserId, attendanceDto); } } catch (e) { return new ErrorResponseTypeOrm({ @@ -393,6 +400,7 @@ export class PostgresAttendanceService { ) { try { + const attendanceRecord = await this.attendanceRepository.findOne({ where: { attendanceId }, }); @@ -418,12 +426,20 @@ export class PostgresAttendanceService { data: updatedAttendanceRecord, }); } catch (error) { - + + if (error.code == '23503') { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please provide valid contextId", + }); + } + else{ return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: error, - }); + }) + } } } @@ -450,12 +466,12 @@ export class PostgresAttendanceService { if (error.code == '23503') { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please provide valid userID", + errorMessage: "Please enter valid UserId and contextId", }); } else { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: 'Internal Server Error', + errorMessage: error, }); } } @@ -581,6 +597,21 @@ export class PostgresAttendanceService { }; } + + + public async validateUserForCohort(userId,cohortId) + { + const attendanceRecord = await this.cohortMembersRepository.findOne({ + where: { userId, cohortId } // Include cohortId in the where clause + }); + if(attendanceRecord){ + return true + }else{ + return false + } + + } + } diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 83e9f095..04df3454 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -85,7 +85,6 @@ export class AttendanceController { }) ) @ApiBody({ type: AttendanceDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", @@ -93,7 +92,7 @@ export class AttendanceController { @UsePipes(ValidationPipe) public async createAttendace( @Headers() headers, - @Req() request: Request, + @Req() request, @Body() attendanceDto: AttendanceDto, @Res() response: Response, @UploadedFile() image @@ -101,7 +100,7 @@ export class AttendanceController { attendanceDto.tenantId = headers["tenantid"]; attendanceDto.image = image?.filename; const result = await this.attendaceAdapter.buildAttenceAdapter().updateAttendanceRecord( - request, + request.user.userId, attendanceDto ); return response.status(result.statusCode).json(result); diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index d7210461..25c70805 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -1,8 +1,53 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { Matches, Validate, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator"; +import { IsOptional, IsUUID, Matches, Validate, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator"; import { isBefore, isSameDay } from "date-fns"; +import { UserDto } from "src/user/dto/user.dto"; +import { AttendanceDto } from "./attendance.dto"; +import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; +import { UUID } from "crypto"; +import { Type } from "class-transformer"; +export class AttendanceFiltersDto { + @ApiPropertyOptional() + @IsOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + fromDate?: string; + + @ApiPropertyOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @IsOptional() + toDate?: string; + + @ApiPropertyOptional() + @IsUUID() + @IsOptional() + cohortId ?:string + + @ApiPropertyOptional() + role ?: string + + @ApiPropertyOptional({ + type: String, + description: "The date of the attendance in format yyyy-mm-dd", + default:"yyyy-mm-dd" + }) + @IsOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + attendanceDate ?:Date + + + @ApiPropertyOptional() + @IsUUID() + @IsOptional() + userId?: string + + // @ApiPropertyOptional() + + + [key: string]: any; // Allows additional dynamic keys +} + @ValidatorConstraint({ name: "validDateRange", async: false }) export class ValidDateRangeConstraint implements ValidatorConstraintInterface { validate(value: any, args: ValidationArguments) { @@ -23,7 +68,6 @@ export class ValidDateRangeConstraint implements ValidatorConstraintInterface { - export class AttendanceSearchDto { @ApiProperty({ type: String, @@ -37,17 +81,14 @@ export class AttendanceSearchDto { }) page: number; - @ApiProperty({ - type: Object, + @ApiPropertyOptional({ + type: AttendanceFiltersDto, description: "Filters", }) - @ApiPropertyOptional() - @Validate(ValidDateRangeConstraint, { message: "Invalid date range." }) - filters: { - fromDate?: string; - toDate?: string; - [key: string]: any; // Allows additional dynamic keys - }; + @ValidateNested({ each: true }) + @Type(() => AttendanceFiltersDto) + // @Validate(ValidDateRangeConstraint, { message: "Invalid date range." }) + filters: AttendanceFiltersDto diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index abdc7911..2366e1a0 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -6,6 +6,7 @@ import { IsNotEmpty, IsString, IsObject } from 'class-validator'; import { User } from 'src/user/entities/user-entity'; import { addHours, format, isAfter, isBefore, isValid } from 'date-fns'; // Import isAfter function from date-fns import { HttpException, HttpStatus } from '@nestjs/common'; +import { Cohort } from 'src/cohort/entities/cohort.entity'; //for student valid enum are[present,absent] //for teacher valid enum are[present,on-leave,half-day] @@ -128,15 +129,27 @@ export class AttendanceDto { @Expose() contextType: string; - @ApiPropertyOptional({ + @ApiProperty({ + type: String, + description: "The contextId of the attendance", + default: "", + }) + @ApiProperty({ type: String, description: "The contextId of the attendance", default: "", }) @IsNotEmpty() + @IsUUID() @Expose() + @IsDefined() contextId: string; + @ManyToOne(() => Cohort, { nullable: true }) // Define the ManyToOne relationship with Cohort entity + @JoinColumn({ name: "contextId", referencedColumnName: "cohortId" }) // Map contextId to cohortId column in Cohort table + cohort: Cohort; + + @Expose() createdAt: string; @@ -152,6 +165,7 @@ export class AttendanceDto { constructor(obj: any) { Object.assign(this, obj); } + } From 2294e8e68a8239201fdb8a473c973295f1e92075 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Thu, 18 Apr 2024 09:58:47 +0530 Subject: [PATCH 236/408] cohort member CRUD APIs --- src/adapters/cohortMembersservicelocator.ts | 20 +- src/adapters/hasura/cohortMembers.adapter.ts | 157 +------- .../postgres/cohortMembers-adapter.ts | 363 ++++++++++++++++++ src/cohortMembers/cohortMembers.controller.ts | 93 +++-- src/cohortMembers/cohortMembers.module.ts | 15 +- src/cohortMembers/cohortMembersadapter.ts | 8 +- 6 files changed, 457 insertions(+), 199 deletions(-) create mode 100644 src/adapters/postgres/cohortMembers-adapter.ts diff --git a/src/adapters/cohortMembersservicelocator.ts b/src/adapters/cohortMembersservicelocator.ts index faefab95..c33a08c0 100644 --- a/src/adapters/cohortMembersservicelocator.ts +++ b/src/adapters/cohortMembersservicelocator.ts @@ -1,9 +1,21 @@ import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-search.dto"; import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; +import { CohortMembersUpdateDto } from "src/cohortMembers/dto/cohortMember-update.dto"; export interface IServicelocatorcohortMembers { - createCohortMembers(request: any, cohortMembersDto: CohortMembersDto); - getCohortMembers(tenantId, cohortMembershipId, request); - searchCohortMembers(tenantid, request: any, cohortMembersSearchDto: CohortMembersSearchDto); - updateCohortMembers(cohortMembershipId: string, request: any, cohortMembersDto: CohortMembersDto); + createCohortMembers( + request: any, + cohortMembersDto: CohortMembersDto, + response: any + ); + getCohortMembers(cohortMemberId: string, fieldvalue); + searchCohortMembers(cohortMembersSearchDto: CohortMembersSearchDto); + updateCohortMembers( + cohortMembershipId: string, + request: any, + cohortMemberUpdateDto: CohortMembersUpdateDto, + + response: any + ); + deleteCohortMemberById(tenantid, cohortMembershipId, response, request); } diff --git a/src/adapters/hasura/cohortMembers.adapter.ts b/src/adapters/hasura/cohortMembers.adapter.ts index 074c5865..15a37f73 100644 --- a/src/adapters/hasura/cohortMembers.adapter.ts +++ b/src/adapters/hasura/cohortMembers.adapter.ts @@ -17,7 +17,7 @@ export class HasuraCohortMembersService request: any, cohortMembers: CohortMembersDto ) { - try{ + try { var axios = require("axios"); let query = ""; Object.keys(cohortMembers).forEach((e) => { @@ -65,156 +65,7 @@ export class HasuraCohortMembersService data: result, }); } - }catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } - } - - public async getCohortMembers( - tenantId: string, - cohortMembershipId: any, - request: any - ) { - var axios = require("axios"); - - var data = { - query: `query GetCohortMembers($cohortMembershipId:uuid!, $tenantId:uuid!) { - CohortMembers( - where:{ - tenantId:{ - _eq:$tenantId - } - cohortMembershipId:{ - _eq:$cohortMembershipId - }, - } - ){ - tenantId - cohortMembershipId - cohortId - userId - role - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - cohortMembershipId: cohortMembershipId, - tenantId: tenantId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response?.data?.data?.CohortMembers; - const cohortMembersResponse = await this.mappedResponse(result); - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: cohortMembersResponse[0], - }); - } - } - - public async searchCohortMembers( - tenantId: string, - request: any, - cohortMembersSearchDto: CohortMembersSearchDto - ) { - try{ - var axios = require("axios"); - - let offset = 0; - if (cohortMembersSearchDto.page > 1) { - offset = - parseInt(cohortMembersSearchDto.limit) * - (cohortMembersSearchDto.page - 1); - } - - let temp_filters = cohortMembersSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - - Object.keys(cohortMembersSearchDto.filters).forEach((item) => { - Object.keys(cohortMembersSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchCohortMembers($filters:CohortMembers_bool_exp,$limit:Int, $offset:Int) { - CohortMembers(where:$filters, limit: $limit, offset: $offset,) { - tenantId - cohortMembershipId - cohortId - userId - role - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(cohortMembersSearchDto.limit), - offset: offset, - filters: cohortMembersSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response.data.data.CohortMembers; - const cohortMembersResponse = await this.mappedResponse(result); - const count = cohortMembersResponse.length; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - totalCount: count, - data: cohortMembersResponse, - }); - } - }catch (e) { + } catch (e) { console.error(e); return new ErrorResponse({ errorCode: "400", @@ -223,6 +74,8 @@ export class HasuraCohortMembersService } } + public async searchCohortMembers(cohortMembersSearchDto) {} + public async getCohortMembers(cohortMemberId, fieldvalue) {} public async updateCohortMembers( cohortMembershipId: string, request: any, @@ -308,4 +161,6 @@ export class HasuraCohortMembersService return cohortMembersResponse; } + + public async deleteCohortMemberById() {} } diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts new file mode 100644 index 00000000..0a73cf4c --- /dev/null +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -0,0 +1,363 @@ +import { Injectable } from "@nestjs/common"; +import { HttpService } from "@nestjs/axios"; +import { SuccessResponse } from "src/success-response"; +import { ErrorResponse } from "src/error-response"; +const resolvePath = require("object-resolve-path"); +import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; +import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-search.dto"; +import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; +import { InjectRepository } from "@nestjs/typeorm"; +import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; +import { CohortDto } from "src/cohort/dto/cohort.dto"; +import APIResponse from "src/utils/response"; +import { HttpStatus } from "@nestjs/common"; +import response from "src/utils/response"; +import { User } from "src/user/entities/user-entity"; +import { CohortMembersUpdateDto } from "src/cohortMembers/dto/cohortMember-update.dto"; +import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; +import { Fields } from "src/fields/entities/fields.entity"; + +@Injectable() +export class PostgresCohortMembersService { + constructor( + @InjectRepository(CohortMembers) + private cohortMembersRepository: Repository, + @InjectRepository(Fields) + private fieldsRepository: Repository, + @InjectRepository(User) + private usersRepository: Repository + ) {} + + async getCohortMembers( + userId: any, + + fieldvalue: any + ) { + try { + if (fieldvalue === "false") { + const result = { + userData: {}, + }; + + let customFieldsArray = []; + + const [userDetails] = await Promise.all([this.findUserDetails(userId)]); + result.userData = userDetails; + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: result, + }); + } else { + const result = { + userData: {}, + }; + + let customFieldsArray = []; + + const [filledValues, userDetails] = await Promise.all([ + this.findFilledValues(userId), + this.findUserDetails(userId), + ]); + + const customFields = await this.findCustomFields(userDetails.role); + + result.userData = userDetails; + const filledValuesMap = new Map( + filledValues.map((item) => [item.fieldId, item.value]) + ); + for (let data of customFields) { + const fieldValue = filledValuesMap.get(data.fieldId); + const customField = { + fieldId: data.fieldId, + label: data.label, + value: fieldValue || "", + options: data?.fieldParams?.["options"] || {}, + type: data.type || "", + }; + customFieldsArray.push(customField); + } + result.userData["customFields"] = customFieldsArray; + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: result, + }); + } + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async findFilledValues(userId: string) { + let query = `SELECT U."userId",F."fieldId",F."value" FROM public."Users" U + LEFT JOIN public."FieldValues" F + ON U."userId" = F."itemId" where U."userId" =$1`; + let result = await this.usersRepository.query(query, [userId]); + return result; + } + + async findUserDetails(userId, username?: any) { + let whereClause: any = { userId: userId }; + if (username && userId === null) { + delete whereClause.userId; + whereClause.username = username; + } + let userDetails = await this.usersRepository.findOne({ + where: whereClause, + }); + return userDetails; + } + + async findCustomFields(role) { + let customFields = await this.fieldsRepository.find({ + where: { + context: "USERS", + contextType: role.toUpperCase(), + }, + }); + return customFields; + } + + async findUsertDetails(userId: string) { + let whereClause: any = { userId: userId }; + let userDetails = await this.usersRepository.findOne({ + where: whereClause, + }); + return userDetails; + } + async searchFindCustomFields() { + let customFields = await this.fieldsRepository.find({ + where: { + context: "COHORT", + contextType: "COHORT", + }, + }); + return customFields; + } + + public async searchCohortMembers( + cohortMembersSearchDto: CohortMembersSearchDto + ) { + try { + let { limit, page, filters } = cohortMembersSearchDto; + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + if (limit.trim() === "") { + limit = "0"; + } + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + + const [userData] = await this.cohortMembersRepository.findAndCount({ + where: whereClause, + skip: offset, + take: parseInt(limit), + }); + let results = { + userDetails: [], + }; + + if (whereClause["cohortId"]) { + let req = 1; + let cohortDetails = await this.getUsersDetailsByCohortId( + whereClause["cohortId"], + req + ); + results.userDetails.push(cohortDetails); + } + + if (whereClause["userId"]) { + let fieldvalue = 1; + + let cohortDetails = await this.getCohortMembers( + whereClause["userId"], + fieldvalue + ); + results.userDetails.push(cohortDetails); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: results, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async getUsersDetailsByCohortId(cohortId: any, response: any) { + let apiId = "api.users.getAllUsersDetails"; + try { + let getUserDetails = await this.findUserName(cohortId); + + let result = { + userDetails: [], + }; + + for (let data of getUserDetails) { + let userDetails = { + userId: data.userId, + userName: data.userName, + name: data.name, + role: data.role, + district: data.district, + state: data.state, + mobile: data.mobile, + customField: [], + }; + const fieldValues = await this.getFieldandFieldValues(data.userId); + + userDetails.customField.push(fieldValues); + + result.userDetails.push(userDetails); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: result, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + async findUserName(cohortId: string) { + let query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + LEFT JOIN public."Users" U + ON CM."userId" = U."userId" + where CM."cohortId" =$1 `; + + let result = await this.usersRepository.query(query, [cohortId]); + + return result; + } + + async getFieldandFieldValues(userId: string) { + let query = `SELECT Fv."fieldId",F."label" AS FieldName,Fv."value" as FieldValues + FROM public."FieldValues" Fv + LEFT JOIN public."Fields" F + ON F."fieldId" = Fv."fieldId" + where Fv."itemId" =$1 `; + let result = await this.usersRepository.query(query, [userId]); + return result; + } + + public async createCohortMembers( + request: any, + cohortMembers: CohortMembersDto, + response: any + ) { + const apiId = "api.cohortMember.createCohortMembers"; + + try { + // Create a new CohortMembers entity and populate it with cohortMembers data + const savedCohortMember = await this.cohortMembersRepository.save( + cohortMembers + ); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Cohort Member created successfully.", + data: savedCohortMember, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async updateCohortMembers( + cohortMembershipId: string, + request: any, + cohortMembersUpdateDto: CohortMembersUpdateDto, + response: any + ) { + const apiId = "api.cohortMember.updateCohortMembers"; + + try { + const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ + where: { cohortMembershipId: cohortMembershipId }, + }); + + if (!cohortMemberToUpdate) { + throw new Error("Cohort member not found"); + } + Object.assign(cohortMemberToUpdate, cohortMembersUpdateDto); + + const updatedCohortMember = await this.cohortMembersRepository.save( + cohortMemberToUpdate + ); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Cohort Member Updated successfully.", + data: updatedCohortMember, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + + public async deleteCohortMemberById( + tenantId: string, + cohortMembershipId: any, + response: any, + request: any + ) { + const apiId = "api.cohortMember.deleteCohortMemberById"; + + try { + const cohortMember = await this.cohortMembersRepository.find({ + where: { + tenantId: tenantId, + cohortMembershipId: cohortMembershipId, + }, + }); + + if (!cohortMember || cohortMember.length === 0) { + return response.status(HttpStatus.NOT_FOUND).send({ + error: "Cohort member not found", + }); + } + + const result = await this.cohortMembersRepository.delete( + cohortMembershipId + ); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Cohort Member deleted Successfully.", + data: result, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } +} diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index bf9e65d6..f2f09a66 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -5,6 +5,8 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiHeader, + ApiOkResponse, + ApiQuery, } from "@nestjs/swagger"; import { Controller, @@ -21,31 +23,39 @@ import { Headers, Res, UseGuards, + UsePipes, + ValidationPipe, + Query, } from "@nestjs/common"; import { CohortMembersSearchDto } from "./dto/cohortMembers-search.dto"; import { Request } from "@nestjs/common"; import { CohortMembersDto } from "./dto/cohortMembers.dto"; import { CohortMembersAdapter } from "./cohortMembersadapter"; import { CohortMembersService } from "./cohortMember.service"; -import { Response } from "@nestjs/common"; +// import { Response } from "@nestjs/common"; import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { Response } from "express"; @ApiTags("Cohort Members") @Controller("cohortmembers") @UseGuards(JwtAuthGuard) export class CohortMembersController { - constructor(private readonly cohortMembersService: CohortMembersService) {} + constructor( + private readonly cohortMembersService: CohortMembersService, + private readonly cohortMemberAdapter: CohortMembersAdapter + ) {} //create cohort members @Post() + @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members has been created successfully.", }) @ApiBody({ type: CohortMembersDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -61,38 +71,39 @@ export class CohortMembersController { }; Object.assign(cohortMembersDto, payload); - return this.cohortMembersService.createCohortMembers( - request, - cohortMembersDto, - response - ); + const result = await this.cohortMemberAdapter + .buildCohortMembersAdapter() + .createCohortMembers(request, cohortMembersDto, response); + return response.status(result.statusCode).json(result); } //get cohort members - @Get("/:id") + @Get("/:userId") @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members detail" }) @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @ApiHeader({ - name: "tenantid", + @SerializeOptions({ strategy: "excludeAll" }) + @ApiHeader({ name: "tenantid" }) + @ApiQuery({ + name: "fieldvalue", + description: "The field Value (optional)", + required: false, }) public async getCohortMembers( @Headers() headers, - @Param("id") cohortMembersId: string, + @Param("userId") userId: string, @Req() request: Request, - @Res() response: Response + @Res() response: Response, + @Query("fieldvalue") fieldvalue: string | null = null ) { let tenantid = headers["tenantid"]; - return this.cohortMembersService.getCohortMembers( - tenantid, - cohortMembersId, - response, - request - ); + + const result = await this.cohortMemberAdapter + .buildCohortMembersAdapter() + .getCohortMembers(userId, fieldvalue); + + return response.status(result.statusCode).json(result); } search; @@ -115,12 +126,11 @@ export class CohortMembersController { @Body() cohortMembersSearchDto: CohortMembersSearchDto ) { let tenantid = headers["tenantid"]; - return this.cohortMembersService.searchCohortMembers( - tenantid, - request, - cohortMembersSearchDto, - response - ); + + const result = await this.cohortMemberAdapter + .buildCohortMembersAdapter() + .searchCohortMembers(cohortMembersSearchDto); + return response.status(result.statusCode).json(result); } //update @@ -131,19 +141,22 @@ export class CohortMembersController { }) @ApiBody({ type: CohortMembersUpdateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) + // @UseInterceptors(ClassSerializerInterceptor) public async updateCohortMembers( @Param("id") cohortMembersId: string, @Req() request: Request, @Body() cohortMemberUpdateDto: CohortMembersUpdateDto, @Res() response: Response ) { - return this.cohortMembersService.updateCohortMembers( - cohortMembersId, - request, - cohortMemberUpdateDto, - response - ); + const result = await this.cohortMemberAdapter + .buildCohortMembersAdapter() + .updateCohortMembers( + cohortMembersId, + request, + cohortMemberUpdateDto, + response + ); + return response.status(result.statusCode).json(result); } //delete @@ -166,11 +179,9 @@ export class CohortMembersController { ) { let tenantid = headers["tenantid"]; - return this.cohortMembersService.deleteCohortMemberById( - tenantid, - cohortMembershipId, - response, - request - ); + const result = await this.cohortMemberAdapter + .buildCohortMembersAdapter() + .deleteCohortMemberById(tenantid, cohortMembershipId, response, request); + return response.status(result.statusCode).json(result); } } diff --git a/src/cohortMembers/cohortMembers.module.ts b/src/cohortMembers/cohortMembers.module.ts index 191c7389..a4d9e81d 100644 --- a/src/cohortMembers/cohortMembers.module.ts +++ b/src/cohortMembers/cohortMembers.module.ts @@ -6,14 +6,25 @@ import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { TypeOrmModule } from "@nestjs/typeorm"; import { CohortMembers } from "./entities/cohort-member.entity"; import { CohortMembersService } from "./cohortMember.service"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; +import { PostgresCohortMembersService } from "src/adapters/postgres/cohortMembers-adapter"; +import { HasuraCohortMembersService } from "src/adapters/hasura/cohortMembers.adapter"; +import { Fields } from "src/fields/entities/fields.entity"; +import { User } from "src/user/entities/user-entity"; @Module({ imports: [ - TypeOrmModule.forFeature([CohortMembers]), + TypeOrmModule.forFeature([CohortMembers, Fields, User]), HttpModule, HasuraModule, + PostgresModule, ], controllers: [CohortMembersController], - providers: [CohortMembersAdapter, CohortMembersService], + providers: [ + CohortMembersAdapter, + CohortMembersService, + PostgresCohortMembersService, + HasuraCohortMembersService, + ], }) export class CohortMembersModule {} diff --git a/src/cohortMembers/cohortMembersadapter.ts b/src/cohortMembers/cohortMembersadapter.ts index 6d4d96ae..8748ba74 100644 --- a/src/cohortMembers/cohortMembersadapter.ts +++ b/src/cohortMembers/cohortMembersadapter.ts @@ -1,10 +1,14 @@ import { Injectable } from "@nestjs/common"; import { IServicelocatorcohortMembers } from "src/adapters/cohortMembersservicelocator"; import { HasuraCohortMembersService } from "src/adapters/hasura/cohortMembers.adapter"; +import { PostgresCohortMembersService } from "src/adapters/postgres/cohortMembers-adapter"; @Injectable() export class CohortMembersAdapter { - constructor(private hasuraProvider: HasuraCohortMembersService) {} + constructor( + private hasuraProvider: HasuraCohortMembersService, + private postgresProvider: PostgresCohortMembersService + ) {} buildCohortMembersAdapter(): IServicelocatorcohortMembers { let adapter: IServicelocatorcohortMembers; @@ -12,6 +16,8 @@ export class CohortMembersAdapter { case "hasura": adapter = this.hasuraProvider; break; + case "postgres": + adapter = this.postgresProvider; } return adapter; } From 08d4224b2c2726e0fb964e0855edf2302b483487 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Thu, 18 Apr 2024 10:45:18 +0530 Subject: [PATCH 237/408] Cohort Member:create & update API change --- src/adapters/cohortMembersservicelocator.ts | 4 ++-- src/adapters/postgres/cohortMembers-adapter.ts | 8 ++++++-- src/cohortMembers/cohortMembers.controller.ts | 11 +++++++---- src/cohortMembers/dto/cohortMembers.dto.ts | 6 +++--- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/adapters/cohortMembersservicelocator.ts b/src/adapters/cohortMembersservicelocator.ts index c33a08c0..d81c3b7d 100644 --- a/src/adapters/cohortMembersservicelocator.ts +++ b/src/adapters/cohortMembersservicelocator.ts @@ -4,7 +4,7 @@ import { CohortMembersUpdateDto } from "src/cohortMembers/dto/cohortMember-updat export interface IServicelocatorcohortMembers { createCohortMembers( - request: any, + loginUser: any, cohortMembersDto: CohortMembersDto, response: any ); @@ -12,7 +12,7 @@ export interface IServicelocatorcohortMembers { searchCohortMembers(cohortMembersSearchDto: CohortMembersSearchDto); updateCohortMembers( cohortMembershipId: string, - request: any, + loginUser: any, cohortMemberUpdateDto: CohortMembersUpdateDto, response: any diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index 0a73cf4c..8a2c91f3 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -262,13 +262,15 @@ export class PostgresCohortMembersService { } public async createCohortMembers( - request: any, + loginUser: any, cohortMembers: CohortMembersDto, response: any ) { const apiId = "api.cohortMember.createCohortMembers"; try { + cohortMembers.createdBy = loginUser; + cohortMembers.updatedBy = loginUser; // Create a new CohortMembers entity and populate it with cohortMembers data const savedCohortMember = await this.cohortMembersRepository.save( cohortMembers @@ -289,13 +291,15 @@ export class PostgresCohortMembersService { public async updateCohortMembers( cohortMembershipId: string, - request: any, + loginUser: any, cohortMembersUpdateDto: CohortMembersUpdateDto, response: any ) { const apiId = "api.cohortMember.updateCohortMembers"; try { + cohortMembersUpdateDto.updatedBy = loginUser; + const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ where: { cohortMembershipId: cohortMembershipId }, }); diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index f2f09a66..f5018a04 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -61,10 +61,11 @@ export class CohortMembersController { }) public async createCohortMembers( @Headers() headers, - @Req() request: Request, + @Req() request, @Body() cohortMembersDto: CohortMembersDto, @Res() response: Response ) { + const loginUser = request.user.userId; let tenantid = headers["tenantid"]; const payload = { tenantId: tenantid, @@ -73,7 +74,7 @@ export class CohortMembersController { const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() - .createCohortMembers(request, cohortMembersDto, response); + .createCohortMembers(loginUser, cohortMembersDto, response); return response.status(result.statusCode).json(result); } @@ -144,15 +145,17 @@ export class CohortMembersController { // @UseInterceptors(ClassSerializerInterceptor) public async updateCohortMembers( @Param("id") cohortMembersId: string, - @Req() request: Request, + @Req() request, @Body() cohortMemberUpdateDto: CohortMembersUpdateDto, @Res() response: Response ) { + const loginUser = request.user.userId; + const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() .updateCohortMembers( cohortMembersId, - request, + loginUser, cohortMemberUpdateDto, response ); diff --git a/src/cohortMembers/dto/cohortMembers.dto.ts b/src/cohortMembers/dto/cohortMembers.dto.ts index c4b8d371..266e7f92 100644 --- a/src/cohortMembers/dto/cohortMembers.dto.ts +++ b/src/cohortMembers/dto/cohortMembers.dto.ts @@ -1,5 +1,5 @@ import { Exclude, Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class CohortMembersDto { //generated fields @@ -40,7 +40,7 @@ export class CohortMembersDto { role: string; //createdBy - @ApiProperty({ + @ApiPropertyOptional({ type: String, description: "The createdBy of the cohort members", default: "", @@ -49,7 +49,7 @@ export class CohortMembersDto { createdBy: string; //updatedBy - @ApiProperty({ + @ApiPropertyOptional({ type: String, description: "The updatedBy of the cohort members", default: "", From 056a4808c55f5dd2b61478050ace0af1feebde36 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 18 Apr 2024 14:26:24 +0530 Subject: [PATCH 238/408] Fix[resolved code rabbit comments] --- src/adapters/postgres/attendance-adapter.ts | 92 +++++++++++---------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 43ba2f42..5e36b86e 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -38,76 +38,82 @@ export class PostgresAttendanceService { */ async searchAttendance(tenantId: string, request: any, attendanceSearchDto: AttendanceSearchDto) { - try { - let { limit, page, filters } = attendanceSearchDto; if (!limit) { limit = '0'; } - + let offset = 0; if (page > 1) { offset = parseInt(limit) * (page - 1); } - + const UserKeys = this.userRepository.metadata.columns.map((column) => column.propertyName); const AttendaceKeys = this.attendanceRepository.metadata.columns.map((column) => column.propertyName); const CohortMembersKeys = this.cohortMembersRepository.metadata.columns.map((column) => column.propertyName); - - let whereClause = `u."tenantId" = '${tenantId}'`; // Default WHERE clause for filtering by tenantId - let attendanceList = '' + + let whereClause = `u."tenantId" = $1`; // Default WHERE clause for filtering by tenantId + let queryParams = [tenantId]; // Parameters for the query + let attendanceList = ''; if (filters && Object.keys(filters).length > 0) { + let index = 2; // Starting index for additional parameters for (const [key, value] of Object.entries(filters)) { if (UserKeys.includes(key)) { - whereClause += ` AND u."${key}" = '${value}'`; + whereClause += ` AND u."${key}" = $${index}`; + queryParams.push(value); } else if (AttendaceKeys.includes(key)) { - if(key==="attendanceDate"){ - attendanceList = ` AND (a."attendanceDate" = '${value}' OR a."attendanceDate" IS NULL)` - continue + if (key === "attendanceDate") { + attendanceList = ` AND (a."attendanceDate" = $${index} OR a."attendanceDate" IS NULL)`; } - whereClause += ` AND a."${key}" = '${value}'`; + whereClause += ` AND a."${key}" = $${index}`; + queryParams.push(value); } else if (CohortMembersKeys.includes(key)) { - whereClause += ` AND cm."${key}" = '${value}'`; - } else if(filters.fromDate && filters.toDate ){ - whereClause += ` AND a."attendanceDate" BETWEEN '${filters.fromDate}' AND '${filters.toDate}'`; - } - else{ + whereClause += ` AND cm."${key}" = $${index}`; + queryParams.push(value); + } else if (filters.fromDate && filters.toDate) { + whereClause += ` AND a."attendanceDate" BETWEEN $${index} AND $${index + 1}`; + queryParams.push(filters.fromDate); + queryParams.push(filters.toDate); + index += 1; // Increment index for toDate parameter + } else { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, errorMessage: `${key} Invalid key`, - }); - -} - }; + }); + } + index += 1; // Increment index for next parameter + } } - - - const query =`SELECT - u.*, - cm.*, - a.* - FROM - "Users" u - INNER JOIN - "CohortMembers" cm ON cm."userId" = u."userId" - LEFT JOIN - "Attendance" a ON a."userId" = cm."userId" ${attendanceList} - where - ${whereClause} - ` - const results = await this.attendanceRepository.query(query); - - const mappedResponse = await this.mappedResponse(results); - - + + const query = ` + SELECT u.*, cm.*, a.* + FROM "Users" u + INNER JOIN "CohortMembers" cm ON cm."userId" = u."userId" + LEFT JOIN "Attendance" a ON a."userId" = cm."userId" ${attendanceList} + WHERE ${whereClause}; + `; + const results = await this.attendanceRepository.query(query, queryParams); + if(!results.length){ + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'No data Found For Entered Filter', + }); + } + const mappedResponse = await this.mappedResponse(results); + return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', - // totalCount, data: mappedResponse, }); } catch (error) { + if (error.code=== "22P02"){ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Invalid value Entered For ${error.routine}`, + }) + } return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: error, @@ -256,7 +262,7 @@ export class PostgresAttendanceService { const attendanceResponse = result.map((item: any) => { const dateObject = new Date(item.attendanceDate); - const formattedDate = moment(dateObject).format('YYYY-MM-DD'); + const formattedDate = format(dateObject, 'yyyy-MM-dd'); const attendanceMapping = { tenantId: item?.tenantId ? `${item.tenantId}` : "", attendanceId: item?.attendanceId ? `${item.attendanceId}` : "", From 3a6197ead5569e0ed17208a50d07a7bd0e8b8dc9 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 18 Apr 2024 14:30:28 +0530 Subject: [PATCH 239/408] Fix[import changes] --- src/adapters/postgres/attendance-adapter.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 5e36b86e..00dcbbb5 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -1,17 +1,13 @@ import { User } from '../../user/entities/user-entity'; -import { isAfter } from 'date-fns'; import { ConfigService } from '@nestjs/config'; -import { Client } from 'pg'; -import jwt_decode from "jwt-decode"; import { InjectRepository } from "@nestjs/typeorm"; import { AttendanceEntity } from "../../attendance/entities/attendance.entity"; -import { EntityMetadata, QueryRunner, Repository } from "typeorm"; -import { BadRequestException, HttpException, HttpStatus, Injectable } from "@nestjs/common"; +import { Repository,Between } from "typeorm"; +import { HttpStatus, Injectable } from "@nestjs/common"; import { AttendanceSearchDto } from "../../attendance/dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; import { AttendanceDto, BulkAttendanceDTO } from '../../attendance/dto/attendance.dto'; import { AttendanceDateDto } from '../../attendance/dto/attendance-date.dto'; -import { Between } from 'typeorm'; import { AttendanceStatsDto } from '../../attendance/dto/attendance-stats.dto'; import { format } from 'date-fns' import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; From ab64a0d7ff26ffe6c79660e81475787fe3152b9d Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 18 Apr 2024 14:57:55 +0530 Subject: [PATCH 240/408] Fix[fix for same format for date parsing] --- src/adapters/postgres/attendance-adapter.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 00dcbbb5..a7f1d7b0 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -9,7 +9,6 @@ import { SuccessResponse } from 'src/success-response'; import { AttendanceDto, BulkAttendanceDTO } from '../../attendance/dto/attendance.dto'; import { AttendanceDateDto } from '../../attendance/dto/attendance-date.dto'; import { AttendanceStatsDto } from '../../attendance/dto/attendance-stats.dto'; -import { format } from 'date-fns' import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; const moment = require('moment'); @@ -258,8 +257,7 @@ export class PostgresAttendanceService { const attendanceResponse = result.map((item: any) => { const dateObject = new Date(item.attendanceDate); - const formattedDate = format(dateObject, 'yyyy-MM-dd'); - const attendanceMapping = { + const formattedDate = moment(dateObject).format('YYYY-MM-DD'); const attendanceMapping = { tenantId: item?.tenantId ? `${item.tenantId}` : "", attendanceId: item?.attendanceId ? `${item.attendanceId}` : "", userId: item?.userId ? `${item.userId}` : "", From eb3a4fd7a28e1ffd76a9d9a4ffe2e7b6fa6c8942 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 18 Apr 2024 16:39:57 +0530 Subject: [PATCH 241/408] Fix[swagger response fix] --- src/attendance/attendance.controller.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 04df3454..f7d3b912 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -7,6 +7,8 @@ import { ApiBasicAuth, ApiConsumes, ApiHeader, + ApiBadRequestResponse, + ApiInternalServerErrorResponse, } from "@nestjs/swagger"; import { Controller, @@ -146,9 +148,10 @@ export class AttendanceController { @Post("/search") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Attendance list." }) + @ApiOkResponse({ description: "Attendance List" }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @ApiBody({ type: AttendanceSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) // @UseInterceptors(ClassSerializerInterceptor) @UsePipes(ValidationPipe) @SerializeOptions({ From b1deffb8052bf25967bdda28c2b89f30d00b962b Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 18 Apr 2024 21:31:22 +0530 Subject: [PATCH 242/408] add --- src/adapters/cohortservicelocator.ts | 2 +- src/adapters/hasura/cohort.adapter.ts | 2 +- src/adapters/postgres/cohort-adapter.ts | 321 +++++++++++++++--------- src/cohort/cohort.controller.ts | 7 +- src/cohort/dto/cohort-create.dto.ts | 21 +- src/cohort/entities/cohort.entity.ts | 19 +- 6 files changed, 226 insertions(+), 146 deletions(-) diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index a756a9ca..8c29b49b 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -7,5 +7,5 @@ export interface IServicelocatorcohort { searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto); updateCohort(cohortId: string, request: any, cohortDto: CohortCreateDto); getCohortsDetails(cohortId: string); - updateCohortStatus(cohortId: string); + updateCohortStatus(cohortId: string, request: any); } diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index bf1e3a0c..eb0befb1 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -261,7 +261,7 @@ export class HasuraCohortService implements IServicelocatorcohort { } public async searchCohort(tenantId: string,request: any,cohortSearchDto: CohortSearchDto) {} - public async updateCohortStatus(cohortId: string) {} + public async updateCohortStatus(cohortId: string, request: any) {} public async getCohortsDetails(cohortId: string) {} public async updateCohort( cohortId: string, diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index c6c0be91..7d5e25e0 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -22,6 +22,9 @@ import { FieldValues } from "../../fields/entities/fields-values.entity"; import { v4 as uuidv4 } from 'uuid'; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; +import { isUUID } from "class-validator"; + + @Injectable() export class PostgresCohortService { @@ -76,38 +79,21 @@ export class PostgresCohortService { } public async getCohortsDetails(cohortId: string) { - let apiId = "api.concept.getCohortDetails"; try { - - const result = { - cohortData: { - } - }; - - let customFieldsArray = []; - - const [filledValues, cohortDetails, customFields] = await Promise.all([ - this.findFilledValues(cohortId), - this.findCohortDetails(cohortId), - this.findCustomFields() - ]); - - - result.cohortData = cohortDetails; - const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); - for (let data of customFields) { - const fieldValue = filledValuesMap.get(data.fieldId); - const customField = { - fieldId: data.fieldId, - label: data.label, - value: fieldValue || '', - options: data?.fieldParams?.['options'] || {}, - type: data.type || '' - }; - customFieldsArray.push(customField); + if (!isUUID(cohortId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid (UUID)", + }); } - result.cohortData['customFields'] = customFieldsArray; - + const result = await this.getCohortDataWithCustomfield(cohortId); + console.log(result); + // if(!result.length){ + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.NOT_FOUND, + // errorMessage: "CohortId not found", + // }); + // } return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", @@ -122,6 +108,39 @@ export class PostgresCohortService { } } + public async getCohortDataWithCustomfield(cohortId: string) { + const result = { + cohortData: { + } + }; + + let customFieldsArray = []; + + const [filledValues, cohortDetails, customFields] = await Promise.all([ + this.findFilledValues(cohortId), + this.findCohortDetails(cohortId), + this.findCustomFields() + ]); + + + result.cohortData = cohortDetails; + const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); + for (let data of customFields) { + const fieldValue = filledValuesMap.get(data.fieldId); + const customField = { + fieldId: data.fieldId, + label: data.label, + value: fieldValue || '', + options: data?.fieldParams?.['options'] || {}, + type: data.type || '' + }; + customFieldsArray.push(customField); + } + result.cohortData['customFields'] = customFieldsArray; + return result + } + + async findFilledValues(cohortId: string) { let query = `SELECT C."cohortId",F."fieldId",F."value" FROM public."Cohort" C LEFT JOIN public."FieldValues" F @@ -137,7 +156,7 @@ export class PostgresCohortService { }) return cohortDetails; } - + async findCustomFields() { let customFields = await this.fieldsRepository.find({ where: { @@ -171,20 +190,15 @@ export class PostgresCohortService { ]); return result; } + public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try { - const cohortData: any = {}; - cohortCreateDto.cohortId = uuidv4(); - Object.keys(cohortCreateDto).forEach((e) => { - if (cohortCreateDto[e] && cohortCreateDto[e] != "" && e != "fieldValues") { - if (Array.isArray(cohortCreateDto[e])) { - cohortData[e] = JSON.stringify(cohortCreateDto[e]); - } else { - cohortData[e] = cohortCreateDto[e]; - } - } - }); - const response = await this.cohortRepository.save(cohortData); + // console.log(request.user.userId) + // cohortCreateDto.createdBy =uuidv4(request.user.userId); + console.log(cohortCreateDto); + + const response = await this.cohortRepository.save(cohortCreateDto); + let cohortId = response?.cohortId; let field_value_array = cohortCreateDto.fieldValues.split("|"); @@ -229,69 +243,83 @@ export class PostgresCohortService { cohortUpdateDto: CohortCreateDto ) { try { - - const cohortUpdateData: any = {}; - - Object.keys(cohortUpdateDto).forEach((e) => { - if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" - ) { - if (Array.isArray(cohortUpdateDto[e])) { - cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); - } else { - cohortUpdateData[e] = cohortUpdateDto[e]; + if (!isUUID(cohortId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid (UUID)", + }); + } + const checkData = await this.checkAuthAndValidData(cohortId); + if (checkData) { + + // const cohortUpdateData: any = {}; + + // Object.keys(cohortUpdateDto).forEach((e) => { + // if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" + // ) { + // if (Array.isArray(cohortUpdateDto[e])) { + // cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + // } else { + // cohortUpdateData[e] = cohortUpdateDto[e]; + // } + // } + // }); + cohortUpdateDto.updatedBy = request.user.userId; + const response = await this.cohortRepository.update(cohortId, cohortUpdateDto); + + if (cohortUpdateDto.fieldValues) { + let field_value_array = cohortUpdateDto.fieldValues.split("|"); + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + + let fieldValues = field_value_array[i].split(":"); + let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + try { + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + const rowid = fieldVauesRowId.fieldValuesId; + + let fieldValueDto: FieldValuesDto = { + fieldValuesId: rowid, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.updateFieldValues(rowid, fieldValueDto); + } catch { + let fieldValueDto: FieldValuesDto = { + fieldValuesId: null, + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.createFieldValues(request, fieldValueDto); + } + } } } - }); - const response = await this.cohortRepository.update(cohortId, cohortUpdateData); - - if (cohortUpdateDto.fieldValues) { - let field_value_array = cohortUpdateDto.fieldValues.split("|"); - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - - let fieldValues = field_value_array[i].split(":"); - let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; - try { - const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) - const rowid = fieldVauesRowId.fieldValuesId; - - let fieldValueDto: FieldValuesDto = { - fieldValuesId: rowid, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.updateFieldValues(rowid, fieldValueDto); - } catch { - let fieldValueDto: FieldValuesDto = { - fieldValuesId: null, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.createFieldValues(request, fieldValueDto); - } + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: { + rowCount: response.affected, } - } + }); + }else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User not found", + }); } - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: { - rowCount: response.affected, - } - }); } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, @@ -324,19 +352,43 @@ export class PostgresCohortService { whereClause[key] = value; }); } - const [results, totalCount] = await this.cohortRepository.findAndCount({ - where: whereClause, - skip: offset, - take: parseInt(limit), - }); + let results = { + cohortDetails: [], + }; + + if (whereClause['userId'] || whereClause['cohortId']) { + const [cohortData] = await this.cohortMembersRepository.findAndCount({ + where: whereClause, + skip: offset, + take: parseInt(limit), + }); + if (whereClause['userId']) { + for (let data of cohortData) { + let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); + results.cohortDetails.push(cohortDetails); + } + } else { + let cohortDetails = await this.getCohortDataWithCustomfield(whereClause['cohortId']); + results.cohortDetails.push(cohortDetails); + } + } else { + const [cohortData] = await this.cohortRepository.findAndCount({ + where: whereClause, + skip: offset, + take: parseInt(limit), + }); + for (let data of cohortData) { + let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); + results.cohortDetails.push(cohortDetails); + } + } + - const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', - totalCount, - data: mappedResponse, + data: results, }); } catch (e) { @@ -372,17 +424,35 @@ export class PostgresCohortService { } public async updateCohortStatus( - cohortId: string + cohortId: string, + request: any ) { try { - let query = `UPDATE public."Cohort" - SET "status" = false - WHERE "cohortId" = $1`; - const results = await this.cohortRepository.query(query, [cohortId]); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Cohort Deleted Successfully.", - }); + if (!isUUID(cohortId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid (UUID)", + }); + } + const checkData = await this.checkAuthAndValidData(cohortId); + const updatedBy = request.user.userId; + if (checkData === true) { + let query = `UPDATE public."Cohort" + SET "status" = false, + "updatedBy" = '${updatedBy}' + WHERE "cohortId" = $1`; + + const results = await this.cohortRepository.query(query, [cohortId]); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Cohort Deleted Successfully.", + }); + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User not found", + }); + } } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, @@ -390,4 +460,19 @@ export class PostgresCohortService { }); } } + + public async checkAuthAndValidData(id: any) { + + const existData = await this.cohortRepository.find({ + where: { + cohortId: id + } + }) + if (existData.length !== 0) { + return true; + } else { + return false; + } + + } } diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 5964538d..b6ace54e 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -40,7 +40,7 @@ import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") @Controller("cohort") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) export class CohortController { constructor(private readonly cohortAdapter:CohortAdapter) {} @@ -58,6 +58,7 @@ export class CohortController { fileFilter: imageFileFilter, }) ) + @UsePipes(new ValidationPipe()) @ApiBody({ type: CohortCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ @@ -106,7 +107,6 @@ export class CohortController { @ApiCreatedResponse({ description: "Cohort list." }) @ApiBody({ type: CohortSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", @@ -145,7 +145,6 @@ export class CohortController { ) @ApiBody({ type: CohortCreateDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) public async updateCohort( @Param("id") cohortId: string, @Req() request: Request, @@ -177,7 +176,7 @@ export class CohortController { @Req() request: Request, @Res() response: Response ) { - const result = await this.cohortAdapter.buildCohortAdapter().updateCohortStatus(cohortId); + const result = await this.cohortAdapter.buildCohortAdapter().updateCohortStatus(cohortId,request); return response.status(result.statusCode).json(result); } } diff --git a/src/cohort/dto/cohort-create.dto.ts b/src/cohort/dto/cohort-create.dto.ts index a0ed1ffa..58a9799b 100644 --- a/src/cohort/dto/cohort-create.dto.ts +++ b/src/cohort/dto/cohort-create.dto.ts @@ -10,11 +10,12 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { FieldValuesCreateDto } from "src/fields/dto/field-values-create.dto"; export class CohortCreateDto { - //generated fields - @Expose() - tenantId: string; @Expose() cohortId: string; + + @Expose() + tenantId: string; + @Expose() createdAt: string; @Expose() @@ -81,7 +82,7 @@ export class CohortCreateDto { default: false, }) @Expose() - attendanceCaptureImage: Boolean; + attendanceCaptureImage: boolean; //image @Expose() @@ -98,16 +99,16 @@ export class CohortCreateDto { metadata: string; //createdBy - @Expose() - @ApiProperty({ + @ApiPropertyOptional({ type: String, description: "The cohort is createdBy", default: "", }) + @Expose() createdBy: string; //updatedBy - @ApiProperty({ + @ApiPropertyOptional({ type: String, description: "The cohort is updatedBy", default: "", @@ -116,14 +117,14 @@ export class CohortCreateDto { updatedBy: string; //fieldValues - @ApiProperty({ + @ApiPropertyOptional({ type: String, description: "The fieldValues Object", }) @Expose() fieldValues: string; - constructor(partial: Partial) { - Object.assign(this, partial); + constructor(obj: any) { + Object.assign(this, obj); } } diff --git a/src/cohort/entities/cohort.entity.ts b/src/cohort/entities/cohort.entity.ts index 505561ba..29362080 100644 --- a/src/cohort/entities/cohort.entity.ts +++ b/src/cohort/entities/cohort.entity.ts @@ -5,11 +5,12 @@ import { CreateDateColumn, UpdateDateColumn, ManyToMany, + PrimaryGeneratedColumn, } from "typeorm"; @Entity({ name: "Cohort" }) export class Cohort { - @PrimaryColumn({ type: "uuid" }) + @PrimaryGeneratedColumn('uuid') cohortId: string; @Column({ nullable: true }) @@ -22,7 +23,7 @@ export class Cohort { type: string; @Column({ nullable: true }) - status: string; + status: boolean; @Column({ nullable: true }) image: string; @@ -54,16 +55,10 @@ export class Cohort { }) updatedAt: Date; - @CreateDateColumn({ - type: "timestamp with time zone", - default: () => "CURRENT_TIMESTAMP", - }) - createdBy: Date; + @Column() + createdBy: string; - @UpdateDateColumn({ - type: "timestamp with time zone", - default: () => "CURRENT_TIMESTAMP", - }) - updatedBy: Date; + @Column() + updatedBy: string; } From cdabc93687d567192fac6351d4ec83a05413fdbe Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 18 Apr 2024 21:52:17 +0530 Subject: [PATCH 243/408] filter changes --- src/cohort/dto/cohort-search.dto.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index c265abb4..968cb109 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -1,5 +1,6 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsNumberString } from "class-validator"; +import { CohortDto } from "./cohort.dto"; export class CohortSearchDto { @@ -17,7 +18,7 @@ export class CohortSearchDto { page: number; @ApiProperty({ - type: Object, + type: CohortDto, description: "Filters", }) @ApiPropertyOptional() From a5d2e09d64311d6f74c48b13be0ac0b97987b496 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 19 Apr 2024 10:55:15 +0530 Subject: [PATCH 244/408] Task #217466: removed group addition which was used for old RBAC --- src/common/utils/keycloak.adapter.util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/utils/keycloak.adapter.util.ts b/src/common/utils/keycloak.adapter.util.ts index 030e2804..dca95dfc 100644 --- a/src/common/utils/keycloak.adapter.util.ts +++ b/src/common/utils/keycloak.adapter.util.ts @@ -68,7 +68,7 @@ async function createUserInKeyCloak(query, token) { lastName: lname, enabled: "true", username: query.username, - groups: [getUserGroup(query.role)], + // groups: [getUserGroup(query.role)], credentials: [ { temporary: "false", From 593bd0322a6db3d1278160cc8c1042013a9dc405 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 19 Apr 2024 11:05:19 +0530 Subject: [PATCH 245/408] chore : removed unwanted package --- src/attendance/dto/attendance-search.dto.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index 25c70805..aaa3abff 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -4,7 +4,6 @@ import { isBefore, isSameDay } from "date-fns"; import { UserDto } from "src/user/dto/user.dto"; import { AttendanceDto } from "./attendance.dto"; import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; -import { UUID } from "crypto"; import { Type } from "class-transformer"; From bd83814c05c16ecb5300a280108bbb53a97098f1 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 19 Apr 2024 11:54:38 +0530 Subject: [PATCH 246/408] chore : added missing imports --- src/rbac/assign-privilege/assign-privilege.controller.ts | 2 +- src/rbac/assign-role/assign-role.controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rbac/assign-privilege/assign-privilege.controller.ts b/src/rbac/assign-privilege/assign-privilege.controller.ts index b06f377f..76e60316 100644 --- a/src/rbac/assign-privilege/assign-privilege.controller.ts +++ b/src/rbac/assign-privilege/assign-privilege.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions } from '@nestjs/common'; import { AssignPrivilegeAdapter } from './assign-privilege.apater'; import { CreatePrivilegeRoleDto } from './dto/create-assign-privilege.dto'; -import { Response} from "express"; +import { Response, Request} from "express"; import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger'; diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index d98bf171..a6557dab 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions } from '@nestjs/common'; import { AssignRoleAdapter } from './assign-role.apater'; import { CreateAssignRoleDto } from './dto/create-assign-role.dto'; -import { Response, response } from "express"; +import { Response, Request } from "express"; import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger'; From e9f82f3c6627148e6b30cfb83a4236dce391f245 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 19 Apr 2024 15:31:15 +0530 Subject: [PATCH 247/408] Task #216365: Updated Create User API according to New Keycloak --- src/adapters/postgres/user-adapter.ts | 22 ++++++++---------- src/common/utils/keycloak.adapter.util.ts | 27 ++++++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 9678f7be..273f5745 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -46,7 +46,6 @@ export class PostgresUserService { statusCode: HttpStatus.BAD_REQUEST, message: 'No Data Found For User',}); } - console.log("Hi"); return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', @@ -330,14 +329,12 @@ export class PostgresUserService { // It is considered that if user is not present in keycloak it is not present in database as well try { const decoded: any = jwt_decode(request.headers.authorization); - const userId = decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; let cohortId = userCreateDto.cohortId; delete userCreateDto?.cohortId; - userCreateDto.createdBy = userId - userCreateDto.updatedBy = userId; + userCreateDto.createdBy = decoded?.sub + userCreateDto.updatedBy = decoded?.sub userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); - const userSchema = new UserCreateDto(userCreateDto); let errKeycloak = ""; @@ -364,6 +361,7 @@ export class PostgresUserService { ); userCreateDto.userId = resKeycloak; let result = await this.createUserInDatabase(request, userCreateDto, cohortId); + let field_value_array = userCreateDto.fieldValues?.split("|"); let fieldData = {}; if (result && field_value_array?.length > 0) { @@ -415,15 +413,15 @@ export class PostgresUserService { user.username = userCreateDto?.username user.name = userCreateDto?.name user.role = userCreateDto?.role - user.mobile = Number(userCreateDto?.mobile), - user.tenantId = userCreateDto?.tenantId + user.mobile = Number(userCreateDto?.mobile) || null, + user.tenantId = userCreateDto?.tenantId user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, - user.state = userCreateDto?.state, - user.district = userCreateDto?.district, - user.address = userCreateDto?.address, - user.pincode = userCreateDto?.pincode + user.state = userCreateDto?.state, + user.district = userCreateDto?.district, + user.address = userCreateDto?.address, + user.pincode = userCreateDto?.pincode if (userCreateDto?.dob) { user.dob = new Date(userCreateDto.dob); @@ -449,7 +447,6 @@ export class PostgresUserService { let result = await this.cohortMemberRepository.insert(cohortData); return result;; } catch (error) { - console.log(error); throw new Error(error) } } @@ -509,7 +506,6 @@ export class PostgresUserService { }); } } catch (e) { - console.error(e); return e; } } diff --git a/src/common/utils/keycloak.adapter.util.ts b/src/common/utils/keycloak.adapter.util.ts index dca95dfc..c2dfabfb 100644 --- a/src/common/utils/keycloak.adapter.util.ts +++ b/src/common/utils/keycloak.adapter.util.ts @@ -87,20 +87,25 @@ async function createUserInKeyCloak(query, token) { }, data: data, }; - let userResponse; + // try { + // userResponse = await axios(config); + // } catch (e) { + // console.log(e.response, "Keycloak Creation error"); + // return e; + // } + + // const userString = userResponse.headers.location; + // const index = userString.lastIndexOf("/"); + // const userId = userString.substring(index + 1); + + // return userId; try { - userResponse = await axios(config); - } catch (e) { - console.log(e.response, "Keycloak Creation error"); - return e; + const userResponse = await axios(config); + return userResponse.headers.location.split("/").pop(); + } catch (error) { + return "Error creating user: " + error.response.data.error; } - - const userString = userResponse.headers.location; - const index = userString.lastIndexOf("/"); - const userId = userString.substring(index + 1); - - return userId; } async function checkIfEmailExistsInKeycloak(email, token) { From 10ab2a230010cd93d20966badc021e22e40e9c1b Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 19 Apr 2024 16:14:45 +0530 Subject: [PATCH 248/408] Fix[Seperate API for attendance Report and swagger changes ] --- src/adapters/postgres/attendance-adapter.ts | 241 +++++++++++--------- src/attendance/attendance.controller.ts | 78 +------ src/attendance/dto/attendance-stats.dto.ts | 74 +++--- src/attendance/dto/attendance.dto.ts | 18 +- src/rbac/privilege/privilege.controller.ts | 24 +- 5 files changed, 220 insertions(+), 215 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index a7f1d7b0..003dd85e 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -116,142 +116,163 @@ export class PostgresAttendanceService { } } + async attendanceReport(attendanceStatsDto: AttendanceStatsDto) { - let { contextId, attendanceDate, report, limit, offset, filters } = attendanceStatsDto + let { contextId, limit, offset, filters } = attendanceStatsDto; try { - if (report === true) { - let nameFilter = ''; - let userFilter = ''; - + + let nameFilter = ''; + let userFilter = ''; + let dateFilter = ''; + let queryParams: any[] = [contextId]; + let subqueryParams: any[] = [contextId]; // Initialize query parameters array + let paramIndex = 1; // Initialize parameter index + if (filters && filters.search) { - nameFilter = `AND u."name" ILIKE '%${filters.search.trim()}%'`; + nameFilter = `AND u."name" ILIKE $${++paramIndex}`; // Increment paramIndex + queryParams.push(`%${filters.search.trim()}%`); + subqueryParams.push(`%${filters.search.trim()}%`); } if (filters && filters.userId) { - userFilter = ` AND u."userId"='${filters.userId.trim()}'`; - } + userFilter = ` AND u."userId" = $${++paramIndex}`; // Increment paramIndex + queryParams.push(filters.userId.trim()); + subqueryParams.push(filters.userId.trim()); - let query = ` - SELECT u."userId",u."name", - CASE - WHEN COUNT(*) = 0 THEN NULL - ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*),0) - END AS attendance_percentage - FROM public."CohortMembers" AS cm - INNER JOIN public."Users" AS u ON cm."userId" = u."userId" - LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" - WHERE cm."cohortId" = $1 AND cm."role" = 'student' - ${userFilter} - ${nameFilter} - GROUP BY u."userId" - `; - - if (filters) { - if (filters.nameOrder && filters.nameOrder==="asc" || filters.nameOrder==="desc") { - query += ` ORDER BY "name" ${filters.nameOrder}` - - } - else if (filters.percentageOrder && filters.percentageOrder==="asc" || filters.percentageOrder==="desc") { - query += ` ORDER BY attendance_percentage ${filters.percentageOrder}` - } + } + if (filters && filters.fromDate && filters.toDate) { + dateFilter = `WHERE aa."attendanceDate" >= $${++paramIndex} AND aa."attendanceDate" <= $${++paramIndex}`; + queryParams.push(filters.fromDate); + queryParams.push(filters.toDate); + subqueryParams.push(filters.fromDate); + subqueryParams.push(filters.toDate); + } - } - query += ` - LIMIT $2 - OFFSET $3` - const result = await this.attendanceRepository.query(query, [contextId, limit, offset]); - - if((!filters) || (!filters?.userId)) - { - // We dont need average for single user - let countquery = `SELECT ROUND(AVG(attendance_percentage)) AS average_attendance_percentage - FROM ( - SELECT u."userId", u."name", - CASE - WHEN COUNT(*) = 0 THEN NULL - ELSE ROUND(COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) * 100.0 / COUNT(*)) - END AS attendance_percentage - FROM public."CohortMembers" AS cm - INNER JOIN public."Users" AS u ON cm."userId" = u."userId" - LEFT JOIN public."Attendance" AS aa ON cm."userId" = aa."userId" - WHERE cm."cohortId" = $1 AND cm."role" = 'student' + + let query = ` + SELECT + u."userId", + u."name", + CASE + WHEN aa_stats."total_attendance" = 0 THEN '-' + ELSE ROUND((aa_stats."present_count" * 100.0) / aa_stats."total_attendance", 0)::text + END AS attendance_percentage + FROM + public."Users" AS u + INNER JOIN + public."CohortMembers" AS cm ON cm."userId" = u."userId" + LEFT JOIN + ( + SELECT + aa."userId", + COUNT(*) AS "total_attendance", + COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) AS "present_count" + FROM + public."Attendance" AS aa + ${dateFilter} + GROUP BY + aa."userId" + ) AS aa_stats ON cm."userId" = aa_stats."userId" + WHERE + cm."cohortId" = $1 + AND cm."role" = 'student' + ${nameFilter} ${userFilter} - GROUP BY u."userId" - ) AS subquery; - ` + GROUP BY + u."userId", u."name", aa_stats."total_attendance", aa_stats."present_count" + `; + + if (filters) { + if (filters.nameOrder && (filters.nameOrder === "asc" || filters.nameOrder === "desc")) { + query += ` ORDER BY "name" ${filters.nameOrder}`; + } else if (filters.percentageOrder && (filters.percentageOrder === "asc" || filters.percentageOrder === "desc")) { + query += ` ORDER BY attendance_percentage ${filters.percentageOrder}`; + } + } + query += ` + LIMIT $${++paramIndex} + OFFSET $${++paramIndex}`; + + queryParams.push(limit); + queryParams.push(offset); + + + + const result = await this.attendanceRepository.query(query, queryParams); + + if (!filters || !filters?.userId) { + // We don't need average for single user + const countquery = ` + SELECT ROUND(AVG(attendance_percentage::NUMERIC), 2) AS average_attendance_percentage + FROM ( + SELECT + u."userId", + u."name", + CASE + WHEN aa_stats."total_attendance" = 0 THEN '-' + ELSE ROUND((aa_stats."present_count" * 100.0) / aa_stats."total_attendance", 0)::text + END AS attendance_percentage + FROM + public."Users" AS u + INNER JOIN + public."CohortMembers" AS cm ON cm."userId" = u."userId" + LEFT JOIN + ( + SELECT + aa."userId", + COUNT(*) AS "total_attendance", + COUNT(CASE WHEN aa."attendance" = 'present' THEN 1 END) AS "present_count" + FROM + public."Attendance" AS aa + ${dateFilter} + GROUP BY + aa."userId" + ) AS aa_stats ON cm."userId" = aa_stats."userId" + WHERE + cm."cohortId" = $1 + AND cm."role" = 'student' + ${nameFilter} + ${userFilter} + GROUP BY + u."userId", u."name", aa_stats."total_attendance", aa_stats."present_count" + ) AS subquery`; + - const average=await this.attendanceRepository.query(countquery,[contextId]) - const report = await this.mapResponseforReport(result); + const average = await this.attendanceRepository.query(countquery, subqueryParams); + const report = await this.mapResponseforReport(result); const response = { report, - average:average[0] - } + average: average[0] + }; return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", - data: response, - + data: response }); - } - else - { - const response = await this.mapResponseforReport(result); + } else { + + const response = await this.mapResponseforReport(result); return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", - data: response, - + data: response }); } - - } - else if (report === false) { - if (attendanceDate) { - const query = ` - SELECT * - FROM public."Users" AS u - INNER JOIN public."CohortMembers" AS cm ON cm."userId" = u."userId" AND cm."role"='student' - LEFT JOIN public."Attendance" AS aa ON aa."userId" = cm."userId" AND (aa."attendanceDate" =$1 OR aa."attendanceDate" IS NULL) - where cm."cohortId" = $2 - LIMIT $3 - OFFSET $4 - `; - - - - const result = await this.attendanceRepository.query(query, [attendanceDate, contextId, limit, offset]); - const report = await this.mapAttendanceRecord(result); - - - - - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: report - }); - } - - else { - - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please provide valid attendance date", - }); - - } - } - } - catch (error) { - + + } catch (error) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, + errorMessage: error }); - - } } + + + + + + + public async mappedResponse(result: any) { const attendanceResponse = result.map((item: any) => { diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index f7d3b912..18ed48e8 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -43,7 +43,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("Attendance") @Controller("attendance") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) export class AttendanceController { constructor( private attendaceAdapter: AttendaceAdapter, @@ -72,7 +72,6 @@ export class AttendanceController { // } @Post() - @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Attendance has been created successfully.", @@ -108,42 +107,7 @@ export class AttendanceController { return response.status(result.statusCode).json(result); } - @Put("/:id") - @ApiConsumes("multipart/form-data") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Attendance has been Updated successfully.", - }) - @UseInterceptors( - FileInterceptor("image", { - storage: diskStorage({ - destination: "./uploads", - filename: editFileName, - }), - fileFilter: imageFileFilter, - }) - ) - @ApiBody({ type: AttendanceDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) - public async updateAttendace( - @Param("id") attendanceId: string, - @Req() request: Request, - @Body() attendanceDto: AttendanceDto, - @Res() response: Response, - @UploadedFile() image - ) { - const Imageresponse = { - image: image?.filename, - }; - Object.assign(attendanceDto, response); - const result = this.attendaceAdapter.buildAttenceAdapter().updateAttendance( - attendanceId, - request, - attendanceDto - ); - return response.status(result.statusCode).json(result); - } + @Post("/search") @@ -176,36 +140,15 @@ export class AttendanceController { return response.status(result.statusCode).json(result); } - @Post("/bydate") - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiHeader({ - name: "tenantid", - }) - @UsePipes(ValidationPipe) - public async attendanceFilter( - @Headers() headers, - @Req() request: Request, - @Res() response: Response, - @Body() attendanceDateDto: AttendanceDateDto - ) { - const tenantId = headers["tenantid"]; - const result = await this.attendaceAdapter.buildAttenceAdapter().attendanceByDate( - tenantId, - request, - attendanceDateDto - ); - return response.status(result.statusCode).json(result); - } + @Post("bulkAttendance") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ - description: "Attendance has been created successfully.", - }) + @ApiCreatedResponse({description: "Attendance has been created successfully."}) + @ApiBadRequestResponse({description: "Bad Request",}) + @ApiOkResponse({description: "Attendance updated successfully"}) + @ApiInternalServerErrorResponse({description: "Internal server error"}) @ApiBody({ type: BulkAttendanceDTO }) - @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ name: "tenantid", }) @@ -225,11 +168,12 @@ export class AttendanceController { return response.status(result.statusCode).json(result); } - @Post("/report") + @Post("/average-report") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Attendance list." }) + @ApiOkResponse({ description: "Average attendance Report" }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server error" }) @ApiBody({ type: AttendanceStatsDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) diff --git a/src/attendance/dto/attendance-stats.dto.ts b/src/attendance/dto/attendance-stats.dto.ts index c8b60446..8850fae4 100644 --- a/src/attendance/dto/attendance-stats.dto.ts +++ b/src/attendance/dto/attendance-stats.dto.ts @@ -1,37 +1,70 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { Expose, Transform, Type } from "class-transformer"; -import { IsEnum, IsNotEmpty, IsNumberString, IsOptional, IsString, IsUUID, ValidateNested } from 'class-validator'; - +import { IsEnum, IsNotEmpty, IsNumberString, IsOptional, IsString, IsUUID, Matches, Validate, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; +import { isBefore, isSameDay } from "date-fns"; enum Order { ASC = 'asc', DESC = 'desc', } +@ValidatorConstraint({ name: 'isNotAfterFromDate', async: false }) +export class IsFromDateBeforeToDateConstraint implements ValidatorConstraintInterface { + validate(fromDate: Date, args: ValidationArguments) { + const toDate = args.object[args.constraints[0]]; + const res = isSameDay(fromDate, toDate) || isBefore(fromDate, toDate); + return res + } + + defaultMessage(args: ValidationArguments) { + return 'From Date must be before or equal to To Date'; + } +} + + class FiltersDto { @IsEnum(Order,{ message: "nameOrder must be a valid enum value asc or desc" }) @IsOptional() + @ApiPropertyOptional() nameOrder: Order; @IsEnum(Order,{ message: "nameOrder must be a valid enum value asc or desc" }) @IsOptional() + @ApiPropertyOptional() percentageOrder: Order; @IsString() @IsOptional() + @ApiPropertyOptional() search: string; @IsString() @IsOptional() + @ApiPropertyOptional() userId: string; + + @ApiPropertyOptional({ + type: Date, + description: "From Date", + }) + @IsOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @Validate(IsFromDateBeforeToDateConstraint, ['toDate']) + fromDate: Date; + + @IsOptional() + @ApiProperty({ + type: Date, + description: "To Date", + }) + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + + toDate: Date; } export class AttendanceStatsDto { - @ApiProperty({ - type: String, - description: "The name of the person", - }) + @Expose() name: string; @@ -44,38 +77,23 @@ export class AttendanceStatsDto { @Expose() contextId: string; - @ApiProperty({ - type: String, - description: "The attendance percentage of the person", - }) + @Expose() attendance_percentage: string; - @ApiProperty({ - type: String, - description: "userId of student", - }) + @Expose() userId: string; - @ApiProperty({ - description: "attendance date", - }) + @Expose() attendanceDate: Date; - @ApiProperty({ - description: "attendance", - }) + @Expose() attendance: string; - @ApiProperty({ - type: String, - description: "flag", - }) - @Expose() - report: boolean; + @ApiProperty({ type: Number, @@ -85,7 +103,7 @@ export class AttendanceStatsDto { @Expose() limit: number; - @ApiProperty({ + @ApiPropertyOptional({ type: Number, description: "offset", }) @@ -93,7 +111,7 @@ export class AttendanceStatsDto { offset: number; @ApiProperty({ - type: Object, + type: FiltersDto, description: "Filters", }) @ApiPropertyOptional() diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 2366e1a0..5fa321df 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -172,11 +172,18 @@ export class AttendanceDto { export class UserAttendanceDTO { @IsUUID() @IsNotEmpty() + @ApiProperty() + @IsUUID() userId: string; - @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) + @ApiProperty({ + type: String, + description: "The attendance of the attendance", + default: "", + }) + @Expose() @IsNotEmpty() - // Assuming these are the possible values for attendance + @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) attendance: string; } @@ -184,7 +191,6 @@ export class BulkAttendanceDTO { @ApiProperty({ type: String, description: "The date of the attendance in format yyyy-mm-dd", - default: new Date() }) @IsNotEmpty() @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @@ -197,11 +203,15 @@ export class BulkAttendanceDTO { @IsUUID() @Expose() @IsNotEmpty() + @ApiProperty() contextId: string; - @ApiPropertyOptional() + @ApiProperty({ + type: [UserAttendanceDTO], // Specify the type of userAttendance as an array of UserAttendanceDTO + description: 'List of user attendance details', + }) @ValidateNested({ each: true }) @Type(() => UserAttendanceDTO) // Adjust the max size according to your requirements diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index f555fc32..fb35aa70 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -24,6 +24,9 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiHeader, + ApiBadRequestResponse, + ApiInternalServerErrorResponse, + ApiConflictResponse, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { Response, response } from "express"; @@ -41,8 +44,9 @@ export class PrivilegeController { @Get("/:privilegeId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Privilege Detail." }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @ApiHeader({ name: "tenantid" }) - @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({strategy: "excludeAll",}) public async getPrivilege( @Param("privilegeId") privilegeId: string, @@ -60,8 +64,10 @@ export class PrivilegeController { @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Privilege has been created successfully." }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) + @ApiConflictResponse({ description: "Privilege Already Exists" }) @ApiBody({ type: PrivilegeDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ name: "tenantid" }) public async createPrivilege( @Req() request: Request, @@ -75,7 +81,10 @@ export class PrivilegeController { @Put("/:id") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Role updated successfully." }) + @ApiOkResponse({ description: "Role updated successfully." }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) + @ApiConflictResponse({ description: "Privilege Already Exists" }) @ApiBody({ type:PrivilegeDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ name: "tenantid", }) @@ -93,7 +102,9 @@ export class PrivilegeController { @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Privilege Detail." }) @ApiHeader({ name: "tenantid" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiOkResponse({ description: "Privileges List" }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @SerializeOptions({strategy: "excludeAll",}) public async getAllPrivilege( @Req() request: Request, @@ -105,9 +116,10 @@ export class PrivilegeController { @Delete("/:id") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Role updated successfully." }) @ApiBody({ type:PrivilegeDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiOkResponse({ description: "Privilege Deleted" }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @ApiHeader({ name: "tenantid", }) public async deletePrivilege( @Param("id") privilegeId: string, From e7d8e684c28ac486d30782a199bee3508b0a4af7 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 19 Apr 2024 16:52:32 +0530 Subject: [PATCH 249/408] Fix[applied authguard] --- src/attendance/attendance.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 18ed48e8..4384aa0a 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -43,7 +43,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("Attendance") @Controller("attendance") -// @UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard) export class AttendanceController { constructor( private attendaceAdapter: AttendaceAdapter, From caed0fc14f2a335e3a1408a8e0984cada8137bcd Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Fri, 19 Apr 2024 17:25:34 +0530 Subject: [PATCH 250/408] Fix[Fix Mark and update attendance API due to change in search API] --- src/adapters/postgres/attendance-adapter.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index a7f1d7b0..eee45839 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -89,12 +89,6 @@ export class PostgresAttendanceService { WHERE ${whereClause}; `; const results = await this.attendanceRepository.query(query, queryParams); - if(!results.length){ - return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'No data Found For Entered Filter', - }); - } const mappedResponse = await this.mappedResponse(results); return new SuccessResponse({ From d886e707719e20b6dd4f8446c6db161fe9bd48c6 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Sat, 20 Apr 2024 13:30:38 +0530 Subject: [PATCH 251/408] Cohort Member: Swagger & search API changes --- .../postgres/cohortMembers-adapter.ts | 328 ++++++++++-------- src/cohortMembers/cohortMembers.controller.ts | 31 +- src/cohortMembers/cohortMembers.module.ts | 3 +- .../dto/cohortMembers-search.dto.ts | 3 +- 4 files changed, 200 insertions(+), 165 deletions(-) diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index 8a2c91f3..7ed3c1af 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -16,7 +16,9 @@ import { User } from "src/user/entities/user-entity"; import { CohortMembersUpdateDto } from "src/cohortMembers/dto/cohortMember-update.dto"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { Fields } from "src/fields/entities/fields.entity"; - +import { UUID } from "typeorm/driver/mongodb/bson.typings"; +import { isUUID } from "class-validator"; +import { Cohort } from "src/cohort/entities/cohort.entity"; @Injectable() export class PostgresCohortMembersService { constructor( @@ -25,64 +27,40 @@ export class PostgresCohortMembersService { @InjectRepository(Fields) private fieldsRepository: Repository, @InjectRepository(User) - private usersRepository: Repository + private usersRepository: Repository, + @InjectRepository(Cohort) + private cohortRepository: Repository ) {} - async getCohortMembers( - userId: any, - - fieldvalue: any - ) { + async getCohortMembers(cohortId: any, fieldvalue: any) { try { - if (fieldvalue === "false") { - const result = { - userData: {}, - }; - - let customFieldsArray = []; - - const [userDetails] = await Promise.all([this.findUserDetails(userId)]); - result.userData = userDetails; - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: result, + if (!isUUID(cohortId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid (UUID)", }); - } else { - const result = { - userData: {}, + } + const userDetails = await this.findcohortData(cohortId); + if (userDetails === true) { + let results = { + userDetails: [], }; - let customFieldsArray = []; - - const [filledValues, userDetails] = await Promise.all([ - this.findFilledValues(userId), - this.findUserDetails(userId), - ]); - - const customFields = await this.findCustomFields(userDetails.role); - - result.userData = userDetails; - const filledValuesMap = new Map( - filledValues.map((item) => [item.fieldId, item.value]) + let cohortDetails = await this.getUserDetails( + cohortId, + "cohortId", + fieldvalue ); - for (let data of customFields) { - const fieldValue = filledValuesMap.get(data.fieldId); - const customField = { - fieldId: data.fieldId, - label: data.label, - value: fieldValue || "", - options: data?.fieldParams?.["options"] || {}, - type: data.type || "", - }; - customFieldsArray.push(customField); - } - result.userData["customFields"] = customFieldsArray; - + results.userDetails.push(cohortDetails); return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", - data: result, + data: results, + }); + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Cohort Member not exist", }); } } catch (e) { @@ -92,27 +70,54 @@ export class PostgresCohortMembersService { }); } } + async getUserDetails(searchId: any, searchKey: any, fieldShowHide: any) { + let results = { + userDetails: [], + }; + + let getUserDetails = await this.findUserName(searchId, searchKey); + + for (let data of getUserDetails) { + let userDetails = { + userId: data?.userId, + userName: data?.userName, + name: data?.name, + role: data?.role, + district: data?.district, + state: data?.state, + mobile: data?.mobile, + customField: [], + }; + if (fieldShowHide === "false") { + results.userDetails.push(userDetails); + } else { + const fieldValues = await this.getFieldandFieldValues(data.userId); + userDetails.customField.push(fieldValues); + results.userDetails.push(userDetails); + } + } + + return results; + } async findFilledValues(userId: string) { - let query = `SELECT U."userId",F."fieldId",F."value" FROM public."Users" U + let query = `SELECT U."userId",F."fieldId",F."value" FROM public."Users" U LEFT JOIN public."FieldValues" F ON U."userId" = F."itemId" where U."userId" =$1`; let result = await this.usersRepository.query(query, [userId]); return result; } - - async findUserDetails(userId, username?: any) { - let whereClause: any = { userId: userId }; - if (username && userId === null) { - delete whereClause.userId; - whereClause.username = username; - } - let userDetails = await this.usersRepository.findOne({ + async findcohortData(cohortId: any) { + let whereClause: any = { cohortId: cohortId }; + let userDetails = await this.cohortMembersRepository.find({ where: whereClause, }); - return userDetails; + if (userDetails.length !== 0) { + return true; + } else { + return false; + } } - async findCustomFields(role) { let customFields = await this.fieldsRepository.find({ where: { @@ -123,23 +128,30 @@ export class PostgresCohortMembersService { return customFields; } - async findUsertDetails(userId: string) { - let whereClause: any = { userId: userId }; - let userDetails = await this.usersRepository.findOne({ - where: whereClause, - }); - return userDetails; - } - async searchFindCustomFields() { - let customFields = await this.fieldsRepository.find({ - where: { - context: "COHORT", - contextType: "COHORT", - }, - }); - return customFields; + async getFieldandFieldValues(userId: string) { + let query = `SELECT Fv."fieldId",F."label" AS FieldName,Fv."value" as FieldValues + FROM public."FieldValues" Fv + LEFT JOIN public."Fields" F + ON F."fieldId" = Fv."fieldId" + where Fv."itemId" =$1 `; + let result = await this.usersRepository.query(query, [userId]); + return result; } + async findUserName(searchData: string, searchKey: any) { + let whereCase; + if (searchKey == "cohortId") { + whereCase = `where CM."cohortId" =$1`; + } else { + whereCase = `where CM."userId" =$1`; + } + let query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + LEFT JOIN public."Users" U + ON CM."userId" = U."userId" ${whereCase}`; + + let result = await this.usersRepository.query(query, [searchData]); + return result; + } public async searchCohortMembers( cohortMembersSearchDto: CohortMembersSearchDto ) { @@ -159,6 +171,44 @@ export class PostgresCohortMembersService { }); } + // Validate cohortId and userId format + if (whereClause["cohortId"] && !isUUID(whereClause["cohortId"])) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter a valid UUID for cohortId", + }); + } + if (whereClause["userId"] && !isUUID(whereClause["userId"])) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter a valid UUID for userId", + }); + } + // Check if cohortId exists + if (whereClause["cohortId"]) { + const cohortExists = await this.cohortMembersRepository.findOne({ + where: { cohortId: whereClause["cohortId"] }, + }); + if (!cohortExists) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Cohort Member with specified cohortId not found", + }); + } + } + + // Check if userId exists + if (whereClause["userId"]) { + const userExists = await this.cohortMembersRepository.findOne({ + where: { userId: whereClause["userId"] }, + }); + if (!userExists) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Cohort Member with specified userId not found", + }); + } + } const [userData] = await this.cohortMembersRepository.findAndCount({ where: whereClause, skip: offset, @@ -167,22 +217,19 @@ export class PostgresCohortMembersService { let results = { userDetails: [], }; - if (whereClause["cohortId"]) { - let req = 1; - let cohortDetails = await this.getUsersDetailsByCohortId( + let cohortDetails = await this.getUserDetails( whereClause["cohortId"], - req + "cohortId", + "true" ); results.userDetails.push(cohortDetails); } - if (whereClause["userId"]) { - let fieldvalue = 1; - - let cohortDetails = await this.getCohortMembers( + let cohortDetails = await this.getUserDetails( whereClause["userId"], - fieldvalue + "userId", + "true" ); results.userDetails.push(cohortDetails); } @@ -200,67 +247,6 @@ export class PostgresCohortMembersService { } } - async getUsersDetailsByCohortId(cohortId: any, response: any) { - let apiId = "api.users.getAllUsersDetails"; - try { - let getUserDetails = await this.findUserName(cohortId); - - let result = { - userDetails: [], - }; - - for (let data of getUserDetails) { - let userDetails = { - userId: data.userId, - userName: data.userName, - name: data.name, - role: data.role, - district: data.district, - state: data.state, - mobile: data.mobile, - customField: [], - }; - const fieldValues = await this.getFieldandFieldValues(data.userId); - - userDetails.customField.push(fieldValues); - - result.userDetails.push(userDetails); - } - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: result, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } - - async findUserName(cohortId: string) { - let query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM - LEFT JOIN public."Users" U - ON CM."userId" = U."userId" - where CM."cohortId" =$1 `; - - let result = await this.usersRepository.query(query, [cohortId]); - - return result; - } - - async getFieldandFieldValues(userId: string) { - let query = `SELECT Fv."fieldId",F."label" AS FieldName,Fv."value" as FieldValues - FROM public."FieldValues" Fv - LEFT JOIN public."Fields" F - ON F."fieldId" = Fv."fieldId" - where Fv."itemId" =$1 `; - let result = await this.usersRepository.query(query, [userId]); - return result; - } - public async createCohortMembers( loginUser: any, cohortMembers: CohortMembersDto, @@ -289,6 +275,42 @@ export class PostgresCohortMembersService { } } + // public async updateCohortMembers( + // cohortMembershipId: string, + // loginUser: any, + // cohortMembersUpdateDto: CohortMembersUpdateDto, + // response: any + // ) { + // const apiId = "api.cohortMember.updateCohortMembers"; + + // try { + // cohortMembersUpdateDto.updatedBy = loginUser; + + // const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ + // where: { cohortMembershipId: cohortMembershipId }, + // }); + + // if (!cohortMemberToUpdate) { + // throw new Error("Cohort member not found"); + // } + // Object.assign(cohortMemberToUpdate, cohortMembersUpdateDto); + + // const updatedCohortMember = await this.cohortMembersRepository.save( + // cohortMemberToUpdate + // ); + + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: "Cohort Member Updated successfully.", + // data: updatedCohortMember, + // }); + // } catch (e) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + // } + // } public async updateCohortMembers( cohortMembershipId: string, loginUser: any, @@ -299,16 +321,30 @@ export class PostgresCohortMembersService { try { cohortMembersUpdateDto.updatedBy = loginUser; + if (!isUUID(cohortMembershipId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter a valid UUID for cohortMemberId", + }); + } + // Find the cohort member to update const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ where: { cohortMembershipId: cohortMembershipId }, }); + // If cohort member not found, return error if (!cohortMemberToUpdate) { - throw new Error("Cohort member not found"); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Cohort member not found", + }); } + + // Update cohort member with provided data Object.assign(cohortMemberToUpdate, cohortMembersUpdateDto); + // Save updated cohort member const updatedCohortMember = await this.cohortMembersRepository.save( cohortMemberToUpdate ); diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index f5018a04..b91c3212 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -7,6 +7,8 @@ import { ApiHeader, ApiOkResponse, ApiQuery, + ApiNotFoundResponse, + ApiBadRequestResponse, } from "@nestjs/swagger"; import { Controller, @@ -16,8 +18,6 @@ import { Put, Delete, Param, - UseInterceptors, - ClassSerializerInterceptor, SerializeOptions, Req, Headers, @@ -54,8 +54,6 @@ export class CohortMembersController { description: "Cohort Members has been created successfully.", }) @ApiBody({ type: CohortMembersDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -79,21 +77,21 @@ export class CohortMembersController { } //get cohort members - @Get("/:userId") - @UseInterceptors(ClassSerializerInterceptor) + @Get("/:cohortId") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members detail" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiNotFoundResponse({ description: "Data not found" }) + @ApiBadRequestResponse({ description: "Bad request" }) @SerializeOptions({ strategy: "excludeAll" }) @ApiHeader({ name: "tenantid" }) @ApiQuery({ name: "fieldvalue", - description: "The field Value (optional)", + description: "Send True to Fetch Custom Field of User", required: false, }) public async getCohortMembers( @Headers() headers, - @Param("userId") userId: string, + @Param("cohortId") cohortId: string, @Req() request: Request, @Res() response: Response, @Query("fieldvalue") fieldvalue: string | null = null @@ -102,18 +100,18 @@ export class CohortMembersController { const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() - .getCohortMembers(userId, fieldvalue); + .getCohortMembers(cohortId, fieldvalue); return response.status(result.statusCode).json(result); } - search; + // search; @Post("/search") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members list." }) + @ApiNotFoundResponse({ description: "Data not found" }) + @ApiBadRequestResponse({ description: "Bad request" }) @ApiBody({ type: CohortMembersSearchDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @UseInterceptors(ClassSerializerInterceptor) @SerializeOptions({ strategy: "excludeAll", }) @@ -140,9 +138,9 @@ export class CohortMembersController { @ApiCreatedResponse({ description: "Cohort Members has been updated successfully.", }) + @ApiNotFoundResponse({ description: "Data not found" }) + @ApiBadRequestResponse({ description: "Bad request" }) @ApiBody({ type: CohortMembersUpdateDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - // @UseInterceptors(ClassSerializerInterceptor) public async updateCohortMembers( @Param("id") cohortMembersId: string, @Req() request, @@ -164,10 +162,9 @@ export class CohortMembersController { //delete @Delete("/:id") - @UseInterceptors(ClassSerializerInterceptor) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort member deleted successfully" }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiNotFoundResponse({ description: "Data not found" }) @SerializeOptions({ strategy: "excludeAll", }) diff --git a/src/cohortMembers/cohortMembers.module.ts b/src/cohortMembers/cohortMembers.module.ts index a4d9e81d..b153ef71 100644 --- a/src/cohortMembers/cohortMembers.module.ts +++ b/src/cohortMembers/cohortMembers.module.ts @@ -11,10 +11,11 @@ import { PostgresCohortMembersService } from "src/adapters/postgres/cohortMember import { HasuraCohortMembersService } from "src/adapters/hasura/cohortMembers.adapter"; import { Fields } from "src/fields/entities/fields.entity"; import { User } from "src/user/entities/user-entity"; +import { Cohort } from "src/cohort/entities/cohort.entity"; @Module({ imports: [ - TypeOrmModule.forFeature([CohortMembers, Fields, User]), + TypeOrmModule.forFeature([CohortMembers, Fields, User, Cohort]), HttpModule, HasuraModule, PostgresModule, diff --git a/src/cohortMembers/dto/cohortMembers-search.dto.ts b/src/cohortMembers/dto/cohortMembers-search.dto.ts index c2a49786..b91425fe 100644 --- a/src/cohortMembers/dto/cohortMembers-search.dto.ts +++ b/src/cohortMembers/dto/cohortMembers-search.dto.ts @@ -16,9 +16,10 @@ export class CohortMembersSearchDto { @ApiProperty({ type: Object, description: "Filters", + example: { cohortId: "", userId: "" }, // Adding example for Swagger }) @ApiPropertyOptional() - filters: object; + filters: { cohortId?: string; userId?: string }; // Define cohortId and userId properties constructor(partial: Partial) { Object.assign(this, partial); From 1ea8cc425fffe44df8d10f3118698f2329d60ec0 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 20 Apr 2024 17:50:33 +0530 Subject: [PATCH 252/408] add --- src/cohortMembers/cohortMember.service.ts | 2 +- src/cohortMembers/cohortMembers.controller.ts | 2 +- src/cohortMembers/cohortMembers.module.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 9682b2bd..8a5f036b 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -297,4 +297,4 @@ export class CohortMembersService { ); } } -} +} \ No newline at end of file diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index bf9e65d6..52815fb8 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -173,4 +173,4 @@ export class CohortMembersController { request ); } -} +} \ No newline at end of file diff --git a/src/cohortMembers/cohortMembers.module.ts b/src/cohortMembers/cohortMembers.module.ts index 191c7389..4cb86767 100644 --- a/src/cohortMembers/cohortMembers.module.ts +++ b/src/cohortMembers/cohortMembers.module.ts @@ -16,4 +16,4 @@ import { CohortMembersService } from "./cohortMember.service"; controllers: [CohortMembersController], providers: [CohortMembersAdapter, CohortMembersService], }) -export class CohortMembersModule {} +export class CohortMembersModule {} \ No newline at end of file From 95f869fc1e48e110a2e4f413519cc77d8c324408 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 20 Apr 2024 17:54:46 +0530 Subject: [PATCH 253/408] resolved conflict --- src/cohort/cohort.controller.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 15ee07fc..0167ae09 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -41,13 +41,8 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") -<<<<<<< HEAD -@Controller("cohort") -// @UseGuards(JwtAuthGuard) -======= @Controller("cohorts") @UseGuards(JwtAuthGuard) ->>>>>>> d1d6d54835c63dc708d2bba86ca42acd973570db export class CohortController { constructor(private readonly cohortAdapter:CohortAdapter) {} @@ -99,14 +94,10 @@ export class CohortController { @Post("/search") @ApiBasicAuth("access-token") @ApiBody({ type: CohortSearchDto }) -<<<<<<< HEAD - @ApiForbiddenResponse({ description: "Forbidden" }) -======= @ApiOkResponse({ description: "Cohort list" }) @ApiBadRequestResponse({description: "Bad request."}) @ApiInternalServerErrorResponse({description: "Internal Server Error."}) // @UseInterceptors(ClassSerializerInterceptor) ->>>>>>> d1d6d54835c63dc708d2bba86ca42acd973570db @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", @@ -143,14 +134,10 @@ export class CohortController { }) ) @ApiBody({ type: CohortCreateDto }) -<<<<<<< HEAD - @ApiForbiddenResponse({ description: "Forbidden" }) -======= @ApiOkResponse({ description: "Cohort has been updated successfully" }) @ApiBadRequestResponse({description: "Bad request."}) @ApiInternalServerErrorResponse({description: "Internal Server Error."}) ->>>>>>> d1d6d54835c63dc708d2bba86ca42acd973570db public async updateCohort( @Param("id") cohortId: string, @Req() request: Request, From dbf4c0511968ab9489c659113fc8a672473bf823 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Mon, 22 Apr 2024 10:00:35 +0530 Subject: [PATCH 254/408] remove commented code --- .../postgres/cohortMembers-adapter.ts | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index 7ed3c1af..60a9dc0d 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -275,42 +275,6 @@ export class PostgresCohortMembersService { } } - // public async updateCohortMembers( - // cohortMembershipId: string, - // loginUser: any, - // cohortMembersUpdateDto: CohortMembersUpdateDto, - // response: any - // ) { - // const apiId = "api.cohortMember.updateCohortMembers"; - - // try { - // cohortMembersUpdateDto.updatedBy = loginUser; - - // const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ - // where: { cohortMembershipId: cohortMembershipId }, - // }); - - // if (!cohortMemberToUpdate) { - // throw new Error("Cohort member not found"); - // } - // Object.assign(cohortMemberToUpdate, cohortMembersUpdateDto); - - // const updatedCohortMember = await this.cohortMembersRepository.save( - // cohortMemberToUpdate - // ); - - // return new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: "Cohort Member Updated successfully.", - // data: updatedCohortMember, - // }); - // } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); - // } - // } public async updateCohortMembers( cohortMembershipId: string, loginUser: any, From a39996490b6225d7c7e38711fd669a1321ee8d70 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 22 Apr 2024 11:53:17 +0530 Subject: [PATCH 255/408] COHORT: Search api changes --- src/adapters/cohortservicelocator.ts | 5 +- src/adapters/hasura/cohort.adapter.ts | 208 +++++----------- src/adapters/postgres/cohort-adapter.ts | 256 ++++++++++++-------- src/adapters/postgres/fields-adapter.ts | 90 ++++--- src/cohort/cohort.controller.ts | 79 ++++-- src/cohort/cohort.service.ts | 231 +++++++++--------- src/cohort/dto/cohort-create.dto.ts | 56 ++--- src/cohort/dto/cohort-search.dto.ts | 13 +- src/cohort/dto/cohort-update.dto.ts | 98 ++++++++ src/fields/dto/field-values-create.dto.ts | 10 - src/fields/dto/field-values.dto.ts | 30 +-- src/fields/entities/fields-values.entity.ts | 2 +- 12 files changed, 556 insertions(+), 522 deletions(-) create mode 100644 src/cohort/dto/cohort-update.dto.ts diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index 8c29b49b..37fb0fcc 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -1,11 +1,12 @@ import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; +import { CohortUpdateDto } from "src/cohort/dto/cohort-update.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { CohortDto } from "src/cohort/dto/cohort.dto"; export interface IServicelocatorcohort { + getCohortsDetails(cohortId: string); createCohort(request: any, cohortDto: CohortCreateDto); searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto); - updateCohort(cohortId: string, request: any, cohortDto: CohortCreateDto); - getCohortsDetails(cohortId: string); + updateCohort(cohortId: string, request: any, cohortUpdateDto: CohortUpdateDto); updateCohortStatus(cohortId: string, request: any); } diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index eb0befb1..e1c9c5c6 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -12,6 +12,7 @@ import { UserDto } from "src/user/dto/user.dto"; import { FieldsService } from "./services/fields.service"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { CohortUpdateDto } from "src/cohort/dto/cohort-update.dto"; export const HasuraCohortToken = "HasuraCohort"; @Injectable() export class HasuraCohortService implements IServicelocatorcohort { @@ -263,104 +264,7 @@ export class HasuraCohortService implements IServicelocatorcohort { public async searchCohort(tenantId: string,request: any,cohortSearchDto: CohortSearchDto) {} public async updateCohortStatus(cohortId: string, request: any) {} public async getCohortsDetails(cohortId: string) {} - public async updateCohort( - cohortId: string, - request: any, - cohortUpdateDto: CohortCreateDto - ) { - var axios = require("axios"); - - let query = ""; - Object.keys(cohortUpdateDto).forEach((e) => { - if ( - cohortUpdateDto[e] && - cohortUpdateDto[e] != "" && - e != "fieldValues" - ) { - if (Array.isArray(cohortUpdateDto[e])) { - query += `${e}: "${JSON.stringify(cohortUpdateDto[e])}", `; - } else { - query += `${e}: "${cohortUpdateDto[e]}", `; - } - } - }); - - var data = { - query: ` - mutation UpdateCohort($cohortId:uuid!) { - update_Cohort_by_pk( - pk_columns: { - cohortId: $cohortId - }, - _set: { - ${query} - } - ) { - cohortId - } - } - `, - variables: { - cohortId: cohortId, - }, - }; - - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; - - const response = await axios(config); - - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response.data.update_Cohort_by_pk; - let fieldCreate = true; - let fieldError = []; - //update fields values - let field_value_array = cohortUpdateDto.fieldValues.split("|"); - if (field_value_array.length > 0) { - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - //update values - let fieldValuesUpdate = new FieldValuesDto({ - value: fieldValues[1] ? fieldValues[1] : "", - }); - - const response_field_values = - await this.fieldsService.updateFieldValues( - fieldValues[0] ? fieldValues[0] : "", - fieldValuesUpdate - ); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError.push(response_field_values?.data); - } - } - } - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } else { - return new ErrorResponse({ - errorCode: "filed value update error", - errorMessage: JSON.stringify(fieldError), - }); - } - } - } + public async updateCohort(cohortId: string,request: any,cohortUpdateDto: CohortUpdateDto) {} public async mappedResponse(result: any) { const cohortResponse = result.map((item: any) => { @@ -413,64 +317,64 @@ export class HasuraCohortService implements IServicelocatorcohort { cohortSearchDto: CohortSearchDto ) { try{ - var axios = require("axios"); + // var axios = require("axios"); - let offset = 0; - if (cohortSearchDto.page > 1) { - offset = parseInt(cohortSearchDto.limit) * (cohortSearchDto.page - 1); - } + // let offset = 0; + // if (cohortSearchDto.page > 1) { + // offset = parseInt(cohortSearchDto.limit) * (cohortSearchDto.page - 1); + // } - let temp_filters = cohortSearchDto.filters; - //add tenantid - let filters = new Object(temp_filters); - filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; + // let temp_filters = cohortSearchDto.filters; + // //add tenantid + // let filters = new Object(temp_filters); + // filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - Object.keys(cohortSearchDto.filters).forEach((item) => { - Object.keys(cohortSearchDto.filters[item]).forEach((e) => { - if (!e.startsWith("_")) { - filters[item][`_${e}`] = filters[item][e]; - delete filters[item][e]; - } - }); - }); - var data = { - query: `query SearchCohort($filters:Cohort_bool_exp,$limit:Int, $offset:Int) { - Cohort(where:$filters, limit: $limit, offset: $offset,) { - tenantId - programId - cohortId - parentId - referenceId - name - type - status - image - metadata - createdAt - updatedAt - createdBy - updatedBy - } - }`, - variables: { - limit: parseInt(cohortSearchDto.limit), - offset: offset, - filters: cohortSearchDto.filters, - }, - }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - Authorization: request.headers.authorization, - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + // Object.keys(cohortSearchDto.filters).forEach((item) => { + // Object.keys(cohortSearchDto.filters[item]).forEach((e) => { + // if (!e.startsWith("_")) { + // filters[item][`_${e}`] = filters[item][e]; + // delete filters[item][e]; + // } + // }); + // }); + // var data = { + // query: `query SearchCohort($filters:Cohort_bool_exp,$limit:Int, $offset:Int) { + // Cohort(where:$filters, limit: $limit, offset: $offset,) { + // tenantId + // programId + // cohortId + // parentId + // referenceId + // name + // type + // status + // image + // metadata + // createdAt + // updatedAt + // createdBy + // updatedBy + // } + // }`, + // variables: { + // limit: parseInt(cohortSearchDto.limit), + // offset: offset, + // filters: cohortSearchDto.filters, + // }, + // }; + // var config = { + // method: "post", + // url: process.env.REGISTRYHASURA, + // headers: { + // Authorization: request.headers.authorization, + // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + // "Content-Type": "application/json", + // }, + // data: data, + // }; - const response = await axios(config); - return response; + // const response = await axios(config); + // return response; }catch (e) { console.error(e); diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 7d5e25e0..3d890de7 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -8,7 +8,9 @@ import { CohortDto } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { UserDto } from "src/user/dto/user.dto"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; +import { CohortUpdateDto } from "src/cohort/dto/cohort-update.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { FieldValuesUpdateDto } from "src/fields/dto/field-values-update.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; @@ -80,25 +82,30 @@ export class PostgresCohortService { public async getCohortsDetails(cohortId: string) { try { + console.log(cohortId); + if (!isUUID(cohortId)) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, errorMessage: "Please Enter valid (UUID)", }); } - const result = await this.getCohortDataWithCustomfield(cohortId); - console.log(result); - // if(!result.length){ - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.NOT_FOUND, - // errorMessage: "CohortId not found", - // }); - // } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: result, - }); + const checkData = await this.checkAuthAndValidData(cohortId); + + if (checkData === true) { + const result = await this.getCohortDataWithCustomfield(cohortId); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Cohort detais fetched succcessfully.", + data: result, + }); + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Cohort not found", + }); + } + } catch (error) { return new ErrorResponseTypeOrm({ @@ -122,7 +129,7 @@ export class PostgresCohortService { this.findCustomFields() ]); - + result.cohortData = cohortDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { @@ -194,13 +201,45 @@ export class PostgresCohortService { public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try { // console.log(request.user.userId) - // cohortCreateDto.createdBy =uuidv4(request.user.userId); - console.log(cohortCreateDto); - - const response = await this.cohortRepository.save(cohortCreateDto); + const decoded: any = jwt_decode(request.headers.authorization); + cohortCreateDto.createdBy = decoded?.sub + cohortCreateDto.updatedBy = decoded?.sub + cohortCreateDto.status = true; + cohortCreateDto.attendanceCaptureImage = false; + + let response; + if (cohortCreateDto.name && cohortCreateDto.parentId) { + const existData = await this.cohortRepository.find({ + where: { name: cohortCreateDto.name, parentId: cohortCreateDto.parentId } + }) + if (existData.length == 0) { + response = await this.cohortRepository.save(cohortCreateDto); + } else { + return new SuccessResponse({ + statusCode: HttpStatus.CONFLICT, + message: "Cohort name already exist for this parent.", + data: existData, + }); + } + } else { + const existData = await this.cohortRepository.find({ + where: { name: cohortCreateDto.name } + }) + if (existData.length == 0) { + response = await this.cohortRepository.save(cohortCreateDto); + } else { + return new SuccessResponse({ + statusCode: HttpStatus.CONFLICT, + message: "Cohort Name already exists.", + data: existData, + }); + } + } + let cohortId = response?.cohortId; + let field_value_array = cohortCreateDto.fieldValues.split("|"); if (field_value_array.length > 0) { @@ -209,23 +248,23 @@ export class PostgresCohortService { let fieldValues = field_value_array[i].split(":"); let fieldValueDto: FieldValuesDto = { - fieldValuesId: "", // Provide a value for fieldValuesId value: fieldValues[1] ? fieldValues[1].trim() : "", itemId: cohortId, fieldId: fieldValues[0] ? fieldValues[0].trim() : "", createdBy: cohortCreateDto?.createdBy, updatedBy: cohortCreateDto?.updatedBy, - createdAt: new Date().toISOString(), // Provide appropriate values for createdAt and updatedAt + createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; - await this.fieldsService.createFieldValues(request, fieldValueDto); + const fieldValue = await this.fieldsService.createFieldValues(request, fieldValueDto); + } } return new SuccessResponse({ statusCode: HttpStatus.CREATED, - message: "Ok.", + message: "Cohort Created Successfully.", data: response, }); @@ -240,72 +279,72 @@ export class PostgresCohortService { public async updateCohort( cohortId: string, request: any, - cohortUpdateDto: CohortCreateDto + cohortUpdateDto: CohortUpdateDto ) { try { + const decoded: any = jwt_decode(request.headers.authorization); + cohortUpdateDto.updatedBy = decoded?.sub + + if (!isUUID(cohortId)) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, errorMessage: "Please Enter valid (UUID)", }); } - const checkData = await this.checkAuthAndValidData(cohortId); - if (checkData) { - // const cohortUpdateData: any = {}; - - // Object.keys(cohortUpdateDto).forEach((e) => { - // if (cohortUpdateDto[e] && cohortUpdateDto[e] != "" && e != "fieldValues" - // ) { - // if (Array.isArray(cohortUpdateDto[e])) { - // cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); - // } else { - // cohortUpdateData[e] = cohortUpdateDto[e]; - // } - // } - // }); - cohortUpdateDto.updatedBy = request.user.userId; - const response = await this.cohortRepository.update(cohortId, cohortUpdateDto); + const checkData = await this.checkAuthAndValidData(cohortId); - if (cohortUpdateDto.fieldValues) { - let field_value_array = cohortUpdateDto.fieldValues.split("|"); - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - - let fieldValues = field_value_array[i].split(":"); - let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; - try { - const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) - const rowid = fieldVauesRowId.fieldValuesId; - - let fieldValueDto: FieldValuesDto = { - fieldValuesId: rowid, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.updateFieldValues(rowid, fieldValueDto); - } catch { - let fieldValueDto: FieldValuesDto = { - fieldValuesId: null, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.createFieldValues(request, fieldValueDto); - } + if (checkData === true) { + const filteredDto = Object.entries(cohortUpdateDto) + .filter(([_, value]) => value !== undefined && value !== '') + .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); + + if (Object.keys(filteredDto).length === 0) { + // If there are no properties to update, return success + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "No fields to update.", + data: { + rowCount: 0, } - } + }); } + console.log("hii"); + const response = await this.cohortRepository.update(cohortId, cohortUpdateDto); + console.log("hii1"); + // if (cohortUpdateDto.fieldValues) { + // let field_value_array = cohortUpdateDto.fieldValues.split("|"); + // if (field_value_array.length > 0) { + // let field_values = []; + // for (let i = 0; i < field_value_array.length; i++) { + + // let fieldValues = field_value_array[i].split(":"); + // let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + // try { + // const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + // const rowid = fieldVauesRowId.fieldValuesId; + + // let fieldValueUpdateDto: FieldValuesUpdateDto = { + // fieldValuesId: rowid, + // value: fieldValues[1] ? fieldValues[1].trim() : "" + // }; + // await this.fieldsService.updateFieldValues(rowid, fieldValueUpdateDto); + // } catch { + // let fieldValueDto: FieldValuesDto = { + // value: fieldValues[1] ? fieldValues[1].trim() : "", + // itemId: cohortId, + // fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + // createdBy: cohortUpdateDto?.createdBy, + // updatedBy: cohortUpdateDto?.updatedBy, + // createdAt: new Date().toISOString(), + // updatedAt: new Date().toISOString(), + // }; + // await this.fieldsService.createFieldValues(request, fieldValueDto); + // } + // } + // } + // } return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -314,10 +353,10 @@ export class PostgresCohortService { rowCount: response.affected, } }); - }else { + } else { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User not found", + errorMessage: "Cohort not found", }); } } catch (e) { @@ -339,11 +378,28 @@ export class PostgresCohortService { let offset = 0; if (page > 1) { - offset = parseInt(limit) * (page - 1); + offset = (limit) * (page - 1); + } + + if (limit === 0) { + limit = 0; } + const MAX_LIMIT = 20; + const PAGE_LIMIT = 100000; - if (limit.trim() === '') { - limit = '0'; + // Validate the limit parameter + if (limit > MAX_LIMIT) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Limit exceeds maximum allowed value of ${MAX_LIMIT}`, + }); + } + + if (page > PAGE_LIMIT) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Page limit exceeds maximum allowed value of ${PAGE_LIMIT}`, + }); } const whereClause = {}; @@ -356,26 +412,23 @@ export class PostgresCohortService { cohortDetails: [], }; - if (whereClause['userId'] || whereClause['cohortId']) { + if (whereClause['userId']) { const [cohortData] = await this.cohortMembersRepository.findAndCount({ where: whereClause, skip: offset, - take: parseInt(limit), + take: limit, }); - if (whereClause['userId']) { - for (let data of cohortData) { - let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); - results.cohortDetails.push(cohortDetails); - } - } else { - let cohortDetails = await this.getCohortDataWithCustomfield(whereClause['cohortId']); + + for (let data of cohortData) { + let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); results.cohortDetails.push(cohortDetails); } + } else { const [cohortData] = await this.cohortRepository.findAndCount({ where: whereClause, skip: offset, - take: parseInt(limit), + take: limit, }); for (let data of cohortData) { let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); @@ -383,13 +436,20 @@ export class PostgresCohortService { } } + if (results.cohortDetails.length > 0) { + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Cohort detais fetched succcessfully', + data: results, + }); + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "No data found.", + }); + } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: results, - }); } catch (e) { return new ErrorResponseTypeOrm({ @@ -435,13 +495,13 @@ export class PostgresCohortService { }); } const checkData = await this.checkAuthAndValidData(cohortId); - const updatedBy = request.user.userId; + const updatedBy = request.user.userId; if (checkData === true) { let query = `UPDATE public."Cohort" SET "status" = false, "updatedBy" = '${updatedBy}' WHERE "cohortId" = $1`; - + const results = await this.cohortRepository.query(query, [cohortId]); return new SuccessResponse({ statusCode: HttpStatus.OK, diff --git a/src/adapters/postgres/fields-adapter.ts b/src/adapters/postgres/fields-adapter.ts index 3f9b23d4..f0808835 100644 --- a/src/adapters/postgres/fields-adapter.ts +++ b/src/adapters/postgres/fields-adapter.ts @@ -2,12 +2,13 @@ import { HttpStatus, Injectable } from "@nestjs/common"; import { FieldsDto } from "src/fields/dto/fields.dto"; import { FieldsSearchDto } from "src/fields/dto/fields-search.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; +import { FieldValuesUpdateDto } from "src/fields/dto/field-values-update.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; import { ErrorResponse } from "src/error-response"; import { Fields } from "../../fields/entities/fields.entity"; import { FieldValues } from "../../fields/entities/fields-values.entity"; import { InjectRepository } from "@nestjs/typeorm"; -import { Repository} from "typeorm"; +import { Repository } from "typeorm"; import { SuccessResponse } from "src/success-response"; import APIResponse from "src/utils/response"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; @@ -58,17 +59,17 @@ export class PostgresFieldsService { try { const getConditionalData = APIResponse.search(fieldsSearchDto) - const offset = getConditionalData.offset ; - const limit = getConditionalData.limit ; - const whereClause = getConditionalData.whereClause ; - + const offset = getConditionalData.offset; + const limit = getConditionalData.limit; + const whereClause = getConditionalData.whereClause; + const getFieldValue = await this.searchFieldData(offset, limit, whereClause) return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', - totalCount : getFieldValue.totalCount, + totalCount: getFieldValue.totalCount, data: getFieldValue.mappedResponse, }); @@ -80,7 +81,7 @@ export class PostgresFieldsService { } } - async searchFieldData(offset: number, limit: string, searchData:any){ + async searchFieldData(offset: number, limit: string, searchData: any) { let queryOptions: any = { where: searchData, }; @@ -88,42 +89,37 @@ export class PostgresFieldsService { if (offset !== undefined) { queryOptions.skip = offset; } - + if (limit !== undefined) { queryOptions.take = parseInt(limit); } - + const [results, totalCount] = await this.fieldsRepository.findAndCount(queryOptions); const mappedResponse = await this.mappedResponseField(results); - return {mappedResponse, totalCount}; + return { mappedResponse, totalCount }; } async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { try { - - const fieldsData: any = {}; - Object.keys(fieldValuesDto).forEach((e) => { - if (fieldValuesDto[e] && fieldValuesDto[e] != "") { - if (Array.isArray(fieldValuesDto[e])) { - fieldsData[e] = JSON.stringify(fieldValuesDto[e]); - } else { - fieldsData[e] = fieldValuesDto[e]; - } - } + const checkFieldValueExist = await this.fieldsValuesRepository.find({ + where: { itemId: fieldValuesDto.itemId, fieldId: fieldValuesDto.fieldId }, }); - let result = await this.fieldsValuesRepository.save(fieldsData); - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Ok.", - data: result, - }); + if (checkFieldValueExist.length == 0) { + + let result = await this.fieldsValuesRepository.save(fieldValuesDto); + return new SuccessResponse({ + statusCode: HttpStatus.CREATED, + message: "Ok.", + data: result, + }); + } } catch (e) { return new ErrorResponseTypeOrm({ - statusCode:HttpStatus.INTERNAL_SERVER_ERROR, + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, }); } @@ -132,9 +128,9 @@ export class PostgresFieldsService { async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { try { const getConditionalData = APIResponse.search(fieldValuesSearchDto) - const offset = getConditionalData.offset ; - const limit = getConditionalData.limit ; - const whereClause = getConditionalData.whereClause ; + const offset = getConditionalData.offset; + const limit = getConditionalData.limit; + const whereClause = getConditionalData.whereClause; const getFieldValue = await this.getSearchFieldValueData(offset, limit, whereClause) @@ -153,47 +149,47 @@ export class PostgresFieldsService { } } - async getSearchFieldValueData(offset: number, limit: string, searchData:any){ + async getSearchFieldValueData(offset: number, limit: string, searchData: any) { let queryOptions: any = { where: searchData, }; - + if (offset !== undefined) { queryOptions.skip = offset; } - + if (limit !== undefined) { queryOptions.take = parseInt(limit); } - + const [results, totalCount] = await this.fieldsValuesRepository.findAndCount(queryOptions); const mappedResponse = await this.mappedResponse(results); - return {mappedResponse, totalCount}; + return { mappedResponse, totalCount }; } - async searchFieldValueId(cohortId: string, fieldId: string){ + async searchFieldValueId(itemId: string, fieldId: string) { const response = await this.fieldsValuesRepository.findOne({ - where: { itemId: cohortId, fieldId: fieldId }, + where: { itemId: itemId, fieldId: fieldId }, }); return response; } - - async updateFieldValues(id: string, fieldValuesDto: FieldValuesDto) { + + async updateFieldValues(id: string, fieldValuesUpdateDto: FieldValuesUpdateDto) { try { const fieldsData: any = {}; - Object.keys(fieldValuesDto).forEach((e) => { - if (fieldValuesDto[e] && fieldValuesDto[e] != "") { - if (Array.isArray(fieldValuesDto[e])) { - fieldsData[e] = JSON.stringify(fieldValuesDto[e]); + Object.keys(fieldValuesUpdateDto).forEach((e) => { + if (fieldValuesUpdateDto[e] && fieldValuesUpdateDto[e] != "") { + if (Array.isArray(fieldValuesUpdateDto[e])) { + fieldsData[e] = JSON.stringify(fieldValuesUpdateDto[e]); } else { - fieldsData[e] = fieldValuesDto[e]; + fieldsData[e] = fieldValuesUpdateDto[e]; } } }); - const response = await this.fieldsValuesRepository.update(id, fieldValuesDto); + const response = await this.fieldsValuesRepository.update(id, fieldValuesUpdateDto); return response; } catch (e) { @@ -204,7 +200,7 @@ export class PostgresFieldsService { } } - public async getFieldsAndFieldsValues(cohortId:string){ + public async getFieldsAndFieldsValues(cohortId: string) { let query = `SELECT FV."value",FV."itemId", FV."fieldId", F."name" AS fieldname, F."label", F."context",F."type", F."state", F."contextType", F."fieldParams" FROM public."FieldValues" FV LEFT JOIN public."Fields" F ON FV."fieldId" = F."fieldId" where FV."itemId" =$1`; @@ -234,7 +230,7 @@ export class PostgresFieldsService { public async mappedResponseField(result: any) { const fieldResponse = result.map((item: any) => { - + const fieldMapping = { fieldId: item?.fieldId ? `${item.fieldId}` : "", assetId: item?.assetId ? `${item.assetId}` : "", diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 0167ae09..05dc3460 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -9,6 +9,8 @@ import { ApiBadRequestResponse, ApiInternalServerErrorResponse, ApiOkResponse, + ApiNotFoundResponse, + ApiConflictResponse, } from "@nestjs/swagger"; import { Controller, @@ -28,6 +30,7 @@ import { ValidationPipe, UsePipes, Query, + BadRequestException, } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -37,22 +40,45 @@ import { diskStorage } from "multer"; import { Response, response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; +import { CohortUpdateDto } from "./dto/cohort-update.dto"; + import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") @Controller("cohorts") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) export class CohortController { - constructor(private readonly cohortAdapter:CohortAdapter) {} + constructor(private readonly cohortAdapter: CohortAdapter) { } + + //Get Cohort Details + @Get("/:cohortId") + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Cohort detais Fetched Succcessfully" }) + @ApiNotFoundResponse({ description: "Cohort Not Found" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) + @ApiBadRequestResponse({description:"Bad Request"}) + @SerializeOptions({ strategy: "excludeAll", }) + @ApiHeader({ name: "tenantid", }) + public async getCohortsDetails( + @Headers() headers, + @Param("cohortId") cohortId: string, + @Req() request: Request, + @Res() response: Response + ) { + // const tenantId = headers["tenantid"]; Can be Used In future + const result = await this.cohortAdapter.buildCohortAdapter().getCohortsDetails(cohortId); + return response.status(result.statusCode).json(result); + } //create cohort @Post() @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort has been created successfully." }) - @ApiBadRequestResponse({description: "Bad request."}) - @ApiInternalServerErrorResponse({description: "Internal Server Error."}) + @ApiBadRequestResponse({ description: "Bad request." }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) + @ApiConflictResponse({description:"Cohort already exists."}) @UseInterceptors( FileInterceptor("image", { @@ -65,8 +91,6 @@ export class CohortController { ) @UsePipes(new ValidationPipe()) @ApiBody({ type: CohortCreateDto }) - - // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ name: "tenantid", }) @@ -77,6 +101,15 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { + // Define expected fields + const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues' ]; + + // Check if any unexpected fields are present in the request body + const unexpectedFields = Object.keys(cohortCreateDto).filter(field => !expectedFields.includes(field)); + if (unexpectedFields.length > 0) { + throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); + } + let tenantid = headers["tenantid"]; const payload = { image: image?.filename, @@ -90,15 +123,17 @@ export class CohortController { return response.status(result.statusCode).json(result); } + + // search @Post("/search") @ApiBasicAuth("access-token") @ApiBody({ type: CohortSearchDto }) @ApiOkResponse({ description: "Cohort list" }) - @ApiBadRequestResponse({description: "Bad request."}) - @ApiInternalServerErrorResponse({description: "Internal Server Error."}) + @ApiBadRequestResponse({ description: "Bad request." }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) // @UseInterceptors(ClassSerializerInterceptor) - @UsePipes(ValidationPipe) + @UsePipes(new ValidationPipe()) @SerializeOptions({ strategy: "excludeAll", }) @@ -121,7 +156,7 @@ export class CohortController { } //update - @Put("/:id") + @Put("/:cohortId") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @UseInterceptors( @@ -133,44 +168,44 @@ export class CohortController { fileFilter: imageFileFilter, }) ) - @ApiBody({ type: CohortCreateDto }) + @ApiBody({ type: CohortUpdateDto }) @ApiOkResponse({ description: "Cohort has been updated successfully" }) - @ApiBadRequestResponse({description: "Bad request."}) - @ApiInternalServerErrorResponse({description: "Internal Server Error."}) + @ApiBadRequestResponse({ description: "Bad request." }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) public async updateCohort( - @Param("id") cohortId: string, + @Param("cohortId") cohortId: string, @Req() request: Request, - @Body() cohortCreateDto: CohortCreateDto, + @Body() cohortUpdateDto: CohortUpdateDto, @UploadedFile() image, @Res() response: Response ) { const imgresponse = { image: image?.filename, }; - Object.assign(cohortCreateDto, imgresponse); + Object.assign(cohortUpdateDto, imgresponse); const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( cohortId, request, - cohortCreateDto + cohortUpdateDto ); return response.status(result.statusCode).json(result); } //delete cohort - @Delete("/:id") + @Delete("/:cohortId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Cohort has been deleted successfully." }) - @ApiBadRequestResponse({description: "Bad request."}) - @ApiInternalServerErrorResponse({description: "Internal Server Error."}) + @ApiBadRequestResponse({ description: "Bad request." }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) public async updateCohortStatus( - @Param("id") cohortId: string, + @Param("cohortId") cohortId: string, @Req() request: Request, @Res() response: Response ) { - const result = await this.cohortAdapter.buildCohortAdapter().updateCohortStatus(cohortId,request); + const result = await this.cohortAdapter.buildCohortAdapter().updateCohortStatus(cohortId, request); return response.status(result.statusCode).json(result); } } diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index 9e4759cc..c7e005bd 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -139,7 +139,6 @@ export class CohortService { for (let i = 0; i < field_value_array.length; i++) { let fieldValues = field_value_array[i].split(":"); let fieldValueDto: FieldValuesDto = { - fieldValuesId: "", // Provide a value for fieldValuesId value: fieldValues[1] ? fieldValues[1].trim() : "", itemId: cohortId, fieldId: fieldValues[0] ? fieldValues[0].trim() : "", @@ -166,133 +165,133 @@ export class CohortService { } } - public async updateCohort( - cohortId: string, - request: any, - cohortUpdateDto: CohortCreateDto - ) { - try { - const cohortUpdateData: any = {}; + // public async updateCohort( + // cohortId: string, + // request: any, + // cohortUpdateDto: CohortCreateDto + // ) { + // try { + // const cohortUpdateData: any = {}; - Object.keys(cohortUpdateDto).forEach((e) => { - if ( - cohortUpdateDto[e] && - cohortUpdateDto[e] != "" && - e != "fieldValues" - ) { - if (Array.isArray(cohortUpdateDto[e])) { - cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); - } else { - cohortUpdateData[e] = cohortUpdateDto[e]; - } - } - }); + // Object.keys(cohortUpdateDto).forEach((e) => { + // if ( + // cohortUpdateDto[e] && + // cohortUpdateDto[e] != "" && + // e != "fieldValues" + // ) { + // if (Array.isArray(cohortUpdateDto[e])) { + // cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + // } else { + // cohortUpdateData[e] = cohortUpdateDto[e]; + // } + // } + // }); - const response = await this.cohortRepository.update( - cohortId, - cohortUpdateData - ); + // const response = await this.cohortRepository.update( + // cohortId, + // cohortUpdateData + // ); - let field_value_array = cohortUpdateDto.fieldValues.split("|"); + // let field_value_array = cohortUpdateDto.fieldValues.split("|"); - if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; - try { - const fieldVauesRowId = await this.fieldsService.searchFieldValueId( - cohortId, - fieldId - ); - const rowid = fieldVauesRowId.fieldValuesId; + // if (field_value_array.length > 0) { + // let field_values = []; + // for (let i = 0; i < field_value_array.length; i++) { + // let fieldValues = field_value_array[i].split(":"); + // let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + // try { + // const fieldVauesRowId = await this.fieldsService.searchFieldValueId( + // cohortId, + // fieldId + // ); + // const rowid = fieldVauesRowId.fieldValuesId; - let fieldValueDto: FieldValuesDto = { - fieldValuesId: rowid, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.updateFieldValues(rowid, fieldValueDto); - } catch { - let fieldValueDto: FieldValuesDto = { - fieldValuesId: null, - value: fieldValues[1] ? fieldValues[1].trim() : "", - itemId: cohortId, - fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - createdBy: cohortUpdateDto?.createdBy, - updatedBy: cohortUpdateDto?.updatedBy, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - await this.fieldsService.createFieldValues(request, fieldValueDto); - } - } - } + // let fieldValueDto: FieldValuesDto = { + // fieldValuesId: rowid, + // value: fieldValues[1] ? fieldValues[1].trim() : "", + // itemId: cohortId, + // fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + // createdBy: cohortUpdateDto?.createdBy, + // updatedBy: cohortUpdateDto?.updatedBy, + // createdAt: new Date().toISOString(), + // updatedAt: new Date().toISOString(), + // }; + // await this.fieldsService.updateFieldValues(rowid, fieldValueDto); + // } catch { + // let fieldValueDto: FieldValuesDto = { + // fieldValuesId: null, + // value: fieldValues[1] ? fieldValues[1].trim() : "", + // itemId: cohortId, + // fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + // createdBy: cohortUpdateDto?.createdBy, + // updatedBy: cohortUpdateDto?.updatedBy, + // createdAt: new Date().toISOString(), + // updatedAt: new Date().toISOString(), + // }; + // await this.fieldsService.createFieldValues(request, fieldValueDto); + // } + // } + // } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: { - rowCount: response.affected, - }, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: "Ok.", + // data: { + // rowCount: response.affected, + // }, + // }); + // } catch (e) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + // } + // } - public async searchCohort( - tenantId: string, - request: any, - cohortSearchDto: CohortSearchDto - ) { - try { - let { limit, page, filters } = cohortSearchDto; + // public async searchCohort( + // tenantId: string, + // request: any, + // cohortSearchDto: CohortSearchDto + // ) { + // try { + // let { limit, page, filters } = cohortSearchDto; - let offset = 0; - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } + // let offset = 0; + // if (page > 1) { + // offset = parseInt(limit) * (page - 1); + // } - if (limit.trim() === "") { - limit = "0"; - } + // if (limit.trim() === "") { + // limit = "0"; + // } - const whereClause = {}; - if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } - const [results, totalCount] = await this.cohortRepository.findAndCount({ - where: whereClause, - skip: offset, - take: parseInt(limit), - }); + // const whereClause = {}; + // if (filters && Object.keys(filters).length > 0) { + // Object.entries(filters).forEach(([key, value]) => { + // whereClause[key] = value; + // }); + // } + // const [results, totalCount] = await this.cohortRepository.findAndCount({ + // where: whereClause, + // skip: offset, + // take: parseInt(limit), + // }); - const mappedResponse = await this.mappedResponse(results); + // const mappedResponse = await this.mappedResponse(results); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - totalCount, - data: mappedResponse, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: "Ok.", + // totalCount, + // data: mappedResponse, + // }); + // } catch (e) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + // } + // } public async mappedResponse(result: any) { const cohortValueResponse = result.map((item: any) => { diff --git a/src/cohort/dto/cohort-create.dto.ts b/src/cohort/dto/cohort-create.dto.ts index 58a9799b..d7974d2e 100644 --- a/src/cohort/dto/cohort-create.dto.ts +++ b/src/cohort/dto/cohort-create.dto.ts @@ -1,10 +1,8 @@ import { Exclude, Expose } from "class-transformer"; import { - MaxLength, IsNotEmpty, - IsEmail, IsString, - IsNumber, + IsOptional } from "class-validator"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { FieldValuesCreateDto } from "src/fields/dto/field-values-create.dto"; @@ -18,6 +16,7 @@ export class CohortCreateDto { @Expose() createdAt: string; + @Expose() updatedAt: string; @@ -40,11 +39,6 @@ export class CohortCreateDto { parentId: string; //referenceId - @ApiPropertyOptional({ - type: String, - description: "The referenceId of the cohort", - default: "", - }) @Expose() referenceId: string; @@ -55,6 +49,7 @@ export class CohortCreateDto { default: "", }) @Expose() + @IsNotEmpty() name: string; //type @@ -64,55 +59,31 @@ export class CohortCreateDto { default: "", }) @Expose() + @IsNotEmpty() type: string; //status - @ApiPropertyOptional({ - type: Boolean, - description: "The status of the cohort", - default: true, - }) @Expose() status: boolean; //attendanceCaptureImage - @ApiProperty({ - type: Boolean, - description: "Capture image while marking the attendance", - default: false, - }) @Expose() attendanceCaptureImage: boolean; - //image - @Expose() - @ApiPropertyOptional({ type: "string", format: "binary" }) - image: string; + //image need for future + // @Expose() + // @ApiPropertyOptional({ type: "string", format: "binary" }) + // image: string; //metadata - @ApiPropertyOptional({ - type: String, - description: "The metadata of cohort", - default: "", - }) @Expose() metadata: string; //createdBy - @ApiPropertyOptional({ - type: String, - description: "The cohort is createdBy", - default: "", - }) @Expose() createdBy: string; //updatedBy - @ApiPropertyOptional({ - type: String, - description: "The cohort is updatedBy", - default: "", - }) @Expose() updatedBy: string; @@ -121,10 +92,15 @@ export class CohortCreateDto { type: String, description: "The fieldValues Object", }) + @IsString() + @IsOptional() @Expose() - fieldValues: string; + fieldValues?: string; + - constructor(obj: any) { - Object.assign(this, obj); + constructor(obj?: Partial) { + if (obj) { + Object.assign(this, obj); + } } } diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index 968cb109..efc6af69 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -1,27 +1,28 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsNumberString } from "class-validator"; +import { IsNumber, IsNumberString, IsObject } from "class-validator"; import { CohortDto } from "./cohort.dto"; export class CohortSearchDto { @ApiProperty({ - type: String, + type: Number, description: "Limit", }) - @IsNumberString() - limit: string; + @IsNumber() + limit: number; @ApiProperty({ type: Number, - description: "number", + description: "Page", }) + @IsNumber() page: number; @ApiProperty({ type: CohortDto, description: "Filters", }) - @ApiPropertyOptional() + @IsObject() filters: object; constructor(partial: Partial) { diff --git a/src/cohort/dto/cohort-update.dto.ts b/src/cohort/dto/cohort-update.dto.ts new file mode 100644 index 00000000..0c7a8d88 --- /dev/null +++ b/src/cohort/dto/cohort-update.dto.ts @@ -0,0 +1,98 @@ +import { Exclude, Expose } from "class-transformer"; +import { + IsNotEmpty, + IsString, + IsOptional +} from "class-validator"; +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; + + +export class CohortUpdateDto { + @Expose() + cohortId: string; + + @Expose() + tenantId: string; + + @Expose() + createdAt: string; + + @Expose() + updatedAt: string; + + //programId + @ApiPropertyOptional({ + type: String, + description: "The programId of the cohort", + }) + @Expose() + programId: string; + + //parentId + @ApiPropertyOptional({ + type: String, + description: "The parentId of the cohort", + }) + @Expose() + parentId: string; + + //referenceId + @Expose() + referenceId: string; + + //name + @ApiPropertyOptional({ + type: String, + description: "The name of the cohort", + }) + @Expose() + name: string; + + //type + @ApiPropertyOptional({ + type: String, + description: "The type of the cohort", + }) + @Expose() + type: string; + + //status + @Expose() + status: boolean; + + //attendanceCaptureImage + @Expose() + attendanceCaptureImage: boolean; + + //image need for future + // @Expose() + // @ApiPropertyOptional({ type: "string", format: "binary" }) + // image: string; + + //metadata + @Expose() + metadata: string; + + //createdBy + @Expose() + createdBy: string; + + //updatedBy + @Expose() + updatedBy: string; + + //fieldValues + @ApiPropertyOptional({ + type: String, + description: "The fieldValues Object", + }) + @Expose() + fieldValues: string; + + + constructor(obj?: Partial) { + if (obj) { + Object.assign(this, obj); + } + } +} diff --git a/src/fields/dto/field-values-create.dto.ts b/src/fields/dto/field-values-create.dto.ts index b356f5bd..152c2b6f 100644 --- a/src/fields/dto/field-values-create.dto.ts +++ b/src/fields/dto/field-values-create.dto.ts @@ -10,20 +10,10 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class FieldValuesCreateDto { //fieldId - @ApiProperty({ - type: String, - description: "The fieldId of the field values", - default: "", - }) @Expose() fieldId: string; //value - @ApiProperty({ - type: String, - description: "The value of the field values", - default: "", - }) @Expose() value: string; diff --git a/src/fields/dto/field-values.dto.ts b/src/fields/dto/field-values.dto.ts index 766e21fc..61af23db 100644 --- a/src/fields/dto/field-values.dto.ts +++ b/src/fields/dto/field-values.dto.ts @@ -9,56 +9,30 @@ import { import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class FieldValuesDto { - //generated fields - @Expose() - fieldValuesId: string; + @Expose() createdAt: string; + @Expose() updatedAt: string; //fieldId - @ApiProperty({ - type: String, - description: "The fieldId of the field values", - default: "", - }) @Expose() fieldId: string; //value - @ApiProperty({ - type: String, - description: "The value of the field values", - default: "", - }) @Expose() value: string; //itemId - @ApiProperty({ - type: String, - description: "The itemId of the field values", - default: "", - }) @Expose() itemId: string; //createdBy - @ApiProperty({ - type: String, - description: "The createdBy of the field values", - default: "", - }) @Expose() createdBy: string; //updatedBy - @ApiProperty({ - type: String, - description: "The updatedBy of the field values", - default: "", - }) @Expose() updatedBy: string; diff --git a/src/fields/entities/fields-values.entity.ts b/src/fields/entities/fields-values.entity.ts index 0f4f7d86..122e8ec0 100644 --- a/src/fields/entities/fields-values.entity.ts +++ b/src/fields/entities/fields-values.entity.ts @@ -5,7 +5,7 @@ export class FieldValues { @Column({ type: 'text', nullable: false }) value: string; - @PrimaryGeneratedColumn('uuid', { name: 'fieldValuesId' }) + @PrimaryGeneratedColumn('uuid') fieldValuesId: string; @Column({ type: 'uuid', nullable: false, default: () => 'gen_random_uuid()' }) From a7faff386e59c66aefe2a928a56e115f0d0e1263 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 22 Apr 2024 12:02:24 +0530 Subject: [PATCH 256/408] add --- src/cohort/cohort.service.ts | 226 +++++++++++++++++------------------ 1 file changed, 111 insertions(+), 115 deletions(-) diff --git a/src/cohort/cohort.service.ts b/src/cohort/cohort.service.ts index c7e005bd..90ac4069 100644 --- a/src/cohort/cohort.service.ts +++ b/src/cohort/cohort.service.ts @@ -165,133 +165,129 @@ export class CohortService { } } - // public async updateCohort( - // cohortId: string, - // request: any, - // cohortUpdateDto: CohortCreateDto - // ) { - // try { - // const cohortUpdateData: any = {}; + public async updateCohort( + cohortId: string, + request: any, + cohortUpdateDto: CohortCreateDto + ) { + try { + const cohortUpdateData: any = {}; - // Object.keys(cohortUpdateDto).forEach((e) => { - // if ( - // cohortUpdateDto[e] && - // cohortUpdateDto[e] != "" && - // e != "fieldValues" - // ) { - // if (Array.isArray(cohortUpdateDto[e])) { - // cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); - // } else { - // cohortUpdateData[e] = cohortUpdateDto[e]; - // } - // } - // }); + Object.keys(cohortUpdateDto).forEach((e) => { + if ( + cohortUpdateDto[e] && + cohortUpdateDto[e] != "" && + e != "fieldValues" + ) { + if (Array.isArray(cohortUpdateDto[e])) { + cohortUpdateData[e] = JSON.stringify(cohortUpdateDto[e]); + } else { + cohortUpdateData[e] = cohortUpdateDto[e]; + } + } + }); - // const response = await this.cohortRepository.update( - // cohortId, - // cohortUpdateData - // ); + const response = await this.cohortRepository.update( + cohortId, + cohortUpdateData + ); - // let field_value_array = cohortUpdateDto.fieldValues.split("|"); + let field_value_array = cohortUpdateDto.fieldValues.split("|"); - // if (field_value_array.length > 0) { - // let field_values = []; - // for (let i = 0; i < field_value_array.length; i++) { - // let fieldValues = field_value_array[i].split(":"); - // let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; - // try { - // const fieldVauesRowId = await this.fieldsService.searchFieldValueId( - // cohortId, - // fieldId - // ); - // const rowid = fieldVauesRowId.fieldValuesId; + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + let fieldValues = field_value_array[i].split(":"); + let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + try { + const fieldVauesRowId = await this.fieldsService.searchFieldValueId( + cohortId, + fieldId + ); + const rowid = fieldVauesRowId.fieldValuesId; - // let fieldValueDto: FieldValuesDto = { - // fieldValuesId: rowid, - // value: fieldValues[1] ? fieldValues[1].trim() : "", - // itemId: cohortId, - // fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - // createdBy: cohortUpdateDto?.createdBy, - // updatedBy: cohortUpdateDto?.updatedBy, - // createdAt: new Date().toISOString(), - // updatedAt: new Date().toISOString(), - // }; - // await this.fieldsService.updateFieldValues(rowid, fieldValueDto); - // } catch { - // let fieldValueDto: FieldValuesDto = { - // fieldValuesId: null, - // value: fieldValues[1] ? fieldValues[1].trim() : "", - // itemId: cohortId, - // fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - // createdBy: cohortUpdateDto?.createdBy, - // updatedBy: cohortUpdateDto?.updatedBy, - // createdAt: new Date().toISOString(), - // updatedAt: new Date().toISOString(), - // }; - // await this.fieldsService.createFieldValues(request, fieldValueDto); - // } - // } - // } + let fieldValueDto: FieldValuesDto = { + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.updateFieldValues(rowid, fieldValueDto); + } catch { + // let fieldValueDto: FieldValuesDto = { + // fieldValuesId: null, + // value: fieldValues[1] ? fieldValues[1].trim() : "", + // itemId: cohortId, + // fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + // createdBy: cohortUpdateDto?.createdBy, + // updatedBy: cohortUpdateDto?.updatedBy, + // createdAt: new Date().toISOString(), + // updatedAt: new Date().toISOString(), + // }; + // await this.fieldsService.createFieldValues(request, fieldValueDto); + } + } + } - // return new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: "Ok.", - // data: { - // rowCount: response.affected, - // }, - // }); - // } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); - // } - // } + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: { + rowCount: response.affected, + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } - // public async searchCohort( - // tenantId: string, - // request: any, - // cohortSearchDto: CohortSearchDto - // ) { - // try { - // let { limit, page, filters } = cohortSearchDto; + public async searchCohort( + tenantId: string, + request: any, + cohortSearchDto: CohortSearchDto + ) { + try { + let { limit, page, filters } = cohortSearchDto; - // let offset = 0; - // if (page > 1) { - // offset = parseInt(limit) * (page - 1); - // } + let offset = 0; + if (page > 1) { + offset = limit * (page - 1); + } - // if (limit.trim() === "") { - // limit = "0"; - // } - // const whereClause = {}; - // if (filters && Object.keys(filters).length > 0) { - // Object.entries(filters).forEach(([key, value]) => { - // whereClause[key] = value; - // }); - // } - // const [results, totalCount] = await this.cohortRepository.findAndCount({ - // where: whereClause, - // skip: offset, - // take: parseInt(limit), - // }); + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + const [results, totalCount] = await this.cohortRepository.findAndCount({ + where: whereClause, + skip: offset, + take: limit, + }); - // const mappedResponse = await this.mappedResponse(results); + const mappedResponse = await this.mappedResponse(results); - // return new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: "Ok.", - // totalCount, - // data: mappedResponse, - // }); - // } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); - // } - // } + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + totalCount, + data: mappedResponse, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } public async mappedResponse(result: any) { const cohortValueResponse = result.map((item: any) => { From a0ea3335504533a84871e57d0413b7e7c8c1a639 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 22 Apr 2024 12:06:12 +0530 Subject: [PATCH 257/408] add --- src/adapters/postgres/cohort-adapter.ts | 68 ++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 3d890de7..1965e599 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -310,41 +310,41 @@ export class PostgresCohortService { } }); } - console.log("hii"); + const response = await this.cohortRepository.update(cohortId, cohortUpdateDto); - console.log("hii1"); - // if (cohortUpdateDto.fieldValues) { - // let field_value_array = cohortUpdateDto.fieldValues.split("|"); - // if (field_value_array.length > 0) { - // let field_values = []; - // for (let i = 0; i < field_value_array.length; i++) { - - // let fieldValues = field_value_array[i].split(":"); - // let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; - // try { - // const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) - // const rowid = fieldVauesRowId.fieldValuesId; - - // let fieldValueUpdateDto: FieldValuesUpdateDto = { - // fieldValuesId: rowid, - // value: fieldValues[1] ? fieldValues[1].trim() : "" - // }; - // await this.fieldsService.updateFieldValues(rowid, fieldValueUpdateDto); - // } catch { - // let fieldValueDto: FieldValuesDto = { - // value: fieldValues[1] ? fieldValues[1].trim() : "", - // itemId: cohortId, - // fieldId: fieldValues[0] ? fieldValues[0].trim() : "", - // createdBy: cohortUpdateDto?.createdBy, - // updatedBy: cohortUpdateDto?.updatedBy, - // createdAt: new Date().toISOString(), - // updatedAt: new Date().toISOString(), - // }; - // await this.fieldsService.createFieldValues(request, fieldValueDto); - // } - // } - // } - // } + + if (cohortUpdateDto.fieldValues) { + let field_value_array = cohortUpdateDto.fieldValues.split("|"); + if (field_value_array.length > 0) { + let field_values = []; + for (let i = 0; i < field_value_array.length; i++) { + + let fieldValues = field_value_array[i].split(":"); + let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; + try { + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) + const rowid = fieldVauesRowId.fieldValuesId; + + let fieldValueUpdateDto: FieldValuesUpdateDto = { + fieldValuesId: rowid, + value: fieldValues[1] ? fieldValues[1].trim() : "" + }; + await this.fieldsService.updateFieldValues(rowid, fieldValueUpdateDto); + } catch { + let fieldValueDto: FieldValuesDto = { + value: fieldValues[1] ? fieldValues[1].trim() : "", + itemId: cohortId, + fieldId: fieldValues[0] ? fieldValues[0].trim() : "", + createdBy: cohortUpdateDto?.createdBy, + updatedBy: cohortUpdateDto?.updatedBy, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + await this.fieldsService.createFieldValues(request, fieldValueDto); + } + } + } + } return new SuccessResponse({ statusCode: HttpStatus.OK, From 48c5fb3bdb8cf7f6edbc47ca703a6dbb23fea123 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 22 Apr 2024 12:15:12 +0530 Subject: [PATCH 258/408] remove comented code --- src/adapters/postgres/cohort-adapter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 1965e599..6e697074 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -346,6 +346,7 @@ export class PostgresCohortService { } } + return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", From e7e18ce7208d08bd8d0e68a6aaedfe581f0eae2f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 22 Apr 2024 12:17:46 +0530 Subject: [PATCH 259/408] comment remove --- src/adapters/postgres/cohort-adapter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 6e697074..1965e599 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -346,7 +346,6 @@ export class PostgresCohortService { } } - return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", From 4bda4b66f8f6a9dd5853ab4df708092c7a124011 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 22 Apr 2024 12:26:36 +0530 Subject: [PATCH 260/408] remove comented code --- src/adapters/hasura/cohort.adapter.ts | 70 +-------------------------- 1 file changed, 1 insertion(+), 69 deletions(-) diff --git a/src/adapters/hasura/cohort.adapter.ts b/src/adapters/hasura/cohort.adapter.ts index e1c9c5c6..69bf39da 100644 --- a/src/adapters/hasura/cohort.adapter.ts +++ b/src/adapters/hasura/cohort.adapter.ts @@ -315,73 +315,5 @@ export class HasuraCohortService implements IServicelocatorcohort { request:any, tenantId: string, cohortSearchDto: CohortSearchDto - ) { - try{ - // var axios = require("axios"); - - // let offset = 0; - // if (cohortSearchDto.page > 1) { - // offset = parseInt(cohortSearchDto.limit) * (cohortSearchDto.page - 1); - // } - - // let temp_filters = cohortSearchDto.filters; - // //add tenantid - // let filters = new Object(temp_filters); - // filters["tenantId"] = { _eq: tenantId ? tenantId : "" }; - - // Object.keys(cohortSearchDto.filters).forEach((item) => { - // Object.keys(cohortSearchDto.filters[item]).forEach((e) => { - // if (!e.startsWith("_")) { - // filters[item][`_${e}`] = filters[item][e]; - // delete filters[item][e]; - // } - // }); - // }); - // var data = { - // query: `query SearchCohort($filters:Cohort_bool_exp,$limit:Int, $offset:Int) { - // Cohort(where:$filters, limit: $limit, offset: $offset,) { - // tenantId - // programId - // cohortId - // parentId - // referenceId - // name - // type - // status - // image - // metadata - // createdAt - // updatedAt - // createdBy - // updatedBy - // } - // }`, - // variables: { - // limit: parseInt(cohortSearchDto.limit), - // offset: offset, - // filters: cohortSearchDto.filters, - // }, - // }; - // var config = { - // method: "post", - // url: process.env.REGISTRYHASURA, - // headers: { - // Authorization: request.headers.authorization, - // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - // "Content-Type": "application/json", - // }, - // data: data, - // }; - - // const response = await axios(config); - // return response; - - }catch (e) { - console.error(e); - return new ErrorResponse({ - errorCode: "400", - errorMessage: e, - }); - } - } + ) {} } From 89ad0bd431d24c2eabece966742cb9eccf9ef05d Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Tue, 23 Apr 2024 10:10:17 +0530 Subject: [PATCH 261/408] Fix[changes for swagger] --- src/adapters/hasura/rbac/privilege.adapter.ts | 2 +- src/adapters/postgres/rbac/privilege-adapter.ts | 2 +- src/adapters/privilegeservicelocator.ts | 2 +- src/rbac/privilege/privilege.controller.ts | 4 +--- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/adapters/hasura/rbac/privilege.adapter.ts b/src/adapters/hasura/rbac/privilege.adapter.ts index 0649eba2..e1a3a692 100644 --- a/src/adapters/hasura/rbac/privilege.adapter.ts +++ b/src/adapters/hasura/rbac/privilege.adapter.ts @@ -11,6 +11,6 @@ export class HasuraPrivilegeService { public async getPrivilege(roleId: string, request: any) {} public async updatePrivilege(privilegeId, request, privilegeDto){} public async getAllPrivilege(request){} - public async deletePrivilege(privilegeId, request, privilegeDto){} + public async deletePrivilege(privilegeId, request){} } diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index b169b415..c8b03733 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -158,7 +158,7 @@ public async getAllPrivilege(request){ } - public async deletePrivilege(privilegeId, request, privilegeDto){ + public async deletePrivilege(privilegeId, request){ try { diff --git a/src/adapters/privilegeservicelocator.ts b/src/adapters/privilegeservicelocator.ts index a0c811f2..b0c00467 100644 --- a/src/adapters/privilegeservicelocator.ts +++ b/src/adapters/privilegeservicelocator.ts @@ -8,7 +8,7 @@ export interface IServicelocator { ); updatePrivilege(privilegeId, request, privilegeDto) getAllPrivilege(request) - deletePrivilege(privilegeId, request, privilegeDto) + deletePrivilege(privilegeId, request) } diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index 9964f69c..00cee396 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -116,7 +116,6 @@ export class PrivilegeController { @Delete("/:id") @ApiBasicAuth("access-token") - @ApiBody({ type:PrivilegeDto }) @ApiOkResponse({ description: "Privilege Deleted" }) @ApiBadRequestResponse({ description: "Bad Request" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @@ -124,10 +123,9 @@ export class PrivilegeController { public async deletePrivilege( @Param("id") privilegeId: string, @Req() request: Request, - @Body() privilegeDto: PrivilegeDto, @Res() response: Response ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().deletePrivilege(privilegeId, request, privilegeDto); + const result = await this.privilegeAdapter.buildPrivilegeAdapter().deletePrivilege(privilegeId, request); return response.status(result.statusCode).json(result); } From 7a7f54cf2b4178c18816e097196e03a104fd3583 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 24 Apr 2024 14:53:38 +0530 Subject: [PATCH 262/408] Fix[Privilege Create API] --- src/adapters/hasura/rbac/privilege.adapter.ts | 6 +- .../postgres/rbac/privilege-adapter.ts | 233 +++++++++--------- src/adapters/privilegeservicelocator.ts | 8 +- src/rbac/privilege/dto/privilege.dto.ts | 53 +++- .../privilege/entities/privilege.entity.ts | 22 +- src/rbac/privilege/privilege.controller.ts | 49 ++-- 6 files changed, 221 insertions(+), 150 deletions(-) diff --git a/src/adapters/hasura/rbac/privilege.adapter.ts b/src/adapters/hasura/rbac/privilege.adapter.ts index e1a3a692..a42cfa90 100644 --- a/src/adapters/hasura/rbac/privilege.adapter.ts +++ b/src/adapters/hasura/rbac/privilege.adapter.ts @@ -1,15 +1,15 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; -import { PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; +import { CreatePrivilegesDto, PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; @Injectable() export class HasuraPrivilegeService { constructor(private httpService: HttpService) {} - public async createPrivilege(request: any, privilegeDto: PrivilegeDto) {} + public async createPrivilege(loggedinUser: any, createPrivileges: CreatePrivilegesDto){} public async getPrivilege(roleId: string, request: any) {} - public async updatePrivilege(privilegeId, request, privilegeDto){} + // public async updatePrivilege(privilegeId, request, privilegeDto){} public async getAllPrivilege(request){} public async deletePrivilege(privilegeId, request){} diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index c8b03733..ff03738f 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -4,7 +4,7 @@ import { Repository } from 'typeorm'; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; -import { PrivilegeDto } from 'src/rbac/privilege/dto/privilege.dto'; +import { CreatePrivilegesDto, PrivilegeDto, PrivilegeResponseDto } from 'src/rbac/privilege/dto/privilege.dto'; import { isUUID } from 'class-validator'; @Injectable() @@ -13,152 +13,165 @@ export class PostgresPrivilegeService { @InjectRepository(Privilege) private privilegeRepository: Repository ) { } - - public async createPrivilege(request: any, privilegeDto: PrivilegeDto) { + + public async createPrivilege(loggedinUser: any, createPrivilegesDto: CreatePrivilegesDto) { + + const privileges = []; + const errors = [] try { - const label = privilegeDto.privilegeName.split(' ').join(''); + for (const privilegeDto of createPrivilegesDto.privileges) { + const code = privilegeDto.code; + // Check if privilege with the same label already exists + const existingPrivilege = await this.checkExistingPrivilege(code); + + if (existingPrivilege) { + errors.push({ + errorMessage: `Privilege with the code '${privilegeDto.code}' already exists.`, + }); + continue; // Skip to the next privilege + } - // const privilegeNameLowercase = privilegeDto.privilegeName.toLowerCase(); - + privilegeDto.createdBy = loggedinUser + privilegeDto.updatedBy = loggedinUser - const result = await this.checkExistingPrivilege(label) - if (result) { + // Create new privilege + const privilege = this.privilegeRepository.create(privilegeDto); + const response = await this.privilegeRepository.save(privilege); + privileges.push(new PrivilegeResponseDto(response)); + } + + } catch (e) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: "Privilege with the same name already exists.", + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.message || 'Internal server error', }); } - // Create new privilege - const privilege = this.privilegeRepository.create({ - ...privilegeDto, - privilegeName: privilegeDto.privilegeName, - label:label - }); - const response = await this.privilegeRepository.save(privilege); - - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Privilege created successfully.", - data: response, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + return { + statusCode: HttpStatus.OK, + successCount: privileges.length, + errorCount: errors.length, + privileges, + errors, + }; } -} - -async checkExistingPrivilege(label){ - const existingPrivilege = await this.privilegeRepository.findOne({ where: { label:label } }); - return existingPrivilege; -} - -public async getPrivilege(privilegeId: string, request: any) { - - - try { - if (!isUUID(privilegeId)) { + public async checkExistingPrivilege(code) { + try { + const existingPrivilege = await this.privilegeRepository.findOne({ where: { code } }); + return existingPrivilege; + } + catch (error) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid PrivilegeId (UUID)", + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, }); - } + } + } + + public async getPrivilege(privilegeId: string, request: any) { - const privilege = await this.privilegeRepository.findOne({ where: { privilegeId }} ); - if (!privilege) { + try { + + if (!isUUID(privilegeId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid PrivilegeId (UUID)", + }); + } + + const privilege = await this.privilegeRepository.findOne({ where: { privilegeId } }); + if (!privilege) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Privilege not found", + }); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + // totalCount, + data: privilege, + }); + } catch (e) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Privilege not found", + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, }); } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - // totalCount, - data: privilege, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); } -} + // public async updatePrivilege(privilegeId: string, request: any, privilegeDto: PrivilegeDto) { + // try { + // // Get the privilege using the getPrivilege method + // const existingPrivilegeResponse = await this.getPrivilege(privilegeId, request); -public async updatePrivilege(privilegeId: string, request: any, privilegeDto: PrivilegeDto) { - try { - // Get the privilege using the getPrivilege method - const existingPrivilegeResponse = await this.getPrivilege(privilegeId, request); + // if (existingPrivilegeResponse instanceof ErrorResponseTypeOrm) { + // return existingPrivilegeResponse; + // } - if (existingPrivilegeResponse instanceof ErrorResponseTypeOrm) { - return existingPrivilegeResponse; - } + // // Cast the data property of the SuccessResponse to a Privilege object + // const existingPrivilege: Privilege = existingPrivilegeResponse.data as Privilege; - // Cast the data property of the SuccessResponse to a Privilege object - const existingPrivilege: Privilege = existingPrivilegeResponse.data as Privilege; + // const newLabel = privilegeDto.privilegeName.split(' ').join(''); - const newLabel = privilegeDto.privilegeName.split(' ').join(''); - - const result = await this.checkExistingPrivilege(newLabel) + // const result = await this.checkExistingPrivilege(newLabel) - if (result) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: "Privilege with the same name already exists.", - }); - } - // Merge the updated data into the existing privilege - const mergedPrivilege = this.privilegeRepository.merge(existingPrivilege, privilegeDto); + // if (result) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.CONFLICT, + // errorMessage: "Privilege with the same name already exists.", + // }); + // } + // // Merge the updated data into the existing privilege + // const mergedPrivilege = this.privilegeRepository.merge(existingPrivilege, privilegeDto); - mergedPrivilege.label = newLabel; - // Save the updated privilege record - const updatedPrivilegeRecord = await this.privilegeRepository.save(mergedPrivilege); + // mergedPrivilege.label = newLabel; + // // Save the updated privilege record + // const updatedPrivilegeRecord = await this.privilegeRepository.save(mergedPrivilege); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Privilege updated successfully", - data: updatedPrivilegeRecord - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: "Internal server error", - }); - } -} + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: "Privilege updated successfully", + // data: updatedPrivilegeRecord + // }); + // } catch (e) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: "Internal server error", + // }); + // } + // } -public async getAllPrivilege(request){ + public async getAllPrivilege(request) { - try { - const [result,count] = await this.privilegeRepository.findAndCount(); + try { + const [result, count] = await this.privilegeRepository.findAndCount(); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok", - totalCount:count, - data: result - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: "Internal server error", - }); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok", + totalCount: count, + data: result + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: "Internal server error", + }); + } } -} - public async deletePrivilege(privilegeId, request){ + public async deletePrivilege(privilegeId, request) { try { diff --git a/src/adapters/privilegeservicelocator.ts b/src/adapters/privilegeservicelocator.ts index b0c00467..441dc6ed 100644 --- a/src/adapters/privilegeservicelocator.ts +++ b/src/adapters/privilegeservicelocator.ts @@ -1,14 +1,12 @@ -import { PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; +import { CreatePrivilegesDto, PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; export interface IServicelocator { - createPrivilege(request: any, privilegeDto: PrivilegeDto); + createPrivilege(loggedinUser: any, createPrivileges: CreatePrivilegesDto); getPrivilege( privilegeId?: string, request?: any, ); - updatePrivilege(privilegeId, request, privilegeDto) + // updatePrivilege(privilegeId, request, privilegeDto) getAllPrivilege(request) deletePrivilege(privilegeId, request) - - } diff --git a/src/rbac/privilege/dto/privilege.dto.ts b/src/rbac/privilege/dto/privilege.dto.ts index 404afd4f..ba5052c2 100644 --- a/src/rbac/privilege/dto/privilege.dto.ts +++ b/src/rbac/privilege/dto/privilege.dto.ts @@ -1,6 +1,6 @@ -import { Expose } from "class-transformer"; +import { Expose, Type } from "class-transformer"; import { ApiProperty } from "@nestjs/swagger"; -import {IsNotEmpty,IsString, IsUUID, Matches} from "class-validator" +import {IsNotEmpty,IsString, IsUUID, Matches, ValidateNested} from "class-validator" export class PrivilegeDto { @Expose() @@ -13,13 +13,58 @@ export class PrivilegeDto { }) @Expose() @IsNotEmpty() - privilegeName: string; + title: string; + @ApiProperty({ + type: String, + description: "Privilege title", + default: "", + }) + @IsNotEmpty() + @Expose() + code: string; + @Expose() - label: string; + createdAt: Date; + + @Expose() + updatedAt: Date; + + @Expose() + createdBy: string; + + @Expose() + updatedBy: string; constructor(obj: any) { Object.assign(this, obj); } } + + + +export class CreatePrivilegesDto { + @ValidateNested({ each: true }) + @Type(() => PrivilegeDto) + privileges: PrivilegeDto[]; +} + + +export class PrivilegeResponseDto { + @Expose() + privilegeId: string; + + @Expose() + title: string; + + @Expose() + code: string; + + constructor(privilegeDto: PrivilegeDto) { + this.privilegeId = privilegeDto.privilegeId; + this.title = privilegeDto.title; + this.code = privilegeDto.code; + + } +} diff --git a/src/rbac/privilege/entities/privilege.entity.ts b/src/rbac/privilege/entities/privilege.entity.ts index ba26946b..e11638bf 100644 --- a/src/rbac/privilege/entities/privilege.entity.ts +++ b/src/rbac/privilege/entities/privilege.entity.ts @@ -1,14 +1,28 @@ // export class Privilege {} -import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; -@Entity({ name: "Privilege" }) +@Entity({ name: "Privileges" }) export class Privilege { @PrimaryGeneratedColumn('uuid') privilegeId: string; + @Column({name:"name"}) + title: string; + @Column() - privilegeName: string; + code:string + + @CreateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + createdAt: Date; + + @UpdateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + updatedAt: Date; @Column() - label:string + createdBy: string; + + @Column() + updatedBy: string; + + } diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index 00cee396..ea0a1106 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -1,4 +1,4 @@ -import { PrivilegeDto } from './dto/privilege.dto'; +import { CreatePrivilegesDto, PrivilegeDto } from './dto/privilege.dto'; import { UpdatePrivilegeDto } from './dto/update-privilege.dto'; import { Controller, @@ -67,36 +67,37 @@ export class PrivilegeController { @ApiBadRequestResponse({ description: "Bad Request" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @ApiConflictResponse({ description: "Privilege Already Exists" }) - @ApiBody({ type: PrivilegeDto }) + @ApiBody({ type: CreatePrivilegesDto }) @ApiHeader({ name: "tenantid" }) public async createPrivilege( - @Req() request: Request, - @Body() privilegeDto: PrivilegeDto, + @Req() request, + @Body() createPrivilegesDto: CreatePrivilegesDto, @Res() response: Response ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().createPrivilege(request, privilegeDto); + + const result=await this.privilegeAdapter.buildPrivilegeAdapter().createPrivilege(request.user.userId, createPrivilegesDto); return response.status(result.statusCode).json(result); - } + } - @Put("/:id") - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Role updated successfully." }) - @ApiBadRequestResponse({ description: "Bad Request" }) - @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) - @ApiConflictResponse({ description: "Privilege Already Exists" }) - @ApiBody({ type:PrivilegeDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiHeader({ name: "tenantid", }) - public async updatePrivilege( - @Param("id") privilegeId: string, - @Req() request: Request, - @Body() privilegeDto: PrivilegeDto, - @Res() response: Response - ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().updatePrivilege(privilegeId, request, privilegeDto); - return response.status(result.statusCode).json(result); - } + // @Put("/:id") + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Role updated successfully." }) + // @ApiBadRequestResponse({ description: "Bad Request" }) + // @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) + // @ApiConflictResponse({ description: "Privilege Already Exists" }) + // @ApiBody({ type:PrivilegeDto }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // @ApiHeader({ name: "tenantid", }) + // public async updatePrivilege( + // @Param("id") privilegeId: string, + // @Req() request: Request, + // @Body() privilegeDto: PrivilegeDto, + // @Res() response: Response + // ) { + // const result = await this.privilegeAdapter.buildPrivilegeAdapter().updatePrivilege(privilegeId, request, privilegeDto); + // return response.status(result.statusCode).json(result); + // } @Get() @ApiBasicAuth("access-token") From 19db4704de4a05ba17710b4e9de39ba4533f56d4 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 24 Apr 2024 16:11:46 +0530 Subject: [PATCH 263/408] add --- src/adapters/postgres/cohort-adapter.ts | 41 +++++++++++++++---------- src/adapters/postgres/fields-adapter.ts | 3 ++ src/cohort/cohort.controller.ts | 31 +++++++++++-------- src/fields/fields.controller.ts | 2 +- 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 1965e599..4cbb4524 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -284,6 +284,7 @@ export class PostgresCohortService { try { const decoded: any = jwt_decode(request.headers.authorization); cohortUpdateDto.updatedBy = decoded?.sub + cohortUpdateDto.createdBy = decoded?.sub if (!isUUID(cohortId)) { @@ -296,32 +297,34 @@ export class PostgresCohortService { const checkData = await this.checkAuthAndValidData(cohortId); if (checkData === true) { - const filteredDto = Object.entries(cohortUpdateDto) - .filter(([_, value]) => value !== undefined && value !== '') - .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); - - if (Object.keys(filteredDto).length === 0) { - // If there are no properties to update, return success - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "No fields to update.", - data: { - rowCount: 0, + let updateData = {}; + let fieldValueData = {}; + + // Iterate over all keys in cohortUpdateDto + for (let key in cohortUpdateDto) { + if (cohortUpdateDto.hasOwnProperty(key) && cohortUpdateDto[key] !== null) { + if (key !== 'fieldValues') { + updateData[key] = cohortUpdateDto[key]; + } else { + fieldValueData[key] = cohortUpdateDto[key]; } - }); + } } - const response = await this.cohortRepository.update(cohortId, cohortUpdateDto); + const response = await this.cohortRepository.update(cohortId, updateData); + + + if (fieldValueData['fieldValues']) { - if (cohortUpdateDto.fieldValues) { let field_value_array = cohortUpdateDto.fieldValues.split("|"); if (field_value_array.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { + for (let i = 0; i < field_value_array.length; i++) { let fieldValues = field_value_array[i].split(":"); let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; try { + console.log("hii"); + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) const rowid = fieldVauesRowId.fieldValuesId; @@ -331,6 +334,8 @@ export class PostgresCohortService { }; await this.fieldsService.updateFieldValues(rowid, fieldValueUpdateDto); } catch { + console.log("hii1"); + let fieldValueDto: FieldValuesDto = { value: fieldValues[1] ? fieldValues[1].trim() : "", itemId: cohortId, @@ -340,6 +345,8 @@ export class PostgresCohortService { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; + // console.log(fieldValueDto); + await this.fieldsService.createFieldValues(request, fieldValueDto); } } @@ -348,7 +355,7 @@ export class PostgresCohortService { return new SuccessResponse({ statusCode: HttpStatus.OK, - message: "Ok.", + message: "Cohort updated successfully.", data: { rowCount: response.affected, } diff --git a/src/adapters/postgres/fields-adapter.ts b/src/adapters/postgres/fields-adapter.ts index f0808835..ec08cad8 100644 --- a/src/adapters/postgres/fields-adapter.ts +++ b/src/adapters/postgres/fields-adapter.ts @@ -108,8 +108,11 @@ export class PostgresFieldsService { }); if (checkFieldValueExist.length == 0) { + console.log("fieldValuesDto",fieldValuesDto); let result = await this.fieldsValuesRepository.save(fieldValuesDto); + console.log(result); + return new SuccessResponse({ statusCode: HttpStatus.CREATED, message: "Ok.", diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 05dc3460..14116b02 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -57,7 +57,7 @@ export class CohortController { @ApiOkResponse({ description: "Cohort detais Fetched Succcessfully" }) @ApiNotFoundResponse({ description: "Cohort Not Found" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) - @ApiBadRequestResponse({description:"Bad Request"}) + @ApiBadRequestResponse({ description: "Bad Request" }) @SerializeOptions({ strategy: "excludeAll", }) @ApiHeader({ name: "tenantid", }) public async getCohortsDetails( @@ -78,7 +78,7 @@ export class CohortController { @ApiCreatedResponse({ description: "Cohort has been created successfully." }) @ApiBadRequestResponse({ description: "Bad request." }) @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) - @ApiConflictResponse({description:"Cohort already exists."}) + @ApiConflictResponse({ description: "Cohort already exists." }) @UseInterceptors( FileInterceptor("image", { @@ -102,14 +102,12 @@ export class CohortController { @Res() response: Response ) { // Define expected fields - const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues' ]; + // const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues']; + // const unexpectedFields = Object.keys(cohortCreateDto).filter(field => !expectedFields.includes(field)); + // if (unexpectedFields.length > 0) { + // throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); + // } - // Check if any unexpected fields are present in the request body - const unexpectedFields = Object.keys(cohortCreateDto).filter(field => !expectedFields.includes(field)); - if (unexpectedFields.length > 0) { - throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); - } - let tenantid = headers["tenantid"]; const payload = { image: image?.filename, @@ -180,10 +178,17 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { - const imgresponse = { - image: image?.filename, - }; - Object.assign(cohortUpdateDto, imgresponse); + // const imgresponse = { + // image: image?.filename, + // }; + // Object.assign(cohortUpdateDto, imgresponse); + + // Define expected fields + // const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues']; + // const unexpectedFields = Object.keys(cohortUpdateDto).filter(field => !expectedFields.includes(field)); + // if (unexpectedFields.length > 0) { + // throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); + // } const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( cohortId, diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 06037aa8..1e71de9d 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -30,7 +30,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("Fields") @Controller("fields") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) export class FieldsController { constructor( private fieldsAdapter: FieldsAdapter, From 7a53602ab1420d054262c86e31749b4db1ae9407 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 24 Apr 2024 18:32:37 +0530 Subject: [PATCH 264/408] Fix[Role create API] --- src/adapters/hasura/rbac/role.adapter.ts | 4 +- src/adapters/postgres/rbac/role-adapter.ts | 95 +++++++++++++------ src/adapters/rbacservicelocator.ts | 4 +- .../entities/assign-privilege.entity.ts | 2 +- .../entities/assign-role.entity.ts | 4 +- src/rbac/privilege/privilege.module.ts | 2 +- src/rbac/role/dto/role.dto.ts | 64 ++++++++++++- src/rbac/role/entities/rbac.entity.ts | 12 --- src/rbac/role/entities/role.entity.ts | 29 ++++++ src/rbac/role/role.controller.ts | 8 +- src/rbac/role/role.module.ts | 2 +- 11 files changed, 167 insertions(+), 59 deletions(-) delete mode 100644 src/rbac/role/entities/rbac.entity.ts create mode 100644 src/rbac/role/entities/role.entity.ts diff --git a/src/adapters/hasura/rbac/role.adapter.ts b/src/adapters/hasura/rbac/role.adapter.ts index a3fffc6e..d3df2890 100644 --- a/src/adapters/hasura/rbac/role.adapter.ts +++ b/src/adapters/hasura/rbac/role.adapter.ts @@ -1,13 +1,13 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; -import { RoleDto } from "../../../rbac/role/dto/role.dto"; +import { CreateRolesDto, RoleDto } from "../../../rbac/role/dto/role.dto"; import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; @Injectable() export class HasuraRoleService { constructor(private httpService: HttpService) {} public async getRole(roleId: string, request: any) {} - public async createRole(request: any, roleDto: RoleDto) {} + public async createRole(request: any, createRolesDto: CreateRolesDto){} public async deleteRole(roleId: string) {} public async updateRole(roleId: string, request: any, roleDto: RoleDto) {} public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) {} diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index 4639e711..2df2f362 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -1,8 +1,8 @@ -import { HttpStatus, Injectable } from '@nestjs/common'; -import { Role } from "src/rbac/role/entities/rbac.entity" +import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { Role } from "src/rbac/role/entities/role.entity" import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { RoleDto } from "../../../rbac/role/dto/role.dto"; +import { CreateRolesDto, RoleDto, RolesResponseDto } from "../../../rbac/role/dto/role.dto"; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; @@ -13,32 +13,48 @@ export class PostgresRoleService { @InjectRepository(Role) private roleRepository: Repository ) { } - public async createRole(request: any, roleDto: RoleDto) { + public async createRole(request: any, createRolesDto: CreateRolesDto) { + + const tenant= await this.checkTenantID(createRolesDto.tenantId) + if(!tenant){ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter valid tenantId", + }); } + const roles = []; + const errors = [] try { + // Convert role name to lowercase - const roleNameInLower = roleDto.roleName.toLowerCase(); - - // Check if role name already exists - const existingRole = await this.roleRepository.findOne({ where: { roleName: roleNameInLower } }) - if (existingRole) { - return new SuccessResponse({ - statusCode: HttpStatus.FORBIDDEN, - message: "Role name already exists.", - data: existingRole, - }); - }else{ - // Convert roleDto to lowercase - const roleDtoLowercase = { + for (const roleDto of createRolesDto.roles) { + const tenantId = createRolesDto.tenantId; + const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); + + // Check if role name already exists + const existingRole = await this.roleRepository.findOne({ where: { code } }) + if (existingRole) { + errors.push({ + errorMessage: `Role with the code '${code}' already exists.`, + }); + continue; + } + + const newRoleDto = new RoleDto({ ...roleDto, - roleName: roleNameInLower - }; - - const response = await this.roleRepository.save(roleDtoLowercase); - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Ok.", - data: response, + code, + createdAt: new Date(), + updatedAt: new Date(), + createdBy: request.user.userId, // Assuming you have a user object in the request + updatedBy: request.user.userId, + tenantId, // Add the tenantId to the RoleDto }); + // Convert roleDto to lowercase + // const response = await this.roleRepository.save(roleDto); + const roleEntity = this.roleRepository.create(newRoleDto); + + // Save the role entity to the database + const response = await this.roleRepository.save(roleEntity); + roles.push(new RolesResponseDto(response)); } } catch (e) { return new ErrorResponseTypeOrm({ @@ -46,10 +62,17 @@ export class PostgresRoleService { errorMessage: e, }); } + + return { + statusCode: HttpStatus.OK, + successCount: roles.length, + errorCount: errors.length, + roles, + errors, + }; } public async getRole(roleId: string, request: any) { - try { const [results, totalCount] = await this.roleRepository.findAndCount({ where: { roleId } @@ -70,12 +93,12 @@ export class PostgresRoleService { public async updateRole(roleId: string, request: any, roleDto: RoleDto) { try { - const response = await this.roleRepository.update(roleId,roleDto) + const response = await this.roleRepository.update(roleId, roleDto) return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", data: { - rowCount: response.affected, + rowCount: response.affected, } }); } catch (e) { @@ -88,7 +111,7 @@ export class PostgresRoleService { public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) { try { - + let { limit, page, filters } = roleSearchDto; let offset = 0; @@ -106,7 +129,7 @@ export class PostgresRoleService { whereClause[key] = value; }); } - + const [results, totalCount] = await this.roleRepository.findAndCount({ where: whereClause, skip: offset, @@ -130,7 +153,7 @@ export class PostgresRoleService { public async deleteRole(roleId: string) { try { - let response = await this.roleRepository.delete(roleId) + let response = await this.roleRepository.delete(roleId) return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Role deleted successfully.', @@ -145,6 +168,16 @@ export class PostgresRoleService { }); } } + + + public async checkTenantID(tenantId) { + let query = `SELECT "tenantId" FROM public."Tenants" + where "tenantId"= $1 ` + let response = await this.roleRepository.query(query,[tenantId]); + if(response.length>0){ + return true + } + } } diff --git a/src/adapters/rbacservicelocator.ts b/src/adapters/rbacservicelocator.ts index 636d1f36..3b33f177 100644 --- a/src/adapters/rbacservicelocator.ts +++ b/src/adapters/rbacservicelocator.ts @@ -1,5 +1,5 @@ import { RoleSearchDto } from "../rbac/role/dto/role-search.dto"; -import { RoleDto } from "../rbac/role/dto/role.dto"; +import { CreateRolesDto, RoleDto } from "../rbac/role/dto/role.dto"; export interface IServicelocatorRbac { getRole( @@ -7,7 +7,7 @@ export interface IServicelocatorRbac { request?: any, ); updateRole(id?: string, request?: any, userDto?: any); - createRole(request: any, roleDto: RoleDto); + createRole(request: any, createRolesDto: CreateRolesDto); searchRole(tenantid, request: any, roleSearchDto: RoleSearchDto); deleteRole(roleId); } diff --git a/src/rbac/assign-privilege/entities/assign-privilege.entity.ts b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts index 3b97429c..67e4e030 100644 --- a/src/rbac/assign-privilege/entities/assign-privilege.entity.ts +++ b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts @@ -1,5 +1,5 @@ import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; -import { Role } from 'src/rbac/role/entities/rbac.entity'; +import { Role } from 'src/rbac/role/entities/role.entity'; import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn} from 'typeorm'; @Entity({ name: 'Role_Privilege_Mapping' }) diff --git a/src/rbac/assign-role/entities/assign-role.entity.ts b/src/rbac/assign-role/entities/assign-role.entity.ts index 3c4617dd..a09b0002 100644 --- a/src/rbac/assign-role/entities/assign-role.entity.ts +++ b/src/rbac/assign-role/entities/assign-role.entity.ts @@ -1,6 +1,6 @@ import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn } from 'typeorm'; import { User } from 'src/user/entities/user-entity'; -import { Role } from '../../role/entities/rbac.entity'; +import { Role } from '../../role/entities/role.entity'; @Entity({ name: 'User_Role_Mapping' }) export class UserRoleMapping { @@ -17,7 +17,7 @@ export class UserRoleMapping { @JoinColumn({ name: 'userId' }) user: User; - @ManyToOne(() => Role, role => role.userRoleMappings) + @ManyToOne(() => Role) @JoinColumn({ name: 'roleId' }) role: Role; } diff --git a/src/rbac/privilege/privilege.module.ts b/src/rbac/privilege/privilege.module.ts index 57f848ed..f3b398b8 100644 --- a/src/rbac/privilege/privilege.module.ts +++ b/src/rbac/privilege/privilege.module.ts @@ -10,7 +10,7 @@ import { HasuraPrivilegeService } from 'src/adapters/hasura/rbac/privilege.adapt import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; import { PostgresPrivilegeService } from 'src/adapters/postgres/rbac/privilege-adapter'; import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; -import { Role } from '../role/entities/rbac.entity'; +import { Role } from '../role/entities/role.entity'; @Module({ imports: [ diff --git a/src/rbac/role/dto/role.dto.ts b/src/rbac/role/dto/role.dto.ts index c254a6ff..8de5a913 100644 --- a/src/rbac/role/dto/role.dto.ts +++ b/src/rbac/role/dto/role.dto.ts @@ -1,6 +1,6 @@ -import { Expose } from "class-transformer"; +import { Expose, Type } from "class-transformer"; import { ApiProperty } from "@nestjs/swagger"; -import {IsNotEmpty,IsString, IsUUID} from "class-validator" +import {IsNotEmpty,IsString, IsUUID, ValidateNested, isUUID} from "class-validator" export class RoleDto { @@ -14,9 +14,67 @@ export class RoleDto { }) @Expose() @IsNotEmpty() - roleName: string; + title: string; + + @Expose() + code: string; + + @Expose() + createdAt: Date; + + @Expose() + updatedAt: Date; + + @Expose() + createdBy: string; + + @Expose() + updatedBy: string; + + constructor(obj: any) { Object.assign(this, obj); } } + + +export class CreateRolesDto { + + @ApiProperty({ + type: String, + description: "Tenant" + }) + @Expose() + @IsNotEmpty() + @IsUUID() + tenantId: string; + + + @ValidateNested({ each: true }) + @Type(() => RoleDto) + roles: RoleDto[]; + + constructor(obj: any) { + Object.assign(this, obj); + } +} + + +export class RolesResponseDto { + @Expose() + roleId: string; + + @Expose() + title: string; + + @Expose() + code: string; + + constructor(roleDto: RoleDto) { + this.roleId = roleDto.roleId; + this.title = roleDto.title; + this.code = roleDto.code; + + } +} diff --git a/src/rbac/role/entities/rbac.entity.ts b/src/rbac/role/entities/rbac.entity.ts deleted file mode 100644 index d25dcafa..00000000 --- a/src/rbac/role/entities/rbac.entity.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; - -@Entity({ name: "Role" }) -export class Role { - @PrimaryGeneratedColumn('uuid') - roleId: string; - - @Column() - roleName: string; - userRoleMappings: Role; - privilegeRoleMappings: Role -} diff --git a/src/rbac/role/entities/role.entity.ts b/src/rbac/role/entities/role.entity.ts new file mode 100644 index 00000000..759e53b6 --- /dev/null +++ b/src/rbac/role/entities/role.entity.ts @@ -0,0 +1,29 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne } from 'typeorm'; + +@Entity({ name: "Roles" }) +export class Role { + @PrimaryGeneratedColumn('uuid') + roleId: string; + + @Column({name:"name"}) + title: string; + + @Column() + code: string; + + @Column('uuid') + tenantId: string; + + @CreateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + createdAt: Date; + + @UpdateDateColumn({ type: "timestamp with time zone", default: () => "CURRENT_TIMESTAMP" }) + updatedAt: Date; + + @Column() + createdBy: string; + + @Column() + updatedBy: string; + +} diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index e4e15c4e..e68540c7 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -24,7 +24,7 @@ import { ApiHeader, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; -import { RoleDto } from "./dto/role.dto"; +import { CreateRolesDto, RoleDto } from "./dto/role.dto"; import { RoleSearchDto } from "./dto/role-search.dto"; import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @@ -58,15 +58,15 @@ export class RoleController { @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role has been created successfully." }) - @ApiBody({ type: RoleDto }) + @ApiBody({ type: CreateRolesDto }) @ApiForbiddenResponse({ description: "Forbidden" }) @ApiHeader({ name: "tenantid" }) public async createRole( @Req() request: Request, - @Body() roleDto: RoleDto, + @Body() createRolesDto: CreateRolesDto, @Res() response: Response ) { - const result = await this.roleAdapter.buildRbacAdapter().createRole(request, roleDto); + const result = await this.roleAdapter.buildRbacAdapter().createRole(request, createRolesDto); return response.status(result.statusCode).json(result); } diff --git a/src/rbac/role/role.module.ts b/src/rbac/role/role.module.ts index 63ed2952..68e319dd 100644 --- a/src/rbac/role/role.module.ts +++ b/src/rbac/role/role.module.ts @@ -1,7 +1,7 @@ import {Module } from '@nestjs/common'; import { RoleController } from './role.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { Role } from './entities/rbac.entity'; +import { Role } from './entities/role.entity'; import { HasuraModule } from 'src/adapters/hasura/hasura.module'; import { PostgresModule } from 'src/adapters/postgres/potsgres-module'; import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; From b707134f84b5e632e588652c68707778d94af8db Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 24 Apr 2024 18:38:31 +0530 Subject: [PATCH 265/408] COHORT: Delete API changes --- src/adapters/postgres/cohort-adapter.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 4cbb4524..4aaf3d49 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -230,7 +230,7 @@ export class PostgresCohortService { } else { return new SuccessResponse({ statusCode: HttpStatus.CONFLICT, - message: "Cohort Name already exists.", + message: "Cohort name already exists.", data: existData, }); } @@ -495,6 +495,10 @@ export class PostgresCohortService { request: any ) { try { + const decoded: any = jwt_decode(request.headers.authorization); + // const createdBy = decoded?.sub; + const updatedBy = decoded?.sub + if (!isUUID(cohortId)) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, @@ -502,14 +506,17 @@ export class PostgresCohortService { }); } const checkData = await this.checkAuthAndValidData(cohortId); - const updatedBy = request.user.userId; + if (checkData === true) { let query = `UPDATE public."Cohort" SET "status" = false, "updatedBy" = '${updatedBy}' WHERE "cohortId" = $1`; - const results = await this.cohortRepository.query(query, [cohortId]); + + const result = await this.cohortMembersRepository.delete( + {cohortId:cohortId} + ); return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Cohort Deleted Successfully.", From 02f49c7f9ec9600871e214d3c5b0deb99e2de150 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 24 Apr 2024 18:42:14 +0530 Subject: [PATCH 266/408] COHORT: Delete API changes --- src/adapters/postgres/fields-adapter.ts | 3 --- src/cohort/cohort.controller.ts | 21 +-------------------- src/fields/fields.controller.ts | 2 +- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/src/adapters/postgres/fields-adapter.ts b/src/adapters/postgres/fields-adapter.ts index ec08cad8..f0808835 100644 --- a/src/adapters/postgres/fields-adapter.ts +++ b/src/adapters/postgres/fields-adapter.ts @@ -108,11 +108,8 @@ export class PostgresFieldsService { }); if (checkFieldValueExist.length == 0) { - console.log("fieldValuesDto",fieldValuesDto); let result = await this.fieldsValuesRepository.save(fieldValuesDto); - console.log(result); - return new SuccessResponse({ statusCode: HttpStatus.CREATED, message: "Ok.", diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 14116b02..86b0fb73 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -47,7 +47,7 @@ import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") @Controller("cohorts") -// @UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard) export class CohortController { constructor(private readonly cohortAdapter: CohortAdapter) { } @@ -101,13 +101,6 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { - // Define expected fields - // const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues']; - // const unexpectedFields = Object.keys(cohortCreateDto).filter(field => !expectedFields.includes(field)); - // if (unexpectedFields.length > 0) { - // throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); - // } - let tenantid = headers["tenantid"]; const payload = { image: image?.filename, @@ -178,18 +171,6 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { - // const imgresponse = { - // image: image?.filename, - // }; - // Object.assign(cohortUpdateDto, imgresponse); - - // Define expected fields - // const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues']; - // const unexpectedFields = Object.keys(cohortUpdateDto).filter(field => !expectedFields.includes(field)); - // if (unexpectedFields.length > 0) { - // throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); - // } - const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( cohortId, request, diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 1e71de9d..06037aa8 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -30,7 +30,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("Fields") @Controller("fields") -// @UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard) export class FieldsController { constructor( private fieldsAdapter: FieldsAdapter, From ec1c194982cbc9788e165fecb51e76f357d0f6b3 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 24 Apr 2024 18:49:17 +0530 Subject: [PATCH 267/408] Fix[route name change] --- src/rbac/role/role.controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index e68540c7..6fb2a3f3 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -32,7 +32,7 @@ import { RoleAdapter } from "./roleadapter" @ApiTags("rbac") -@Controller("role") +@Controller("rbac/roles") @UseGuards(JwtAuthGuard) export class RoleController { constructor(private readonly roleAdapter:RoleAdapter) { } @@ -54,7 +54,7 @@ export class RoleController { } //Create role - @Post() + @Post("/create") @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role has been created successfully." }) From 02a498ee659219feea92e6d3831d674203c5c369 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 24 Apr 2024 18:54:36 +0530 Subject: [PATCH 268/408] Fix[Added error handling for checkTenantID method ] --- src/adapters/postgres/rbac/role-adapter.ts | 32 ++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index 2df2f362..e003abec 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -15,12 +15,13 @@ export class PostgresRoleService { ) { } public async createRole(request: any, createRolesDto: CreateRolesDto) { - const tenant= await this.checkTenantID(createRolesDto.tenantId) - if(!tenant){ - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter valid tenantId", - }); } + const tenant = await this.checkTenantID(createRolesDto.tenantId) + if (!tenant) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter valid tenantId", + }); + } const roles = []; const errors = [] try { @@ -54,7 +55,7 @@ export class PostgresRoleService { // Save the role entity to the database const response = await this.roleRepository.save(roleEntity); - roles.push(new RolesResponseDto(response)); + roles.push(new RolesResponseDto(response)); } } catch (e) { return new ErrorResponseTypeOrm({ @@ -171,11 +172,20 @@ export class PostgresRoleService { public async checkTenantID(tenantId) { - let query = `SELECT "tenantId" FROM public."Tenants" + try { + let query = `SELECT "tenantId" FROM public."Tenants" where "tenantId"= $1 ` - let response = await this.roleRepository.query(query,[tenantId]); - if(response.length>0){ - return true + let response = await this.roleRepository.query(query, [tenantId]); + if (response.length > 0) { + return true + } + } + catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } } } From 09abc3fdf7536df766e0a081f29366059e513c53 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 24 Apr 2024 21:23:47 +0530 Subject: [PATCH 269/408] update cohort sattus --- src/adapters/postgres/cohort-adapter.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 4aaf3d49..7da6e53a 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -37,6 +37,8 @@ export class PostgresCohortService { private cohortRepository: Repository, @InjectRepository(CohortMembers) private cohortMembersRepository: Repository, + @InjectRepository(FieldValues) + private fieldValuesRepository: Repository, @InjectRepository(Fields) private fieldsRepository: Repository, private fieldsService: PostgresFieldsService, @@ -285,6 +287,7 @@ export class PostgresCohortService { const decoded: any = jwt_decode(request.headers.authorization); cohortUpdateDto.updatedBy = decoded?.sub cohortUpdateDto.createdBy = decoded?.sub + cohortUpdateDto.status = true; if (!isUUID(cohortId)) { @@ -512,11 +515,16 @@ export class PostgresCohortService { SET "status" = false, "updatedBy" = '${updatedBy}' WHERE "cohortId" = $1`; - const results = await this.cohortRepository.query(query, [cohortId]); + await this.cohortRepository.query(query, [cohortId]); - const result = await this.cohortMembersRepository.delete( + await this.cohortMembersRepository.delete( {cohortId:cohortId} ); + await this.fieldValuesRepository.delete( + {itemId:cohortId} + ); + + return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Cohort Deleted Successfully.", From b02cb787c8a288fde5de0983bbc59c22c3604733 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 25 Apr 2024 12:47:46 +0530 Subject: [PATCH 270/408] Task #217036: Create Assign Privilege API --- src/adapters/assignprivilegelocater.ts | 1 - .../postgres/rbac/privilegerole.adapter.ts | 64 +++++++------------ src/adapters/postgres/user-adapter.ts | 4 +- .../assign-privilege.controller.ts | 22 +++---- .../dto/create-assign-privilege.dto.ts | 14 +++- .../entities/assign-privilege.entity.ts | 37 ++++++----- src/user/user.controller.ts | 2 +- 7 files changed, 69 insertions(+), 75 deletions(-) diff --git a/src/adapters/assignprivilegelocater.ts b/src/adapters/assignprivilegelocater.ts index d71c321a..cf5aca03 100644 --- a/src/adapters/assignprivilegelocater.ts +++ b/src/adapters/assignprivilegelocater.ts @@ -3,5 +3,4 @@ import { CreatePrivilegeRoleDto } from "src/rbac/assign-privilege/dto/create-ass export interface IServicelocatorprivilegeRole { createPrivilegeRole(request: any, createPrivilegeRole:CreatePrivilegeRoleDto); getPrivilegeRole(userId, request); - deletePrivilegeRole(userId); } \ No newline at end of file diff --git a/src/adapters/postgres/rbac/privilegerole.adapter.ts b/src/adapters/postgres/rbac/privilegerole.adapter.ts index d1905278..a6f378e8 100644 --- a/src/adapters/postgres/rbac/privilegerole.adapter.ts +++ b/src/adapters/postgres/rbac/privilegerole.adapter.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Injectable } from '@nestjs/common'; +import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SuccessResponse } from 'src/success-response'; @@ -15,23 +15,21 @@ export class PostgresAssignPrivilegeService { ){} public async createPrivilegeRole(request: Request,createPrivilegeRoleDto:CreatePrivilegeRoleDto){ try { - let findExistingPrivilege = await this.rolePrivilegeMappingRepository.findOne({ - where:{ - privilegeId:createPrivilegeRoleDto?.privilegeId, - roleId:createPrivilegeRoleDto?.roleId - } - }) - if(findExistingPrivilege){ - return new SuccessResponse({ - statusCode: HttpStatus.FORBIDDEN, - message: "Privilege Already Assigned to This Role.", - }); + let result ; + if (createPrivilegeRoleDto.deleteOld) { + await this.deleteByRoleId(createPrivilegeRoleDto.roleId); + } + const privilegeRoles = createPrivilegeRoleDto.privilegeId.map(privilegeId => ({ + roleId: createPrivilegeRoleDto.roleId, + privilegeId + })); + for(let data of privilegeRoles) { + result = await this.rolePrivilegeMappingRepository.save(data) } - let data = await this.rolePrivilegeMappingRepository.save(createPrivilegeRoleDto) return new SuccessResponse({ statusCode: HttpStatus.CREATED, - message: "Ok.", - data: data, + message: "Privileges assigned successfully.", + data: result, }); } catch (error) { if(error.code === '23503'){ @@ -47,6 +45,16 @@ export class PostgresAssignPrivilegeService { } } + public async deleteByRoleId(roleId: string) { + try { + await this.rolePrivilegeMappingRepository.delete({ roleId }); + } catch (error) { + throw error; + } +} +// public async createPrivilegeRole(){ + +// } public async getPrivilegeRole(userId:string,request: Request){ try { if (!isUUID(userId)) { @@ -77,32 +85,6 @@ export class PostgresAssignPrivilegeService { } - public async deletePrivilegeRole(userId){ - try { - let result = await this.checkExistingRole(userId); - if(!result){ - return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'No Role assigned to user', - data: result, - }); - } - let response = await this.rolePrivilegeMappingRepository.delete(userId) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Role deleted successfully.', - data: { - rowCount: response.affected, - } - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } - async checkExistingRole(privilegeId){ const result= await this.rolePrivilegeMappingRepository.findOne({ where: { privilegeId}, diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 273f5745..65f118d6 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -85,7 +85,6 @@ export class PostgresUserService { return results; } - async getUsersDetailsById(userData: Record, response: any) { try { if (!isUUID(userData.userId)) { @@ -343,6 +342,7 @@ export class PostgresUserService { const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) + let checkUserinDb = await this.checkUserinKeyCloakandDb(userCreateDto.username); if (checkUserinKeyCloakandDb) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.FORBIDDEN, @@ -365,7 +365,7 @@ export class PostgresUserService { let field_value_array = userCreateDto.fieldValues?.split("|"); let fieldData = {}; if (result && field_value_array?.length > 0) { - let userId = result.userId; + let userId = result?.userId; for (let i = 0; i < field_value_array?.length; i++) { let fieldValues = field_value_array[i].split(":"); fieldData = { diff --git a/src/rbac/assign-privilege/assign-privilege.controller.ts b/src/rbac/assign-privilege/assign-privilege.controller.ts index 76e60316..b37e0af4 100644 --- a/src/rbac/assign-privilege/assign-privilege.controller.ts +++ b/src/rbac/assign-privilege/assign-privilege.controller.ts @@ -39,16 +39,16 @@ export class AssignPrivilegeController { return response.status(result.statusCode).json(result); } - @Delete("/:id") - @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Assigend Privililege has been deleted successfully." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - public async deletePrivilegeRole( - @Param("id") userId: string, - @Res() response: Response - ) { - const result = await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().deletePrivilegeRole(userId); - return response.status(result.statusCode).json(result); - } + // @Delete("/:id") + // @ApiBasicAuth("access-token") + // @ApiCreatedResponse({ description: "Assigend Privililege has been deleted successfully." }) + // @ApiForbiddenResponse({ description: "Forbidden" }) + // public async deletePrivilegeRole( + // @Param("id") userId: string, + // @Res() response: Response + // ) { + // const result = await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().deletePrivilegeRole(userId); + // return response.status(result.statusCode).json(result); + // } } diff --git a/src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts b/src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts index 878a866a..b05f09c7 100644 --- a/src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts +++ b/src/rbac/assign-privilege/dto/create-assign-privilege.dto.ts @@ -9,8 +9,7 @@ export class CreatePrivilegeRoleDto { default: "", }) @Expose() - @IsUUID() - privilegeId: string; + privilegeId: string[]; @ApiProperty({ type: String, @@ -22,6 +21,17 @@ export class CreatePrivilegeRoleDto { @IsNotEmpty() roleId: string; + @ApiProperty({ + type: String, + description: "Boolean to Delete Previous Privileges", + default: "", + }) + @Expose() + @IsNotEmpty() + deleteOld:boolean; + + + constructor(obj: any) { Object.assign(this, obj); } diff --git a/src/rbac/assign-privilege/entities/assign-privilege.entity.ts b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts index 3b97429c..40054dbe 100644 --- a/src/rbac/assign-privilege/entities/assign-privilege.entity.ts +++ b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts @@ -1,25 +1,28 @@ -import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; -import { Role } from 'src/rbac/role/entities/rbac.entity'; -import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn} from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, BaseEntity } from 'typeorm'; -@Entity({ name: 'Role_Privilege_Mapping' }) -export class RolePrivilegeMapping { - @PrimaryGeneratedColumn('uuid') - Id: string; +@Entity({ name: 'RolePrivilegesMapping' }) +export class RolePrivilegeMapping { + @PrimaryGeneratedColumn('uuid', { name: 'rolePrivilegesId' }) + rolePrivilegesId: string; - @Column('uuid') - roleId: string; + @Column('uuid', { name: 'roleId' }) + roleId: string; - @Column('uuid') - privilegeId: string; + @Column('uuid', { name: 'createdBy', nullable: true }) + createdBy: string | null; - @ManyToOne(() => Privilege) - @JoinColumn({ name: 'privilege' }) - privilege: Privilege; + @Column('uuid', { name: 'updatedBy', nullable: true }) + updatedBy: string | null; - @ManyToOne(() => Role, {nullable:true}) - @JoinColumn({ name: 'roleId' }) - role: Role; + @CreateDateColumn({ name: 'createdAt', type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' }) + createdAt: Date; + + @UpdateDateColumn({ name: 'updatedAt', type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' }) + updatedAt: Date; + + @Column('uuid', { name: 'privilegeId', nullable: true }) + privilegeId: string | null; } + diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 4ddc280f..29ea8a07 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -31,7 +31,6 @@ import { ApiBadRequestResponse, } from "@nestjs/swagger"; -import { UserDto } from "./dto/user.dto"; import { UserSearchDto } from "./dto/user-search.dto"; import { UserAdapter } from "./useradapter"; import { UserCreateDto } from "./dto/user-create.dto"; @@ -41,6 +40,7 @@ import { Response } from "express"; import { isUUID } from "class-validator"; import { SuccessResponse } from "src/success-response"; @ApiTags("User") +@UseGuards(JwtAuthGuard) @Controller("users") export class UserController { constructor( From f64830df9008bd5978400978a7ae07170085eb9f Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Thu, 25 Apr 2024 13:42:13 +0530 Subject: [PATCH 271/408] Privilege:Delete privilege API --- src/adapters/hasura/rbac/privilege.adapter.ts | 16 +- .../postgres/rbac/privilege-adapter.ts | 397 +++++++++--------- src/adapters/privilegeservicelocator.ts | 18 +- .../entities/assign-privilege.entity.ts | 30 +- src/rbac/privilege/privilege.controller.ts | 66 +-- src/rbac/privilege/privilege.module.ts | 42 +- 6 files changed, 299 insertions(+), 270 deletions(-) diff --git a/src/adapters/hasura/rbac/privilege.adapter.ts b/src/adapters/hasura/rbac/privilege.adapter.ts index a42cfa90..29ada0ac 100644 --- a/src/adapters/hasura/rbac/privilege.adapter.ts +++ b/src/adapters/hasura/rbac/privilege.adapter.ts @@ -1,16 +1,20 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; -import { CreatePrivilegesDto, PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; - +import { + CreatePrivilegesDto, + PrivilegeDto, +} from "src/rbac/privilege/dto/privilege.dto"; @Injectable() export class HasuraPrivilegeService { constructor(private httpService: HttpService) {} - public async createPrivilege(loggedinUser: any, createPrivileges: CreatePrivilegesDto){} + public async createPrivilege( + loggedinUser: any, + createPrivileges: CreatePrivilegesDto + ) {} public async getPrivilege(roleId: string, request: any) {} // public async updatePrivilege(privilegeId, request, privilegeDto){} - public async getAllPrivilege(request){} - public async deletePrivilege(privilegeId, request){} - + public async getAllPrivilege(request) {} + public async deletePrivilege(privilegeId) {} } diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index ff03738f..f09db4ed 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -1,204 +1,217 @@ -import { HttpStatus, Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { SuccessResponse } from 'src/success-response'; -import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; -import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; -import { CreatePrivilegesDto, PrivilegeDto, PrivilegeResponseDto } from 'src/rbac/privilege/dto/privilege.dto'; -import { isUUID } from 'class-validator'; +import { HttpStatus, Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; +import { SuccessResponse } from "src/success-response"; +import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; +import { Privilege } from "src/rbac/privilege/entities/privilege.entity"; +import { + CreatePrivilegesDto, + PrivilegeDto, + PrivilegeResponseDto, +} from "src/rbac/privilege/dto/privilege.dto"; +import { isUUID } from "class-validator"; +import { RolePrivilegeMapping } from "src/rbac/assign-privilege/entities/assign-privilege.entity"; @Injectable() export class PostgresPrivilegeService { - constructor( - @InjectRepository(Privilege) - private privilegeRepository: Repository - ) { } - - public async createPrivilege(loggedinUser: any, createPrivilegesDto: CreatePrivilegesDto) { - - const privileges = []; - const errors = [] - try { - - for (const privilegeDto of createPrivilegesDto.privileges) { - const code = privilegeDto.code; - - // Check if privilege with the same label already exists - const existingPrivilege = await this.checkExistingPrivilege(code); - - if (existingPrivilege) { - errors.push({ - errorMessage: `Privilege with the code '${privilegeDto.code}' already exists.`, - }); - continue; // Skip to the next privilege - } - - privilegeDto.createdBy = loggedinUser - privilegeDto.updatedBy = loggedinUser - - - // Create new privilege - const privilege = this.privilegeRepository.create(privilegeDto); - const response = await this.privilegeRepository.save(privilege); - privileges.push(new PrivilegeResponseDto(response)); - } - - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.message || 'Internal server error', - }); + constructor( + @InjectRepository(Privilege) + private privilegeRepository: Repository, + @InjectRepository(RolePrivilegeMapping) + private rolePrivilegeMappingRepository: Repository + ) {} + + public async createPrivilege( + loggedinUser: any, + createPrivilegesDto: CreatePrivilegesDto + ) { + const privileges = []; + const errors = []; + try { + for (const privilegeDto of createPrivilegesDto.privileges) { + const code = privilegeDto.code; + + // Check if privilege with the same label already exists + const existingPrivilege = await this.checkExistingPrivilege(code); + + if (existingPrivilege) { + errors.push({ + errorMessage: `Privilege with the code '${privilegeDto.code}' already exists.`, + }); + continue; // Skip to the next privilege } - return { - statusCode: HttpStatus.OK, - successCount: privileges.length, - errorCount: errors.length, - privileges, - errors, - }; + privilegeDto.createdBy = loggedinUser; + privilegeDto.updatedBy = loggedinUser; + + // Create new privilege + const privilege = this.privilegeRepository.create(privilegeDto); + const response = await this.privilegeRepository.save(privilege); + privileges.push(new PrivilegeResponseDto(response)); + } + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.message || "Internal server error", + }); } - public async checkExistingPrivilege(code) { - try { - const existingPrivilege = await this.privilegeRepository.findOne({ where: { code } }); - return existingPrivilege; - } - catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); - } + return { + statusCode: HttpStatus.OK, + successCount: privileges.length, + errorCount: errors.length, + privileges, + errors, + }; + } + + public async checkExistingPrivilege(code) { + try { + const existingPrivilege = await this.privilegeRepository.findOne({ + where: { code }, + }); + return existingPrivilege; + } catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); } - - public async getPrivilege(privilegeId: string, request: any) { - - try { - - if (!isUUID(privilegeId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid PrivilegeId (UUID)", - }); - } - - const privilege = await this.privilegeRepository.findOne({ where: { privilegeId } }); - if (!privilege) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Privilege not found", - }); - } - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - // totalCount, - data: privilege, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - + } + + public async getPrivilege(privilegeId: string, request: any) { + try { + if (!isUUID(privilegeId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid PrivilegeId (UUID)", + }); + } + + const privilege = await this.privilegeRepository.findOne({ + where: { privilegeId }, + }); + if (!privilege) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Privilege not found", + }); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + // totalCount, + data: privilege, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } - - - - // public async updatePrivilege(privilegeId: string, request: any, privilegeDto: PrivilegeDto) { - // try { - // // Get the privilege using the getPrivilege method - // const existingPrivilegeResponse = await this.getPrivilege(privilegeId, request); - - // if (existingPrivilegeResponse instanceof ErrorResponseTypeOrm) { - // return existingPrivilegeResponse; - // } - - // // Cast the data property of the SuccessResponse to a Privilege object - // const existingPrivilege: Privilege = existingPrivilegeResponse.data as Privilege; - - // const newLabel = privilegeDto.privilegeName.split(' ').join(''); - - - // const result = await this.checkExistingPrivilege(newLabel) - - // if (result) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.CONFLICT, - // errorMessage: "Privilege with the same name already exists.", - // }); - // } - // // Merge the updated data into the existing privilege - // const mergedPrivilege = this.privilegeRepository.merge(existingPrivilege, privilegeDto); - - // mergedPrivilege.label = newLabel; - // // Save the updated privilege record - // const updatedPrivilegeRecord = await this.privilegeRepository.save(mergedPrivilege); - - // return new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: "Privilege updated successfully", - // data: updatedPrivilegeRecord - // }); - // } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: "Internal server error", - // }); - // } - // } - - public async getAllPrivilege(request) { - - try { - const [result, count] = await this.privilegeRepository.findAndCount(); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok", - totalCount: count, - data: result - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: "Internal server error", - }); - } + } + + // public async updatePrivilege(privilegeId: string, request: any, privilegeDto: PrivilegeDto) { + // try { + // // Get the privilege using the getPrivilege method + // const existingPrivilegeResponse = await this.getPrivilege(privilegeId, request); + + // if (existingPrivilegeResponse instanceof ErrorResponseTypeOrm) { + // return existingPrivilegeResponse; + // } + + // // Cast the data property of the SuccessResponse to a Privilege object + // const existingPrivilege: Privilege = existingPrivilegeResponse.data as Privilege; + + // const newLabel = privilegeDto.privilegeName.split(' ').join(''); + + // const result = await this.checkExistingPrivilege(newLabel) + + // if (result) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.CONFLICT, + // errorMessage: "Privilege with the same name already exists.", + // }); + // } + // // Merge the updated data into the existing privilege + // const mergedPrivilege = this.privilegeRepository.merge(existingPrivilege, privilegeDto); + + // mergedPrivilege.label = newLabel; + // // Save the updated privilege record + // const updatedPrivilegeRecord = await this.privilegeRepository.save(mergedPrivilege); + + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: "Privilege updated successfully", + // data: updatedPrivilegeRecord + // }); + // } catch (e) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: "Internal server error", + // }); + // } + // } + + public async getAllPrivilege(request) { + try { + const [result, count] = await this.privilegeRepository.findAndCount(); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok", + totalCount: count, + data: result, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: "Internal server error", + }); } - - - public async deletePrivilege(privilegeId, request) { - - try { - - const existingPrivilegeResponse = await this.getPrivilege(privilegeId, request); - - if (existingPrivilegeResponse instanceof ErrorResponseTypeOrm) { - return existingPrivilegeResponse; - } - const result = await this.privilegeRepository.delete(privilegeId); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Privilege Deleted successfully", - data: { - affectedRows: result // Return the number of affected rows - } - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: "Internal server error", - }); - } + } + + public async deletePrivilege(privilegeId: string) { + try { + if (!isUUID(privilegeId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid (UUID)", + }); + } + + const privilegeToDelete = await this.privilegeRepository.findOne({ + where: { privilegeId: privilegeId }, + }); + if (!privilegeToDelete) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Privilege not found", + }); + } + // Delete the privilege + const response = await this.privilegeRepository.delete(privilegeId); + + // Delete entries from RolePrivilegesMapping table associated with the privilegeId + const rolePrivilegesDeleteResponse = + await this.rolePrivilegeMappingRepository.delete({ + privilegeId: privilegeId, + }); + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Privilege deleted successfully.", + data: { + rowCount: response.affected, + }, + }); + } catch (e) { + console.log(e); + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: "Internal server error", + }); } - + } } - - - - diff --git a/src/adapters/privilegeservicelocator.ts b/src/adapters/privilegeservicelocator.ts index 441dc6ed..0a4e7b12 100644 --- a/src/adapters/privilegeservicelocator.ts +++ b/src/adapters/privilegeservicelocator.ts @@ -1,12 +1,12 @@ -import { CreatePrivilegesDto, PrivilegeDto } from "src/rbac/privilege/dto/privilege.dto"; +import { + CreatePrivilegesDto, + PrivilegeDto, +} from "src/rbac/privilege/dto/privilege.dto"; export interface IServicelocator { - createPrivilege(loggedinUser: any, createPrivileges: CreatePrivilegesDto); - getPrivilege( - privilegeId?: string, - request?: any, - ); - // updatePrivilege(privilegeId, request, privilegeDto) - getAllPrivilege(request) - deletePrivilege(privilegeId, request) + createPrivilege(loggedinUser: any, createPrivileges: CreatePrivilegesDto); + getPrivilege(privilegeId?: string, request?: any); + // updatePrivilege(privilegeId, request, privilegeDto) + getAllPrivilege(request); + deletePrivilege(privilegeId); } diff --git a/src/rbac/assign-privilege/entities/assign-privilege.entity.ts b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts index 67e4e030..04553f13 100644 --- a/src/rbac/assign-privilege/entities/assign-privilege.entity.ts +++ b/src/rbac/assign-privilege/entities/assign-privilege.entity.ts @@ -1,25 +1,29 @@ -import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; -import { Role } from 'src/rbac/role/entities/role.entity'; -import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn} from 'typeorm'; +import { Privilege } from "src/rbac/privilege/entities/privilege.entity"; +import { Role } from "src/rbac/role/entities/role.entity"; +import { + Entity, + PrimaryGeneratedColumn, + Column, + ManyToOne, + JoinColumn, +} from "typeorm"; -@Entity({ name: 'Role_Privilege_Mapping' }) -export class RolePrivilegeMapping { - @PrimaryGeneratedColumn('uuid') +@Entity({ name: "RolePrivilegesMapping" }) +export class RolePrivilegeMapping { + @PrimaryGeneratedColumn("uuid") Id: string; - @Column('uuid') + @Column("uuid") roleId: string; - @Column('uuid') + @Column("uuid") privilegeId: string; @ManyToOne(() => Privilege) - @JoinColumn({ name: 'privilege' }) + @JoinColumn({ name: "privilege" }) privilege: Privilege; - @ManyToOne(() => Role, {nullable:true}) - @JoinColumn({ name: 'roleId' }) + @ManyToOne(() => Role, { nullable: true }) + @JoinColumn({ name: "roleId" }) role: Role; } - - diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index ea0a1106..b3dc62e6 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -1,5 +1,5 @@ -import { CreatePrivilegesDto, PrivilegeDto } from './dto/privilege.dto'; -import { UpdatePrivilegeDto } from './dto/update-privilege.dto'; +import { CreatePrivilegesDto, PrivilegeDto } from "./dto/privilege.dto"; +import { UpdatePrivilegeDto } from "./dto/update-privilege.dto"; import { Controller, Get, @@ -27,17 +27,17 @@ import { ApiBadRequestResponse, ApiInternalServerErrorResponse, ApiConflictResponse, + ApiNotFoundResponse, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; -import { PrivilegeAdapter } from './privilegeadapter'; -import { v4 as uuidv4 } from 'uuid'; - +import { PrivilegeAdapter } from "./privilegeadapter"; +import { v4 as uuidv4 } from "uuid"; @UseGuards(JwtAuthGuard) @ApiTags("rbac") -@Controller('privilege') +@Controller("privilege") export class PrivilegeController { constructor(private readonly privilegeAdapter: PrivilegeAdapter) {} @@ -47,23 +47,24 @@ export class PrivilegeController { @ApiBadRequestResponse({ description: "Bad Request" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @ApiHeader({ name: "tenantid" }) - @SerializeOptions({strategy: "excludeAll",}) + @SerializeOptions({ strategy: "excludeAll" }) public async getPrivilege( @Param("privilegeId") privilegeId: string, @Req() request: Request, @Res() response: Response ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().getPrivilege(privilegeId, request); + const result = await this.privilegeAdapter + .buildPrivilegeAdapter() + .getPrivilege(privilegeId, request); return response.status(result.statusCode).json(result); } - - - @Post() @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Privilege has been created successfully." }) + @ApiCreatedResponse({ + description: "Privilege has been created successfully.", + }) @ApiBadRequestResponse({ description: "Bad Request" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) @ApiConflictResponse({ description: "Privilege Already Exists" }) @@ -74,11 +75,11 @@ export class PrivilegeController { @Body() createPrivilegesDto: CreatePrivilegesDto, @Res() response: Response ) { - - const result=await this.privilegeAdapter.buildPrivilegeAdapter().createPrivilege(request.user.userId, createPrivilegesDto); + const result = await this.privilegeAdapter + .buildPrivilegeAdapter() + .createPrivilege(request.user.userId, createPrivilegesDto); return response.status(result.statusCode).json(result); - } - + } // @Put("/:id") // @ApiBasicAuth("access-token") @@ -97,7 +98,7 @@ export class PrivilegeController { // ) { // const result = await this.privilegeAdapter.buildPrivilegeAdapter().updatePrivilege(privilegeId, request, privilegeDto); // return response.status(result.statusCode).json(result); - // } + // } @Get() @ApiBasicAuth("access-token") @@ -106,28 +107,31 @@ export class PrivilegeController { @ApiOkResponse({ description: "Privileges List" }) @ApiBadRequestResponse({ description: "Bad Request" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) - @SerializeOptions({strategy: "excludeAll",}) + @SerializeOptions({ strategy: "excludeAll" }) public async getAllPrivilege( @Req() request: Request, @Res() response: Response ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().getAllPrivilege(request); + const result = await this.privilegeAdapter + .buildPrivilegeAdapter() + .getAllPrivilege(request); return response.status(result.statusCode).json(result); } - - @Delete("/:id") + + //delete + @Delete("/:privilegeId") @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Privilege Deleted" }) - @ApiBadRequestResponse({ description: "Bad Request" }) - @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) - @ApiHeader({ name: "tenantid", }) - public async deletePrivilege( - @Param("id") privilegeId: string, - @Req() request: Request, + @ApiHeader({ name: "tenantid" }) + @ApiOkResponse({ description: "Role deleted successfully." }) + @ApiNotFoundResponse({ description: "Data not found" }) + @ApiBadRequestResponse({ description: "Bad request" }) + public async deleteRole( + @Param("privilegeId") privilegeId: string, @Res() response: Response ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().deletePrivilege(privilegeId, request); + const result = await this.privilegeAdapter + .buildPrivilegeAdapter() + .deletePrivilege(privilegeId); return response.status(result.statusCode).json(result); - } - + } } diff --git a/src/rbac/privilege/privilege.module.ts b/src/rbac/privilege/privilege.module.ts index f3b398b8..288308fa 100644 --- a/src/rbac/privilege/privilege.module.ts +++ b/src/rbac/privilege/privilege.module.ts @@ -1,28 +1,32 @@ -import { Module } from '@nestjs/common'; -import { PrivilegeController } from './privilege.controller'; -import { Privilege } from './entities/privilege.entity'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { HttpModule } from '@nestjs/axios'; -import { PostgresModule } from 'src/adapters/postgres/potsgres-module'; -import { HasuraModule } from 'src/adapters/hasura/hasura.module'; -import { PrivilegeAdapter } from './privilegeadapter'; -import { HasuraPrivilegeService } from 'src/adapters/hasura/rbac/privilege.adapter'; -import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; -import { PostgresPrivilegeService } from 'src/adapters/postgres/rbac/privilege-adapter'; -import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; -import { Role } from '../role/entities/role.entity'; +import { Module } from "@nestjs/common"; +import { PrivilegeController } from "./privilege.controller"; +import { Privilege } from "./entities/privilege.entity"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { HttpModule } from "@nestjs/axios"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; +import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { PrivilegeAdapter } from "./privilegeadapter"; +import { HasuraPrivilegeService } from "src/adapters/hasura/rbac/privilege.adapter"; +import { PostgresRoleService } from "src/adapters/postgres/rbac/role-adapter"; +import { PostgresPrivilegeService } from "src/adapters/postgres/rbac/privilege-adapter"; +import { HasuraRoleService } from "src/adapters/hasura/rbac/role.adapter"; +import { Role } from "../role/entities/role.entity"; +import { RolePrivilegeMapping } from "../assign-privilege/entities/assign-privilege.entity"; @Module({ imports: [ - TypeOrmModule.forFeature([Privilege,Role]), + TypeOrmModule.forFeature([Privilege, Role, RolePrivilegeMapping]), HttpModule, PostgresModule, - HasuraModule + HasuraModule, ], controllers: [PrivilegeController], - providers: [PrivilegeAdapter,HasuraPrivilegeService,PostgresPrivilegeService,HasuraRoleService,PostgresRoleService] + providers: [ + PrivilegeAdapter, + HasuraPrivilegeService, + PostgresPrivilegeService, + HasuraRoleService, + PostgresRoleService, + ], }) export class PrivilegeModule {} - - - From e1385050266a99ef0e99bae4bb725a34152d0a7c Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 25 Apr 2024 16:48:46 +0530 Subject: [PATCH 272/408] Fix[API to get list of privileges for a role of a tenant , swagger changes for Privilege create and role create API] --- src/adapters/hasura/rbac/privilege.adapter.ts | 1 + .../postgres/rbac/privilege-adapter.ts | 76 ++++++++++++++++++- src/adapters/privilegeservicelocator.ts | 2 +- src/rbac/privilege/dto/privilege.dto.ts | 1 + src/rbac/privilege/privilege.controller.ts | 52 ++++++++----- src/rbac/privilege/privilege.module.ts | 3 +- src/rbac/role/dto/role.dto.ts | 7 +- 7 files changed, 116 insertions(+), 26 deletions(-) diff --git a/src/adapters/hasura/rbac/privilege.adapter.ts b/src/adapters/hasura/rbac/privilege.adapter.ts index a42cfa90..8dc5e452 100644 --- a/src/adapters/hasura/rbac/privilege.adapter.ts +++ b/src/adapters/hasura/rbac/privilege.adapter.ts @@ -12,5 +12,6 @@ export class HasuraPrivilegeService { // public async updatePrivilege(privilegeId, request, privilegeDto){} public async getAllPrivilege(request){} public async deletePrivilege(privilegeId, request){} + public async getPrivilegebyRoleId(tenantId, roleId,request){} } diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index ff03738f..fd04b6b4 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -6,12 +6,16 @@ import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { Privilege } from 'src/rbac/privilege/entities/privilege.entity'; import { CreatePrivilegesDto, PrivilegeDto, PrivilegeResponseDto } from 'src/rbac/privilege/dto/privilege.dto'; import { isUUID } from 'class-validator'; +import { Role } from 'src/rbac/role/entities/role.entity'; @Injectable() export class PostgresPrivilegeService { constructor( @InjectRepository(Privilege) - private privilegeRepository: Repository + private privilegeRepository: Repository, + @InjectRepository(Role) + private roleRepository: Repository + ) { } public async createPrivilege(loggedinUser: any, createPrivilegesDto: CreatePrivilegesDto) { @@ -40,7 +44,7 @@ export class PostgresPrivilegeService { // Create new privilege const privilege = this.privilegeRepository.create(privilegeDto); const response = await this.privilegeRepository.save(privilege); - privileges.push(new PrivilegeResponseDto(response)); + privileges.push(new PrivilegeResponseDto(response)); } } catch (e) { @@ -197,6 +201,74 @@ export class PostgresPrivilegeService { } } + public async getPrivilegebyRoleId(tenantId, roleId, request) { + + if (!isUUID(tenantId) || !isUUID(roleId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid tenantId and roleId (UUID)", + }); + } + + try { + const valid = await this.checkValidTenantIdRoleIdCombination(tenantId, roleId) + + if (!valid) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Invalid combination of roleId and tenantId", + }); + } + + let query = `SELECT r.*, u.* + FROM public."RolePrivilegesMapping" AS r + inner JOIN public."Privileges" AS u ON r."privilegeId" = u."privilegeId" + where r."roleId"=$1` + + const result = await this.privilegeRepository.query(query, [roleId]); + const privilegeResponseArray: PrivilegeResponseDto[] = result.map((item: any) => { + const privilegeDto = new PrivilegeDto(item); + privilegeDto.title = item.name + return new PrivilegeResponseDto(privilegeDto); + }); + + if (!privilegeResponseArray.length) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "No privileges assigned to the role", + }); + } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok", + data: privilegeResponseArray + }); + } + catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + + + } + + public async checkValidTenantIdRoleIdCombination(tenantId, roleId) { + try { + + const ValidTenantIdRoleCombination = await this.roleRepository.findOne({ where: { tenantId: tenantId, roleId: roleId } }); + return ValidTenantIdRoleCombination; + } + catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + } + } diff --git a/src/adapters/privilegeservicelocator.ts b/src/adapters/privilegeservicelocator.ts index 441dc6ed..ea41e004 100644 --- a/src/adapters/privilegeservicelocator.ts +++ b/src/adapters/privilegeservicelocator.ts @@ -9,4 +9,4 @@ export interface IServicelocator { // updatePrivilege(privilegeId, request, privilegeDto) getAllPrivilege(request) deletePrivilege(privilegeId, request) -} + getPrivilegebyRoleId(tenantId, roleId,request)} diff --git a/src/rbac/privilege/dto/privilege.dto.ts b/src/rbac/privilege/dto/privilege.dto.ts index ba5052c2..3db03d8d 100644 --- a/src/rbac/privilege/dto/privilege.dto.ts +++ b/src/rbac/privilege/dto/privilege.dto.ts @@ -45,6 +45,7 @@ export class PrivilegeDto { export class CreatePrivilegesDto { + @ApiProperty({type:[PrivilegeDto]}) @ValidateNested({ each: true }) @Type(() => PrivilegeDto) privileges: PrivilegeDto[]; diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index ea0a1106..21bb1c58 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -15,6 +15,7 @@ import { Headers, Delete, UseGuards, + Query, } from "@nestjs/common"; import { ApiTags, @@ -37,10 +38,27 @@ import { v4 as uuidv4 } from 'uuid'; @UseGuards(JwtAuthGuard) @ApiTags("rbac") -@Controller('privilege') +@Controller('rbac/privileges') export class PrivilegeController { constructor(private readonly privilegeAdapter: PrivilegeAdapter) {} + @Get() + @ApiBasicAuth("access-token") + @ApiOkResponse({ description: "Privilege Detail." }) + @ApiBadRequestResponse({ description: "Bad Request" }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) + @SerializeOptions({strategy: "excludeAll",}) + public async getPrivilegebyRoleId( + @Query("tenantId") tenantId: string, + @Query("roleId") roleId: string, + @Req() request: Request, + @Res() response: Response + ) { + const result = await this.privilegeAdapter.buildPrivilegeAdapter().getPrivilegebyRoleId(tenantId, roleId,request); + return response.status(result.statusCode).json(result); + } + + @Get("/:privilegeId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Privilege Detail." }) @@ -60,7 +78,7 @@ export class PrivilegeController { - @Post() + @Post("/create") @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Privilege has been created successfully." }) @@ -99,21 +117,21 @@ export class PrivilegeController { // return response.status(result.statusCode).json(result); // } - @Get() - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Privilege Detail." }) - @ApiHeader({ name: "tenantid" }) - @ApiOkResponse({ description: "Privileges List" }) - @ApiBadRequestResponse({ description: "Bad Request" }) - @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) - @SerializeOptions({strategy: "excludeAll",}) - public async getAllPrivilege( - @Req() request: Request, - @Res() response: Response - ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().getAllPrivilege(request); - return response.status(result.statusCode).json(result); - } + // @Get() + // @ApiBasicAuth("access-token") + // @ApiOkResponse({ description: "Privilege Detail." }) + // @ApiHeader({ name: "tenantid" }) + // @ApiOkResponse({ description: "Privileges List" }) + // @ApiBadRequestResponse({ description: "Bad Request" }) + // @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) + // @SerializeOptions({strategy: "excludeAll",}) + // public async getAllPrivilege( + // @Req() request: Request, + // @Res() response: Response + // ) { + // const result = await this.privilegeAdapter.buildPrivilegeAdapter().getAllPrivilege(request); + // return response.status(result.statusCode).json(result); + // } @Delete("/:id") @ApiBasicAuth("access-token") diff --git a/src/rbac/privilege/privilege.module.ts b/src/rbac/privilege/privilege.module.ts index f3b398b8..2e0605a1 100644 --- a/src/rbac/privilege/privilege.module.ts +++ b/src/rbac/privilege/privilege.module.ts @@ -11,6 +11,7 @@ import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; import { PostgresPrivilegeService } from 'src/adapters/postgres/rbac/privilege-adapter'; import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; import { Role } from '../role/entities/role.entity'; +import { Repository } from 'typeorm'; @Module({ imports: [ @@ -20,7 +21,7 @@ import { Role } from '../role/entities/role.entity'; HasuraModule ], controllers: [PrivilegeController], - providers: [PrivilegeAdapter,HasuraPrivilegeService,PostgresPrivilegeService,HasuraRoleService,PostgresRoleService] + providers: [PrivilegeAdapter,HasuraPrivilegeService,PostgresPrivilegeService,HasuraRoleService,PostgresRoleService,Repository] }) export class PrivilegeModule {} diff --git a/src/rbac/role/dto/role.dto.ts b/src/rbac/role/dto/role.dto.ts index 8de5a913..33e9ec30 100644 --- a/src/rbac/role/dto/role.dto.ts +++ b/src/rbac/role/dto/role.dto.ts @@ -7,11 +7,7 @@ export class RoleDto { @Expose() roleId: string; - @ApiProperty({ - type: String, - description: "The name of the role", - default: "", - }) + @ApiProperty() @Expose() @IsNotEmpty() title: string; @@ -51,6 +47,7 @@ export class CreateRolesDto { tenantId: string; + @ApiProperty( {type: [RoleDto]} ) @ValidateNested({ each: true }) @Type(() => RoleDto) roles: RoleDto[]; From efa3803be3803e74825a994628d457ffbb452dd1 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 25 Apr 2024 16:49:34 +0530 Subject: [PATCH 273/408] Fix[role dto changes] --- src/rbac/role/dto/role.dto.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rbac/role/dto/role.dto.ts b/src/rbac/role/dto/role.dto.ts index 33e9ec30..25902d32 100644 --- a/src/rbac/role/dto/role.dto.ts +++ b/src/rbac/role/dto/role.dto.ts @@ -7,7 +7,11 @@ export class RoleDto { @Expose() roleId: string; - @ApiProperty() + @ApiProperty({ + type: String, + description: "The name of the role", + default: "", + }) @Expose() @IsNotEmpty() title: string; From 1783fd061d6b3f5122e37b45c8f637efc280a04e Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 25 Apr 2024 17:16:13 +0530 Subject: [PATCH 274/408] Fix[changes suggested by bot] --- src/adapters/privilegeservicelocator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/privilegeservicelocator.ts b/src/adapters/privilegeservicelocator.ts index 6c188113..d36fa01c 100644 --- a/src/adapters/privilegeservicelocator.ts +++ b/src/adapters/privilegeservicelocator.ts @@ -10,8 +10,8 @@ export interface IServicelocator { request?: any, ); // updatePrivilege(privilegeId, request, privilegeDto) - getAllPrivilege(request) - getPrivilegebyRoleId(tenantId, roleId,request) + getAllPrivilege(request:any) + getPrivilegebyRoleId(tenantId:string, roleId:string,request:any) // updatePrivilege(privilegeId, request, privilegeDto) deletePrivilege(privilegeId); } From e95d67cd9fc5bd680b368794ad1f05fcc203aa0d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 25 Apr 2024 21:01:08 +0530 Subject: [PATCH 275/408] Assign Role: assign roles to a user in a tenant --- .../postgres/rbac/assignrole-adapter.ts | 241 +++++++++++------- src/adapters/postgres/rbac/role-adapter.ts | 4 +- .../assign-role/assign-role.controller.ts | 28 +- src/rbac/assign-role/assign-role.module.ts | 3 +- .../assign-role/dto/create-assign-role.dto.ts | 48 +++- .../entities/assign-role.entity.ts | 27 +- 6 files changed, 236 insertions(+), 115 deletions(-) diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts index 85e4e41a..9dd7d308 100644 --- a/src/adapters/postgres/rbac/assignrole-adapter.ts +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -3,120 +3,175 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; -import { CreateAssignRoleDto } from 'src/rbac/assign-role/dto/create-assign-role.dto'; +import { CreateAssignRoleDto, ResponseAssignRoleDto } from 'src/rbac/assign-role/dto/create-assign-role.dto'; import { UserRoleMapping } from 'src/rbac/assign-role/entities/assign-role.entity'; +import { Role } from "src/rbac/role/entities/role.entity"; import { IsAlpha, IsUUID, isUUID } from 'class-validator'; import { executionAsyncResource } from 'async_hooks'; +import jwt_decode from "jwt-decode"; + @Injectable() export class PostgresAssignroleService { - constructor( - @InjectRepository(UserRoleMapping) - private userRoleMappingRepository: Repository - ){} - public async createAssignRole(request: Request,createAssignRoleDto:CreateAssignRoleDto){ - try { - let findExistingRole = await this.userRoleMappingRepository.findOne({ - where:{ - userId:createAssignRoleDto?.userId, - roleId:createAssignRoleDto?.roleId + constructor( + @InjectRepository(UserRoleMapping) + private userRoleMappingRepository: Repository, + @InjectRepository(Role) + private roleRepository: Repository + ) { } + public async createAssignRole(request: Request, createAssignRoleDto: CreateAssignRoleDto) { + try { + // const decoded: any = jwt_decode(request.headers.authorization); + const userId = createAssignRoleDto.userId; + const roles = createAssignRoleDto.roleId; + const tenantId = createAssignRoleDto.tenantId; + + // Check if roles array is not empty + if (!roles || roles.length === 0) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: "Roles array cannot be empty.", + }); + } + let result = []; + let errors = []; + + for (const roleId of roles) { + // If role already exists for user, return error response + let findExistingRole = await this.userRoleMappingRepository.findOne({ + where: { + userId: userId, + roleId: roleId, + }, + }); + if (findExistingRole) { + errors.push({ + errorMessage: `Role ${roleId} is already assigned to this user.`, + }); + continue; + } + + //Rele is belong for this tenent + let roleExistforTenant = await this.roleRepository.findOne({ + where: { + roleId: roleId, + tenantId: tenantId, + }, + }); + if (!roleExistforTenant) { + errors.push({ + errorMessage: `Role ${roleId} is not exist for this tenant.`, + }); + continue; + } + + const data = await this.userRoleMappingRepository.save({ + userId: userId, + roleId: roleId, + tenantId: tenantId, + createdBy: request['user'].userId, + updatedBy: request['user'].userId + }) + result.push(new ResponseAssignRoleDto(data, `Role assigned successfully to the user in the specified tenant.`)); + } + + if (result.length == 0) { + return { + statusCode: HttpStatus.BAD_REQUEST, + errorCount: errors.length, + errors, + }; + } + return { + statusCode: HttpStatus.CREATED, + successCount: result.length, + errorCount: errors.length, + data: result, + errors, + }; + } catch (error) { + if (error.code === '23503') { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: `User Id or Role Id Doesn't Exist in Database ` + }); } - }) - if(findExistingRole){ - return new SuccessResponse({ - statusCode: HttpStatus.FORBIDDEN, - message: "Role Already Assigned to This User.", - }); - } - let data = await this.userRoleMappingRepository.save(createAssignRoleDto) - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Ok.", - data: data, - }); - } catch (error) { - if(error.code === '23503'){ return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: `User Id or Role Id Doesn't Exist in Database ` - }); + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: JSON.stringify(error) + }); } - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: JSON.stringify(error) - }); } - } - public async getAssignedRole(userId:string,request: Request){ - try { - if (!isUUID(userId)) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: 'Please Enter Valid User ID', - }); - } - let result = await this.checkExistingRole(userId); - if(!result){ + public async getAssignedRole(userId: string, request: Request) { + try { + if (!isUUID(userId)) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'Please Enter Valid User ID', + }); + } + let result = await this.checkExistingRole(userId); + if (!result) { + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'No Role assigned to user', + data: result, + }); + } return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'No Role assigned to user', + statusCode: HttpStatus.OK, + message: 'Ok.', data: result, }); + } catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: result, - }); - } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); + } - - } - public async deleteAssignedRole(userId){ - try { - let result = await this.checkExistingRole(userId); - if(!result){ + public async deleteAssignedRole(userId) { + try { + let result = await this.checkExistingRole(userId); + if (!result) { + return new SuccessResponse({ + statusCode: HttpStatus.NOT_FOUND, + message: 'No Role assigned to user', + data: result, + }); + } + let response = await this.userRoleMappingRepository.delete(userId) return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'No Role assigned to user', - data: result, + statusCode: HttpStatus.OK, + message: 'Role deleted successfully.', + data: { + rowCount: response.affected, + } + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, }); } - let response = await this.userRoleMappingRepository.delete(userId) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Role deleted successfully.', - data: { - rowCount: response.affected, - } - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); } - } -// async checkAndAddUserRole(data){ -// let existingUser = await this.checkExistingRole(data.userId) ; -// if(existingUser){ -// let update = -// } -// } + // async checkAndAddUserRole(data){ + // let existingUser = await this.checkExistingRole(data.userId) ; + // if(existingUser){ + // let update = + // } + // } - async checkExistingRole(userId){ - const result= await this.userRoleMappingRepository.findOne({ - where: { userId }, - relations:['user'] - }) - return result; - } + async checkExistingRole(userId) { + const result = await this.userRoleMappingRepository.findOne({ + where: { userId }, + relations: ['user'] + }) + return result; + } -} \ No newline at end of file +} diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index e003abec..3e7da09a 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -32,10 +32,10 @@ export class PostgresRoleService { const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); // Check if role name already exists - const existingRole = await this.roleRepository.findOne({ where: { code } }) + const existingRole = await this.roleRepository.findOne({ where: { code:code,tenantId:tenantId } }) if (existingRole) { errors.push({ - errorMessage: `Role with the code '${code}' already exists.`, + errorMessage: `Combination of this tenantId and the code '${code}' already exists.`, }); continue; } diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index a6557dab..55bfbd05 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -1,26 +1,38 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions } from '@nestjs/common'; +import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions, Headers, UseGuards } from '@nestjs/common'; import { AssignRoleAdapter } from './assign-role.apater'; import { CreateAssignRoleDto } from './dto/create-assign-role.dto'; import { Response, Request } from "express"; -import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger'; +import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags, ApiBadRequestResponse, ApiInternalServerErrorResponse, ApiConflictResponse } from '@nestjs/swagger'; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; + + -@Controller('assignrole') @ApiTags('rbac') +@Controller('rbac/usersRoles') +@UseGuards(JwtAuthGuard) export class AssignRoleController { constructor(private readonly assignRoleAdpater: AssignRoleAdapter) {} @Post() @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Role has been Assigned successfully." }) + + @ApiCreatedResponse({ description: "Role assigned successfully to the user in the specified tenant." }) + @ApiBadRequestResponse({ description: "Bad request." }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) + @ApiConflictResponse({description:"Role is already assigned to this user."}) + @ApiBody({ type: CreateAssignRoleDto }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiHeader({ name: "tenantid" }) - public async create(@Req() request: Request, + // @ApiHeader({ name: "tenantid" }) + public async create( + @Req() request: Request, @Body() createAssignRoleDto:CreateAssignRoleDto , - @Res() response: Response) { + @Res() response: Response, + @Headers() headers, + ) { + const result = await this.assignRoleAdpater.buildassignroleAdapter().createAssignRole(request,createAssignRoleDto); return response.status(result.statusCode).json(result); } diff --git a/src/rbac/assign-role/assign-role.module.ts b/src/rbac/assign-role/assign-role.module.ts index 06f521bd..04ce19e2 100644 --- a/src/rbac/assign-role/assign-role.module.ts +++ b/src/rbac/assign-role/assign-role.module.ts @@ -3,12 +3,13 @@ import { AssignRoleAdapter } from './assign-role.apater'; import { AssignRoleController } from './assign-role.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UserRoleMapping } from './entities/assign-role.entity'; +import { Role } from "src/rbac/role/entities/role.entity"; import { PostgresAssignroleService } from 'src/adapters/postgres/rbac/assignrole-adapter'; import { HasuraAssignRoleService } from 'src/adapters/hasura/rbac/assignrole.adapter'; import { HttpModule } from '@nestjs/axios'; @Module({ - imports:[TypeOrmModule.forFeature([UserRoleMapping]),HttpModule], + imports:[TypeOrmModule.forFeature([UserRoleMapping,Role]),HttpModule], controllers: [AssignRoleController], providers: [AssignRoleAdapter,HasuraAssignRoleService,PostgresAssignroleService] }) diff --git a/src/rbac/assign-role/dto/create-assign-role.dto.ts b/src/rbac/assign-role/dto/create-assign-role.dto.ts index a11c4d06..be516b76 100644 --- a/src/rbac/assign-role/dto/create-assign-role.dto.ts +++ b/src/rbac/assign-role/dto/create-assign-role.dto.ts @@ -1,29 +1,61 @@ -// export class CreatePrivilegeDto {} import { Expose } from "class-transformer"; import { ApiProperty } from "@nestjs/swagger"; -import {IsNotEmpty,IsString, IsUUID} from "class-validator" +import { IsNotEmpty, IsString, IsUUID, IsArray } from "class-validator"; export class CreateAssignRoleDto { - @ApiProperty({ + @ApiProperty({ type: String, - description: "User Id of User", + description: "Tenant Id", default: "", }) @Expose() @IsUUID() - userId: string; + tenantId: string; @ApiProperty({ type: String, - description: "Assigned Role Id", + description: "User Id of User", default: "", }) @Expose() @IsUUID() - @IsNotEmpty() - roleId: string; + userId: string; + + @ApiProperty({ + type: [String], + description: "Assigned Role Ids", + default: [], + }) + @Expose() + @IsArray() + @IsUUID(undefined, { each: true }) // Validate each item in the array to be a UUID + @IsNotEmpty({ each: true }) // Ensure each item in the array is not empty + roleId: string[]; constructor(obj: any) { Object.assign(this, obj); } + +} + +export class ResponseAssignRoleDto { + @Expose() + userId: string; + + @Expose() + roleId: string; + + @Expose() + tenantId: string; + + @Expose() + message: string; + + constructor(data: { userId: string; roleId: string; tenantId: string }, message: string) { + this.userId = data.userId; + this.roleId = data.roleId; + this.tenantId = data.tenantId; + this.message = message; + } } + diff --git a/src/rbac/assign-role/entities/assign-role.entity.ts b/src/rbac/assign-role/entities/assign-role.entity.ts index a09b0002..9bac1d39 100644 --- a/src/rbac/assign-role/entities/assign-role.entity.ts +++ b/src/rbac/assign-role/entities/assign-role.entity.ts @@ -1,11 +1,11 @@ -import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn } from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'; import { User } from 'src/user/entities/user-entity'; import { Role } from '../../role/entities/role.entity'; -@Entity({ name: 'User_Role_Mapping' }) +@Entity({ name: 'UserRolesMapping' }) export class UserRoleMapping { @PrimaryGeneratedColumn('uuid') - Id: string; + userRolesId: string; @Column('uuid') userId: string; @@ -13,6 +13,27 @@ export class UserRoleMapping { @Column('uuid') roleId: string; + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + + @Column() + createdBy: string; + + @Column() + updatedBy: string; + + @Column('uuid') + tenantId: string; + @ManyToOne(() => User, user => user.userRoleMappings) @JoinColumn({ name: 'userId' }) user: User; From a2118aca02114057b839fb5f7c36d96bd0a06cd8 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 26 Apr 2024 12:00:34 +0530 Subject: [PATCH 276/408] Task #218126: Create Role Search API --- src/adapters/hasura/rbac/role.adapter.ts | 2 +- .../postgres/rbac/privilegerole.adapter.ts | 19 +- src/adapters/postgres/rbac/role-adapter.ts | 439 +++++++++++------- src/adapters/rbacservicelocator.ts | 2 +- .../entities/assign-role.entity.ts | 61 ++- src/rbac/privilege/privilege.module.ts | 4 +- src/rbac/rbac.module.ts | 6 +- src/rbac/role/role.controller.ts | 8 +- src/rbac/role/role.module.ts | 6 +- 9 files changed, 349 insertions(+), 198 deletions(-) diff --git a/src/adapters/hasura/rbac/role.adapter.ts b/src/adapters/hasura/rbac/role.adapter.ts index d3df2890..ffed3234 100644 --- a/src/adapters/hasura/rbac/role.adapter.ts +++ b/src/adapters/hasura/rbac/role.adapter.ts @@ -10,5 +10,5 @@ export class HasuraRoleService { public async createRole(request: any, createRolesDto: CreateRolesDto){} public async deleteRole(roleId: string) {} public async updateRole(roleId: string, request: any, roleDto: RoleDto) {} - public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) {} + public async searchRole(roleSearchDto: RoleSearchDto) {} } diff --git a/src/adapters/postgres/rbac/privilegerole.adapter.ts b/src/adapters/postgres/rbac/privilegerole.adapter.ts index a6f378e8..762badd5 100644 --- a/src/adapters/postgres/rbac/privilegerole.adapter.ts +++ b/src/adapters/postgres/rbac/privilegerole.adapter.ts @@ -1,6 +1,6 @@ -import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import {HttpStatus, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import { In, Repository } from 'typeorm'; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { CreatePrivilegeRoleDto } from 'src/rbac/assign-privilege/dto/create-assign-privilege.dto'; @@ -23,8 +23,19 @@ export class PostgresAssignPrivilegeService { roleId: createPrivilegeRoleDto.roleId, privilegeId })); - for(let data of privilegeRoles) { - result = await this.rolePrivilegeMappingRepository.save(data) + const existingPrivileges = await this.rolePrivilegeMappingRepository.find({ + where: { + roleId: createPrivilegeRoleDto.roleId, + privilegeId: In(createPrivilegeRoleDto.privilegeId) + } + }); + + const newPrivileges = privilegeRoles.filter(privilegeRole => { + return !existingPrivileges.some(existing => existing.privilegeId === privilegeRole.privilegeId); + }); + + for (let data of newPrivileges) { + result = await this.rolePrivilegeMappingRepository.save(data); } return new SuccessResponse({ statusCode: HttpStatus.CREATED, diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index e003abec..f89eb4ee 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -1,193 +1,298 @@ -import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; -import { Role } from "src/rbac/role/entities/role.entity" -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { CreateRolesDto, RoleDto, RolesResponseDto } from "../../../rbac/role/dto/role.dto"; -import { SuccessResponse } from 'src/success-response'; -import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { ConsoleLogger, HttpStatus, Injectable } from "@nestjs/common"; +import { Role } from "src/rbac/role/entities/role.entity"; +import { RolePrivilegeMapping } from "src/rbac/assign-privilege/entities/assign-privilege.entity"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; +import { + CreateRolesDto, + RoleDto, + RolesResponseDto, +} from "../../../rbac/role/dto/role.dto"; +import { SuccessResponse } from "src/success-response"; +import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; +import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; +import { Privilege } from "src/rbac/privilege/entities/privilege.entity"; @Injectable() export class PostgresRoleService { - constructor( - @InjectRepository(Role) - private roleRepository: Repository - ) { } - public async createRole(request: any, createRolesDto: CreateRolesDto) { + constructor( + @InjectRepository(Role) + private roleRepository: Repository, + @InjectRepository(UserRoleMapping) + private readonly userRoleMappingRepository: Repository, + @InjectRepository(RolePrivilegeMapping) + private readonly roleprivilegeMappingRepository: Repository + ) {} + public async createRole(request: any, createRolesDto: CreateRolesDto) { + const tenant = await this.checkTenantID(createRolesDto.tenantId); + if (!tenant) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter valid tenantId", + }); + } + const roles = []; + const errors = []; + try { + // Convert role name to lowercase + for (const roleDto of createRolesDto.roles) { + const tenantId = createRolesDto.tenantId; + const code = roleDto.title.toLowerCase().replace(/\s+/g, "_"); - const tenant = await this.checkTenantID(createRolesDto.tenantId) - if (!tenant) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter valid tenantId", - }); + // Check if role name already exists + const existingRole = await this.roleRepository.findOne({ + where: { code }, + }); + if (existingRole) { + errors.push({ + errorMessage: `Role with the code '${code}' already exists.`, + }); + continue; } - const roles = []; - const errors = [] - try { - - // Convert role name to lowercase - for (const roleDto of createRolesDto.roles) { - const tenantId = createRolesDto.tenantId; - const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); - - // Check if role name already exists - const existingRole = await this.roleRepository.findOne({ where: { code } }) - if (existingRole) { - errors.push({ - errorMessage: `Role with the code '${code}' already exists.`, - }); - continue; - } - const newRoleDto = new RoleDto({ - ...roleDto, - code, - createdAt: new Date(), - updatedAt: new Date(), - createdBy: request.user.userId, // Assuming you have a user object in the request - updatedBy: request.user.userId, - tenantId, // Add the tenantId to the RoleDto - }); - // Convert roleDto to lowercase - // const response = await this.roleRepository.save(roleDto); - const roleEntity = this.roleRepository.create(newRoleDto); + const newRoleDto = new RoleDto({ + ...roleDto, + code, + createdAt: new Date(), + updatedAt: new Date(), + createdBy: request.user.userId, // Assuming you have a user object in the request + updatedBy: request.user.userId, + tenantId, // Add the tenantId to the RoleDto + }); + // Convert roleDto to lowercase + // const response = await this.roleRepository.save(roleDto); + const roleEntity = this.roleRepository.create(newRoleDto); - // Save the role entity to the database - const response = await this.roleRepository.save(roleEntity); - roles.push(new RolesResponseDto(response)); - } - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - - return { - statusCode: HttpStatus.OK, - successCount: roles.length, - errorCount: errors.length, - roles, - errors, - }; + // Save the role entity to the database + const response = await this.roleRepository.save(roleEntity); + roles.push(new RolesResponseDto(response)); + } + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } - public async getRole(roleId: string, request: any) { - try { - const [results, totalCount] = await this.roleRepository.findAndCount({ - where: { roleId } - }) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - totalCount, - data: results, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - } + return { + statusCode: HttpStatus.OK, + successCount: roles.length, + errorCount: errors.length, + roles, + errors, + }; + } - public async updateRole(roleId: string, request: any, roleDto: RoleDto) { - try { - const response = await this.roleRepository.update(roleId, roleDto) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: { - rowCount: response.affected, - } - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } + public async getRole(roleId: string, request: any) { + try { + const [results, totalCount] = await this.roleRepository.findAndCount({ + where: { roleId }, + }); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + totalCount, + data: results, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } + } - public async searchRole(tenantid: string, request: any, roleSearchDto: RoleSearchDto) { - try { - - let { limit, page, filters } = roleSearchDto; - - let offset = 0; - if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - - if (limit.trim() === '') { - limit = '0'; - } + public async updateRole(roleId: string, request: any, roleDto: RoleDto) { + try { + const response = await this.roleRepository.update(roleId, roleDto); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Ok.", + data: { + rowCount: response.affected, + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } - const whereClause = {}; - if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } + public async searchRole(roleSearchDto: RoleSearchDto) { + try { + let { limit, page, filters } = roleSearchDto; - const [results, totalCount] = await this.roleRepository.findAndCount({ - where: whereClause, - skip: offset, - take: parseInt(limit), - }); + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - totalCount, - data: results, - }); + if (limit.trim() === "") { + limit = "0"; + } - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } + let whereClause: any = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + if (whereClause.userId && !whereClause.tenantId ) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter Tenenat id or Valid Filter", + }); + } + if (whereClause.field && !["Privilege"].includes(whereClause?.field)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Invalid field value.", + }); } - - public async deleteRole(roleId: string) { - try { - let response = await this.roleRepository.delete(roleId) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Role deleted successfully.', - data: { - rowCount: response.affected, - } + if (whereClause.userId && whereClause.tenantId && whereClause.field==="Privilege") { + const userRoleMappingData = await this.findUserRoleData(whereClause.userId, whereClause.tenantId) + const roles = []; + for (let data of userRoleMappingData) { + const result = await this.findPrivilegeByRoleId(data.roleid); + roles.push({ + roleId: data.roleid, + title: data.title, + code: data.code, + privileges: result.map((privilege) => ({ + privilegeId: privilege.privilegeid, + title: privilege.name, + code: privilege.code, + })), }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, + }return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Role For User with Privileges fetched successfully.", + data: roles, + }); + + }else if(whereClause.userId && whereClause.tenantId && !whereClause.field){ + const data = await this.findUserRoleData(whereClause.userId,whereClause.tenantId) + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Role For User Id fetched successfully.", + data: data, + }); + } + else if (whereClause.tenantId && whereClause.field === "Privilege") { + const userRoleData = await this.findRoleData(whereClause.tenantId); + const roles = []; + + for (let data of userRoleData) { + const result = await this.findPrivilegeByRoleId(data.roleId); + roles.push({ + roleId: data.roleId, + title: data.title, + code: data.code, + privileges: result.map((privilege) => ({ + privilegeId: privilege.privilegeid, + title: privilege.name, + code: privilege.code, + })), }); } + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Role For Tenant with Privileges fetched successfully.", + data: roles, + }); + } else if (whereClause.tenantId && !whereClause.field) { + const data = await this.findRoleData(whereClause.tenantId); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Role For Tenant fetched successfully.", + data: data, + }); + }else { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: "Please Enter Valid Filter", + }); } + + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + public async deleteRole(roleId: string) { + try { + let response = await this.roleRepository.delete(roleId); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Role deleted successfully.", + data: { + rowCount: response.affected, + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + public async findRoleData(id: string) { + const data = await this.roleRepository.find({ + where: { + tenantId: id, + }, + select: ["roleId", "title", "code"], + }); + return data; + } + public async findUserRoleData(userId: string,tenantId: string){ + let userRoleData = await this.userRoleMappingRepository.createQueryBuilder('urp'). + innerJoin(Role,'r','r.roleId=urp.roleId'). + select(['urp.roleId as roleid','r.title as title','r.code as code']). + where("urp.userId= :userId",{userId}). + andWhere("urp.tenantId=:tenantId",{tenantId}) + .getRawMany() + // let query =`SELECT "urp"."roleId" AS "urp_roleId", "r"."name" AS "r_name", "r"."code" AS "r_code" + // FROM "UserRolesMapping" "urp" + // INNER JOIN "Roles" "r" ON "r"."roleId"="urp"."roleId" + // WHERE "urp"."userId"=$1 AND "urp"."tenantId"= $2` + // let userRoleData = await this.userRoleMappingRepository.query(query,[userId,tenantId]) + return userRoleData; + } + public async findPrivilegeByRoleId(roleId: string) { + const privileges = await this.roleprivilegeMappingRepository + .createQueryBuilder("rpm") + .innerJoin(Privilege, "p", "p.privilegeId=rpm.privilegeId") + .select([ + "p.privilegeId as privilegeId", + "p.name as name", + "p.code as code", + ]) + .where("rpm.roleId = :roleId", { roleId }) + .getRawMany() + return privileges; + } - public async checkTenantID(tenantId) { - try { - let query = `SELECT "tenantId" FROM public."Tenants" - where "tenantId"= $1 ` - let response = await this.roleRepository.query(query, [tenantId]); - if (response.length > 0) { - return true - } - } - catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); - - } + public async checkTenantID(tenantId) { + try { + let query = `SELECT "tenantId" FROM public."Tenants" + where "tenantId"= $1 `; + let response = await this.roleRepository.query(query, [tenantId]); + if (response.length > 0) { + return true; + } + } catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); } + } } - - diff --git a/src/adapters/rbacservicelocator.ts b/src/adapters/rbacservicelocator.ts index 3b33f177..8f5c02fc 100644 --- a/src/adapters/rbacservicelocator.ts +++ b/src/adapters/rbacservicelocator.ts @@ -8,6 +8,6 @@ export interface IServicelocatorRbac { ); updateRole(id?: string, request?: any, userDto?: any); createRole(request: any, createRolesDto: CreateRolesDto); - searchRole(tenantid, request: any, roleSearchDto: RoleSearchDto); + searchRole(roleSearchDto: RoleSearchDto); deleteRole(roleId); } diff --git a/src/rbac/assign-role/entities/assign-role.entity.ts b/src/rbac/assign-role/entities/assign-role.entity.ts index a09b0002..82695f6e 100644 --- a/src/rbac/assign-role/entities/assign-role.entity.ts +++ b/src/rbac/assign-role/entities/assign-role.entity.ts @@ -1,24 +1,51 @@ -import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColumn } from 'typeorm'; -import { User } from 'src/user/entities/user-entity'; -import { Role } from '../../role/entities/role.entity'; - -@Entity({ name: 'User_Role_Mapping' }) +import { + Entity, + PrimaryGeneratedColumn, + Column, + ManyToOne, + JoinColumn, + CreateDateColumn, + UpdateDateColumn, +} from "typeorm"; +import { User } from "src/user/entities/user-entity"; +import { Role } from "../../role/entities/role.entity"; +@Entity({ name: "UserRolesMapping" }) export class UserRoleMapping { - @PrimaryGeneratedColumn('uuid') - Id: string; + @PrimaryGeneratedColumn("uuid") + userRolesId: string; - @Column('uuid') + @Column("uuid") userId: string; - - @Column('uuid') + + @Column("uuid") + tenantId: string; + + @Column("uuid") roleId: string; - @ManyToOne(() => User, user => user.userRoleMappings) - @JoinColumn({ name: 'userId' }) - user: User; + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; - @ManyToOne(() => Role) - @JoinColumn({ name: 'roleId' }) - role: Role; -} + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + @Column() + createdBy: string; + + @Column() + updatedBy: string; + + // @ManyToOne(() => User, (user) => user.userRoleMappings) + // @JoinColumn({ name: "userId" }) + // user: User; + + // @ManyToOne(() => Role) + // @JoinColumn({ name: "roleId" }) + // role: Role; +} diff --git a/src/rbac/privilege/privilege.module.ts b/src/rbac/privilege/privilege.module.ts index f3b398b8..33ad2fba 100644 --- a/src/rbac/privilege/privilege.module.ts +++ b/src/rbac/privilege/privilege.module.ts @@ -11,10 +11,12 @@ import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; import { PostgresPrivilegeService } from 'src/adapters/postgres/rbac/privilege-adapter'; import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; import { Role } from '../role/entities/role.entity'; +import { UserRoleMapping } from '../assign-role/entities/assign-role.entity'; +import { RolePrivilegeMapping } from '../assign-privilege/entities/assign-privilege.entity'; @Module({ imports: [ - TypeOrmModule.forFeature([Privilege,Role]), + TypeOrmModule.forFeature([Privilege,Role,UserRoleMapping,RolePrivilegeMapping]), HttpModule, PostgresModule, HasuraModule diff --git a/src/rbac/rbac.module.ts b/src/rbac/rbac.module.ts index 043963cf..2fb2744d 100644 --- a/src/rbac/rbac.module.ts +++ b/src/rbac/rbac.module.ts @@ -3,13 +3,17 @@ import { RoleModule } from "./role/role.module"; import { PrivilegeModule } from './privilege/privilege.module'; import { AssignRoleModule } from './assign-role/assign-role.module'; import { AssignPrivilegeModule } from "./assign-privilege/assign-privilege.module"; +import { RolePrivilegeMapping } from "./assign-privilege/entities/assign-privilege.entity"; +import { UserRoleMapping } from "./assign-role/entities/assign-role.entity"; @Module({ imports: [ RoleModule, PrivilegeModule, AssignRoleModule, - AssignPrivilegeModule + AssignPrivilegeModule, + UserRoleMapping, + RolePrivilegeMapping ], }) export class RbacModule {} diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index 6fb2a3f3..1eddbae6 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -88,12 +88,12 @@ export class RoleController { } // search Role - @Post("/search") + @Post("/list-roles") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role List." }) @ApiBody({ type: RoleSearchDto }) @ApiForbiddenResponse({ description: "Forbidden" }) - @UsePipes(ValidationPipe) + // @UsePipes(ValidationPipe) @SerializeOptions({ strategy: "excludeAll", }) @ApiHeader({ name: "tenantid" }) public async searchRole( @@ -102,8 +102,8 @@ export class RoleController { @Body() roleSearchDto: RoleSearchDto, @Res() response: Response ) { - let tenantid = headers["tenantid"]; - const result = await this.roleAdapter.buildRbacAdapter().searchRole(tenantid,request,roleSearchDto); + // let tenantid = headers["tenantid"]; + const result = await this.roleAdapter.buildRbacAdapter().searchRole(roleSearchDto); return response.status(result.statusCode).json(result); } diff --git a/src/rbac/role/role.module.ts b/src/rbac/role/role.module.ts index 68e319dd..cfb1bfe9 100644 --- a/src/rbac/role/role.module.ts +++ b/src/rbac/role/role.module.ts @@ -8,13 +8,15 @@ import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; import { HttpModule } from '@nestjs/axios'; import { RoleAdapter } from './roleadapter'; +import { UserRoleMapping } from '../assign-role/entities/assign-role.entity'; +import { RolePrivilegeMapping } from '../assign-privilege/entities/assign-privilege.entity'; @Module({ imports: [ - TypeOrmModule.forFeature([Role]), + TypeOrmModule.forFeature([Role,UserRoleMapping,RolePrivilegeMapping]), HttpModule, PostgresModule, - HasuraModule + HasuraModule, ], controllers: [RoleController], providers: [RoleAdapter,HasuraRoleService,PostgresRoleService], From 1f5588cd0333b9e2a6984ec0a240a2a4e9abd3f8 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Fri, 26 Apr 2024 13:57:36 +0530 Subject: [PATCH 277/408] Role:Delete Role API --- src/adapters/postgres/rbac/role-adapter.ts | 35 ++++++++++++++++++++-- src/rbac/role/role.controller.ts | 12 +++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index 60f2e870..db77cb69 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -13,6 +13,7 @@ import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; import { Privilege } from "src/rbac/privilege/entities/privilege.entity"; +import { isUUID } from "class-validator"; @Injectable() export class PostgresRoleService { @@ -228,7 +229,37 @@ export class PostgresRoleService { public async deleteRole(roleId: string) { try { - let response = await this.roleRepository.delete(roleId); + if (!isUUID(roleId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please Enter valid (UUID)", + }); + } + + const roleToDelete = await this.roleRepository.findOne({ + where: { roleId: roleId }, + }); + + if (!roleToDelete) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "Role not found", + }); + } + // Delete the role + const response = await this.roleRepository.delete(roleId); + + // Delete entries from RolePrivilegesMapping table associated with the roleId + const rolePrivilegesDeleteResponse = + await this.roleprivilegeMappingRepository.delete({ + roleId: roleId, + }); + + const userRoleDeleteResponse = + await this.userRoleMappingRepository.delete({ + roleId: roleId, + }); + return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Role deleted successfully.", @@ -239,7 +270,7 @@ export class PostgresRoleService { } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, + errorMessage: "Internal server error", // Access the error message }); } } diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index 1eddbae6..faf553cf 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -22,6 +22,8 @@ import { ApiCreatedResponse, ApiBasicAuth, ApiHeader, + ApiBadRequestResponse, + ApiNotFoundResponse, } from "@nestjs/swagger"; import { Request } from "@nestjs/common"; import { CreateRolesDto, RoleDto } from "./dto/role.dto"; @@ -108,12 +110,14 @@ export class RoleController { } //delete role - @Delete("/:id") + @Delete("/:roleId") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Role deleted successfully." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid" }) + @ApiOkResponse({ description: "Role deleted successfully." }) + @ApiNotFoundResponse({ description: "Data not found" }) + @ApiBadRequestResponse({ description: "Bad request" }) public async deleteRole( - @Param("id") roleId: string, + @Param("roleId") roleId: string, @Res() response: Response ) { const result = await this.roleAdapter.buildRbacAdapter().deleteRole(roleId); From 521ca17c1b14ea181b6016c17f900769a40709ce Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Fri, 26 Apr 2024 14:21:17 +0530 Subject: [PATCH 278/408] UserRole:Delete Userrole API --- src/adapters/assignroleservicelocater.ts | 2 +- .../hasura/rbac/assignrole.adapter.ts | 2 +- .../postgres/rbac/assignrole-adapter.ts | 78 ++++++++++++++----- .../assign-role/assign-role.controller.ts | 17 ++-- .../assign-role/dto/delete-assign-role.dto.ts | 28 +++++++ 5 files changed, 99 insertions(+), 28 deletions(-) create mode 100644 src/rbac/assign-role/dto/delete-assign-role.dto.ts diff --git a/src/adapters/assignroleservicelocater.ts b/src/adapters/assignroleservicelocater.ts index 2d4619f5..35f8fb50 100644 --- a/src/adapters/assignroleservicelocater.ts +++ b/src/adapters/assignroleservicelocater.ts @@ -3,5 +3,5 @@ import { CreateAssignRoleDto } from "src/rbac/assign-role/dto/create-assign-role export interface IServicelocatorassignRole { createAssignRole(request: any, createAssignRoleDto:CreateAssignRoleDto); getAssignedRole(userId, request); - deleteAssignedRole(userId); + deleteAssignedRole(deleteAssignRoleDto); } \ No newline at end of file diff --git a/src/adapters/hasura/rbac/assignrole.adapter.ts b/src/adapters/hasura/rbac/assignrole.adapter.ts index 24481f21..f98b94d9 100644 --- a/src/adapters/hasura/rbac/assignrole.adapter.ts +++ b/src/adapters/hasura/rbac/assignrole.adapter.ts @@ -8,5 +8,5 @@ export class HasuraAssignRoleService { constructor(private httpService: HttpService) {} public async createAssignRole(request: any, createAssignRoleDto:CreateAssignRoleDto){}; public async getAssignedRole(request: any, createAssignRoleDto:CreateAssignRoleDto){}; - public async deleteAssignedRole(userId){}; + public async deleteAssignedRole(deleteAssignRoleDto){}; } \ No newline at end of file diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts index 9dd7d308..acd4c0ac 100644 --- a/src/adapters/postgres/rbac/assignrole-adapter.ts +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -1,6 +1,6 @@ import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import { In, Repository } from 'typeorm'; import { SuccessResponse } from 'src/success-response'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { CreateAssignRoleDto, ResponseAssignRoleDto } from 'src/rbac/assign-role/dto/create-assign-role.dto'; @@ -9,6 +9,7 @@ import { Role } from "src/rbac/role/entities/role.entity"; import { IsAlpha, IsUUID, isUUID } from 'class-validator'; import { executionAsyncResource } from 'async_hooks'; import jwt_decode from "jwt-decode"; +import { DeleteAssignRoleDto } from 'src/rbac/assign-role/dto/delete-assign-role.dto'; @Injectable() @@ -133,31 +134,68 @@ export class PostgresAssignroleService { } - public async deleteAssignedRole(userId) { + public async deleteAssignedRole(deleteAssignRoleDto: DeleteAssignRoleDto) { try { - let result = await this.checkExistingRole(userId); - if (!result) { - return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'No Role assigned to user', - data: result, - }); + // Validate userId format + if (!isUUID(deleteAssignRoleDto.userId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Invalid userId format. Please provide a valid UUID.", + }); + } + // Validate roleId format + for (const roleId of deleteAssignRoleDto.roleId) { + if (!isUUID(roleId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Invalid roleId format. Please provide valid UUIDs.", + }); } - let response = await this.userRoleMappingRepository.delete(userId) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Role deleted successfully.', - data: { - rowCount: response.affected, - } + } + // Check if the userId exists in userRoleMapping table + const userExists = await this.userRoleMappingRepository.findOne({ + where: { userId: deleteAssignRoleDto.userId }, + }); + if (!userExists) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "User not found in userRoleMapping table", }); - } catch (e) { + } + // Check if all roleId(s) exist + const roleExists = await this.userRoleMappingRepository.find({ + where: { + userId: deleteAssignRoleDto.userId, + roleId: In(deleteAssignRoleDto.roleId), + }, + }); + // If any roleId(s) are missing, throw an error + if (roleExists.length !== deleteAssignRoleDto.roleId.length) { + // throw new Error("One or more roles not found for the user"); return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Roles not found for the user", }); + } + // If all validations pass, proceed with deletion + const response = await this.userRoleMappingRepository.delete({ + userId: deleteAssignRoleDto.userId, + roleId: In(deleteAssignRoleDto.roleId), + }); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "Roles deleted successfully.", + data: { + rowCount: response.affected, + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.message || "Internal server error", + }); } - } + } // async checkAndAddUserRole(data){ // let existingUser = await this.checkExistingRole(data.userId) ; diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index 55bfbd05..7f440440 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -2,8 +2,9 @@ import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, Validation import { AssignRoleAdapter } from './assign-role.apater'; import { CreateAssignRoleDto } from './dto/create-assign-role.dto'; import { Response, Request } from "express"; -import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags, ApiBadRequestResponse, ApiInternalServerErrorResponse, ApiConflictResponse } from '@nestjs/swagger'; +import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags, ApiBadRequestResponse, ApiInternalServerErrorResponse, ApiConflictResponse, ApiNotFoundResponse } from '@nestjs/swagger'; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { DeleteAssignRoleDto } from './dto/delete-assign-role.dto'; @@ -52,15 +53,19 @@ export class AssignRoleController { return response.status(result.statusCode).json(result); } - @Delete("/:id") + @Delete("/:userId") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Assigend Role deleted successfully." }) - @ApiForbiddenResponse({ description: "Forbidden" }) + @ApiHeader({ name: "tenantid" }) + @ApiOkResponse({ description: "Role deleted successfully." }) + @ApiNotFoundResponse({ description: "Data not found" }) + @ApiBadRequestResponse({ description: "Bad request" }) public async deleteRole( - @Param("id") userId: string, + @Body() deleteAssignRoleDto: DeleteAssignRoleDto, // Modify this line to accept DeleteAssignRoleDto @Res() response: Response ) { - const result = await this.assignRoleAdpater.buildassignroleAdapter().deleteAssignedRole(userId); + const result = await this.assignRoleAdpater + .buildassignroleAdapter() + .deleteAssignedRole(deleteAssignRoleDto); return response.status(result.statusCode).json(result); } diff --git a/src/rbac/assign-role/dto/delete-assign-role.dto.ts b/src/rbac/assign-role/dto/delete-assign-role.dto.ts new file mode 100644 index 00000000..2dec6bba --- /dev/null +++ b/src/rbac/assign-role/dto/delete-assign-role.dto.ts @@ -0,0 +1,28 @@ +import { Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; +import { IsArray, IsNotEmpty, IsString, IsUUID } from "class-validator"; + +export class DeleteAssignRoleDto { + @ApiProperty({ + type: String, + description: "User Id of User", + default: "", + }) + @Expose() + // @IsUUID() + userId: string; + + @ApiProperty({ + type: [String], // Define roleId as an array of strings + description: "Assigned Role Id", + default: [], + }) + @IsArray() + @IsString({ each: true }) // Validate each string in the array + // @IsUUID(4, { each: true }) // Specify the UUID version (4) and validate each UUID string in the array + roleId: string[]; +} + +// constructor(obj: any) { +// Object.assign(this, obj); +// } \ No newline at end of file From 799345e10339a4cc0c61bab4e8031e9518a751ed Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 26 Apr 2024 16:35:21 +0530 Subject: [PATCH 279/408] Task #218147 feat : created RBAC module for token generation --- package.json | 2 +- src/authRbac/authRbac.controller.ts | 29 +++++++++++++ src/authRbac/authRbac.module.ts | 22 ++++++++++ src/authRbac/authRbac.service.ts | 66 +++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/authRbac/authRbac.controller.ts create mode 100644 src/authRbac/authRbac.module.ts create mode 100644 src/authRbac/authRbac.service.ts diff --git a/package.json b/package.json index 181f6af2..ed8ad249 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@nestjs/common": "^8.4.2", "@nestjs/config": "^2.3.4", "@nestjs/core": "^8.0.0", - "@nestjs/jwt": "^8.0.0", + "@nestjs/jwt": "^8.0.1", "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^8.0.0", "@nestjs/schedule": "^1.1.0", diff --git a/src/authRbac/authRbac.controller.ts b/src/authRbac/authRbac.controller.ts new file mode 100644 index 00000000..b687fea4 --- /dev/null +++ b/src/authRbac/authRbac.controller.ts @@ -0,0 +1,29 @@ +import { + Body, + Controller, + Post, + HttpCode, + HttpStatus, + Param, + Get, + UseGuards, + Req, +} from "@nestjs/common"; +import { AuthRbacService } from "./authRbac.service"; +import { ApiBasicAuth, ApiTags } from "@nestjs/swagger"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; + +@ApiTags("AuthRbac") +@Controller("auth/rbac") +export class AuthRbacController { + constructor(private authService: AuthRbacService) {} + + @HttpCode(HttpStatus.OK) + @Get("/token") + @ApiBasicAuth("access-token") + @UseGuards(JwtAuthGuard) + signInRbac(@Req() req) { + // console.log(req.user, "user"); + return this.authService.signInRbac(req.user.userId); + } +} diff --git a/src/authRbac/authRbac.module.ts b/src/authRbac/authRbac.module.ts new file mode 100644 index 00000000..f2a59542 --- /dev/null +++ b/src/authRbac/authRbac.module.ts @@ -0,0 +1,22 @@ +import { Module } from "@nestjs/common"; +import { JwtModule } from "@nestjs/jwt"; +import { ConfigModule, ConfigService } from "@nestjs/config"; +import { AuthRbacService } from "./authRbac.service"; +import { AuthRbacController } from "./authRbac.controller"; + +@Module({ + imports: [ + JwtModule.registerAsync({ + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => ({ + global: true, + secret: configService.get("RBAC_JWT_SECRET"), + signOptions: { expiresIn: configService.get("RBAC_JWT_EXPIRES_IN") }, + }), + inject: [ConfigService], + }), + ], + providers: [AuthRbacService], + controllers: [AuthRbacController], +}) +export class AuthRbacModule {} diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts new file mode 100644 index 00000000..28aba6af --- /dev/null +++ b/src/authRbac/authRbac.service.ts @@ -0,0 +1,66 @@ +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import { JwtService } from "@nestjs/jwt"; +// import { UsersService } from '../users/users.service'; + +@Injectable() +export class AuthRbacService { + issuer: string; + audience: string; + jwt_expires_In: any; + jwt_secret: any; + constructor( + private jwtService: JwtService, + private configService: ConfigService + ) { + this.issuer = this.configService.get("ISSUER"); + this.audience = this.configService.get("AUDIENCE"); + this.jwt_expires_In = this.configService.get("RBAC_JWT_EXPIRES_IN"); + this.jwt_secret = this.configService.get("RBAC_JWT_SECRET"); + } // private usersService: UsersService, + + async generateToken(payload) { + const plainObject = JSON.parse(JSON.stringify(payload)); + const token = await this.jwtService.signAsync(plainObject, { + secret: this.jwt_secret, + expiresIn: this.jwt_expires_In, + }); + return token; + } + + async signInRbac(userId: string): Promise { + console.log(userId, "user Id"); + const issuer = this.issuer; + const audience = this.audience; + const user = { + username: "admin", + userId: "1", + email: "admin@yopmail.com", + name: "admin", + roles: ["admin", "teacher"], + privileges: ["user.create", "attendance.create"], + tenantId: "ef99949b-7f3a-4a5f-806a-e67e683e38f3", + }; + // if (user?.password !== pass) { + // throw new UnauthorizedException(); + // } + // TODO: Generate a JWT and return it here + // instead of the user object + + if (!user) { + throw new UnauthorizedException(); + } + + const payload = { + user, + iss: issuer, + aud: audience, + }; + + // console.log(payload, "auth -payload"); + + return { + access_token: await this.generateToken(payload), + }; + } +} From 0afdfb8d769121ab1466c9b3fc3b3e691bd15530 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 26 Apr 2024 16:36:31 +0530 Subject: [PATCH 280/408] Task #218147 feat : added rbac guard and strategy --- src/common/guards/rbac.guard.ts | 5 +++++ src/common/guards/rbac.strategy.ts | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/common/guards/rbac.guard.ts create mode 100644 src/common/guards/rbac.strategy.ts diff --git a/src/common/guards/rbac.guard.ts b/src/common/guards/rbac.guard.ts new file mode 100644 index 00000000..93240b90 --- /dev/null +++ b/src/common/guards/rbac.guard.ts @@ -0,0 +1,5 @@ +import { Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; + +@Injectable() +export class RbacAuthGuard extends AuthGuard('jwt-rbac') {} diff --git a/src/common/guards/rbac.strategy.ts b/src/common/guards/rbac.strategy.ts new file mode 100644 index 00000000..4179afc6 --- /dev/null +++ b/src/common/guards/rbac.strategy.ts @@ -0,0 +1,25 @@ +import { ExtractJwt, Strategy } from "passport-jwt"; +import { PassportStrategy } from "@nestjs/passport"; +import { Injectable } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; + +@Injectable() +export class RbacJwtStrategy extends PassportStrategy(Strategy, "jwt-rbac") { + constructor(configService: ConfigService) { + super({ + jwtFromRequest: ExtractJwt.fromHeader("rbac_token"), + ignoreExpiration: false, + secretOrKey: configService.get("RBAC_JWT_SECRET"), + }); + } + + async validate(payload: any) { + /** + * This can be obtained via req.user in the Controllers + * This is where we validate that the user is valid and delimit the payload returned to req.user + */ + + // console.log(payload, "payload -rbac"); + return payload; + } +} From cb1ae7e5e288749952f2c3a6f0b13e0af62a9b67 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 26 Apr 2024 16:37:24 +0530 Subject: [PATCH 281/408] Task #218147 feat : added rbac guard to api --- src/app.controller.ts | 19 +++++++++++++++---- src/app.module.ts | 2 ++ src/auth/auth.module.ts | 11 +++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/app.controller.ts b/src/app.controller.ts index dd325187..3b70c990 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,16 +1,27 @@ -import { Controller, Get, Param, Res, UseGuards } from "@nestjs/common"; +import { + Controller, + Get, + Param, + Res, + UseGuards, + Headers, +} from "@nestjs/common"; import { AppService } from "./app.service"; import { JwtAuthGuard } from "./common/guards/keycloak.guard"; -import { ApiBasicAuth } from "@nestjs/swagger"; +import { ApiBasicAuth, ApiHeader } from "@nestjs/swagger"; +import { RbacAuthGuard } from "./common/guards/rbac.guard"; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() - @UseGuards(JwtAuthGuard) + @UseGuards(RbacAuthGuard, JwtAuthGuard) + @ApiHeader({ + name: "rbac_token", + }) @ApiBasicAuth("access-token") - getHello(): object { + getHello(@Headers() headers): object { return this.appService.getHello(); } diff --git a/src/app.module.ts b/src/app.module.ts index e2e05bae..ce29ec7c 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -11,6 +11,7 @@ import { ConfigurationModule } from "./configs/configuration.module"; // In use for Shiksha 2.0 import { DatabaseModule } from "./common/database.module"; import { AuthModule } from "./auth/auth.module"; +import { AuthRbacModule } from "./authRbac/authRbac.module"; import { CohortModule } from "./cohort/cohort.module"; import { CohortMembersModule } from "./cohortMembers/cohortMembers.module"; import { FieldsModule } from "./fields/fields.module"; @@ -31,6 +32,7 @@ import { RbacModule } from "./rbac/rbac.module"; CohortMembersModule, FieldsModule, AuthModule, + AuthRbacModule, DatabaseModule, ], controllers: [AppController], diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 453c4aa2..8ff41fbb 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,8 +1,9 @@ -import { HttpService, Module } from "@nestjs/common"; +import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { AuthController } from "./auth.controller"; import { AuthService } from "./auth.service"; import { JwtStrategy } from "src/common/guards/keycloak.strategy"; +import { RbacJwtStrategy } from "src/common/guards/rbac.strategy"; import { UserAdapter } from "../user/useradapter"; import { TypeOrmModule } from "@nestjs/typeorm"; import { User } from "../user/entities/user-entity"; @@ -24,6 +25,12 @@ import { PostgresModule } from "src/adapters/postgres/potsgres-module"; PostgresModule, ], controllers: [AuthController], - providers: [AuthService, JwtStrategy, KeycloakService, UserAdapter], + providers: [ + AuthService, + JwtStrategy, + RbacJwtStrategy, + KeycloakService, + UserAdapter, + ], }) export class AuthModule {} From 3d85dfd071c79d36e6d4dfb36d86b7ff47c6854b Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 26 Apr 2024 16:39:12 +0530 Subject: [PATCH 282/408] Task #218147 chore : added more data to decoded token --- src/common/guards/keycloak.strategy.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/common/guards/keycloak.strategy.ts b/src/common/guards/keycloak.strategy.ts index 73d78aab..a2d83467 100644 --- a/src/common/guards/keycloak.strategy.ts +++ b/src/common/guards/keycloak.strategy.ts @@ -18,6 +18,11 @@ export class JwtStrategy extends PassportStrategy(Strategy, "jwt-keycloak") { * This can be obtained via req.user in the Controllers * This is where we validate that the user is valid and delimit the payload returned to req.user */ - return { userId: payload.sub }; + // console.log(payload, "payload"); + return { + userId: payload.sub, + name: payload.name, + username: payload.preferred_username, + }; } } From 54440686895b4bf0a87a590d7feb9cc98fdbcd2e Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 26 Apr 2024 21:38:48 +0530 Subject: [PATCH 283/408] Task #218147 chore : added actual user data to token --- src/adapters/postgres/rbac/role-adapter.ts | 2 + src/authRbac/authRbac.controller.ts | 2 +- src/authRbac/authRbac.module.ts | 17 +++++- src/authRbac/authRbac.service.ts | 63 ++++++++++++++-------- src/rbac/role/role.module.ts | 28 +++++----- 5 files changed, 72 insertions(+), 40 deletions(-) diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index db77cb69..42f064c9 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -297,6 +297,8 @@ export class PostgresRoleService { // let userRoleData = await this.userRoleMappingRepository.query(query,[userId,tenantId]) return userRoleData; } + + // Make this query with in clause public async findPrivilegeByRoleId(roleId: string) { const privileges = await this.roleprivilegeMappingRepository .createQueryBuilder("rpm") diff --git a/src/authRbac/authRbac.controller.ts b/src/authRbac/authRbac.controller.ts index b687fea4..b2bd7867 100644 --- a/src/authRbac/authRbac.controller.ts +++ b/src/authRbac/authRbac.controller.ts @@ -24,6 +24,6 @@ export class AuthRbacController { @UseGuards(JwtAuthGuard) signInRbac(@Req() req) { // console.log(req.user, "user"); - return this.authService.signInRbac(req.user.userId); + return this.authService.signInRbac(req.user.username); } } diff --git a/src/authRbac/authRbac.module.ts b/src/authRbac/authRbac.module.ts index f2a59542..f939f703 100644 --- a/src/authRbac/authRbac.module.ts +++ b/src/authRbac/authRbac.module.ts @@ -3,20 +3,33 @@ import { JwtModule } from "@nestjs/jwt"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { AuthRbacService } from "./authRbac.service"; import { AuthRbacController } from "./authRbac.controller"; +import { UserAdapter } from "src/user/useradapter"; +import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; +import { PostgresRoleService } from "src/adapters/postgres/rbac/role-adapter"; +import { Role } from "src/rbac/role/entities/role.entity"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; +import { RolePrivilegeMapping } from "src/rbac/assign-privilege/entities/assign-privilege.entity"; @Module({ imports: [ + TypeOrmModule.forFeature([Role, UserRoleMapping, RolePrivilegeMapping]), JwtModule.registerAsync({ imports: [ConfigModule], useFactory: async (configService: ConfigService) => ({ global: true, secret: configService.get("RBAC_JWT_SECRET"), - signOptions: { expiresIn: configService.get("RBAC_JWT_EXPIRES_IN") }, + signOptions: { + expiresIn: configService.get("RBAC_JWT_EXPIRES_IN"), + }, }), inject: [ConfigService], }), + HasuraModule, + PostgresModule, ], - providers: [AuthRbacService], + providers: [AuthRbacService, UserAdapter, PostgresRoleService], controllers: [AuthRbacController], }) export class AuthRbacModule {} diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts index 28aba6af..2252f717 100644 --- a/src/authRbac/authRbac.service.ts +++ b/src/authRbac/authRbac.service.ts @@ -1,6 +1,8 @@ import { Injectable, UnauthorizedException } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { JwtService } from "@nestjs/jwt"; +import { PostgresRoleService } from "src/adapters/postgres/rbac/role-adapter"; +import { UserAdapter } from "src/user/useradapter"; // import { UsersService } from '../users/users.service'; @Injectable() @@ -11,7 +13,9 @@ export class AuthRbacService { jwt_secret: any; constructor( private jwtService: JwtService, - private configService: ConfigService + private configService: ConfigService, + private readonly userAdapter: UserAdapter, + private readonly postgresRoleService: PostgresRoleService ) { this.issuer = this.configService.get("ISSUER"); this.audience = this.configService.get("AUDIENCE"); @@ -28,39 +32,52 @@ export class AuthRbacService { return token; } - async signInRbac(userId: string): Promise { - console.log(userId, "user Id"); - const issuer = this.issuer; - const audience = this.audience; - const user = { - username: "admin", - userId: "1", - email: "admin@yopmail.com", - name: "admin", - roles: ["admin", "teacher"], - privileges: ["user.create", "attendance.create"], - tenantId: "ef99949b-7f3a-4a5f-806a-e67e683e38f3", - }; - // if (user?.password !== pass) { - // throw new UnauthorizedException(); - // } - // TODO: Generate a JWT and return it here - // instead of the user object + async signInRbac(username: string): Promise { + let userData = await this.userAdapter + .buildUserAdapter() + .findUserDetails(null, username); + + // console.log(userData, "user Id"); - if (!user) { + if (!userData) { throw new UnauthorizedException(); } + userData["roles"] = await this.postgresRoleService.findUserRoleData( + userData?.userId, + userData?.tenantId + ); + + userData["priviledges"] = await this.getPrivileges(userData.roles); + + // console.log(userData, "roleDta"); + + const issuer = this.issuer; + const audience = this.audience; + const payload = { - user, + userData, iss: issuer, aud: audience, }; - // console.log(payload, "auth -payload"); - return { access_token: await this.generateToken(payload), }; } + + async getPrivileges(userRoleData) { + let privileges = []; + for (let data of userRoleData) { + const result = await this.postgresRoleService.findPrivilegeByRoleId( + data.roleid + ); + privileges = result.map((privilege) => ({ + privilegeId: privilege.privilegeid, + title: privilege.name, + code: privilege.code, + })); + } + return privileges; + } } diff --git a/src/rbac/role/role.module.ts b/src/rbac/role/role.module.ts index cfb1bfe9..08252c59 100644 --- a/src/rbac/role/role.module.ts +++ b/src/rbac/role/role.module.ts @@ -1,24 +1,24 @@ -import {Module } from '@nestjs/common'; -import { RoleController } from './role.controller'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { Role } from './entities/role.entity'; -import { HasuraModule } from 'src/adapters/hasura/hasura.module'; -import { PostgresModule } from 'src/adapters/postgres/potsgres-module'; -import { PostgresRoleService } from 'src/adapters/postgres/rbac/role-adapter'; -import { HasuraRoleService } from 'src/adapters/hasura/rbac/role.adapter'; -import { HttpModule } from '@nestjs/axios'; -import { RoleAdapter } from './roleadapter'; -import { UserRoleMapping } from '../assign-role/entities/assign-role.entity'; -import { RolePrivilegeMapping } from '../assign-privilege/entities/assign-privilege.entity'; +import { Module } from "@nestjs/common"; +import { RoleController } from "./role.controller"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { Role } from "./entities/role.entity"; +import { HasuraModule } from "src/adapters/hasura/hasura.module"; +import { PostgresModule } from "src/adapters/postgres/potsgres-module"; +import { PostgresRoleService } from "src/adapters/postgres/rbac/role-adapter"; +import { HasuraRoleService } from "src/adapters/hasura/rbac/role.adapter"; +import { HttpModule } from "@nestjs/axios"; +import { RoleAdapter } from "./roleadapter"; +import { UserRoleMapping } from "../assign-role/entities/assign-role.entity"; +import { RolePrivilegeMapping } from "../assign-privilege/entities/assign-privilege.entity"; @Module({ imports: [ - TypeOrmModule.forFeature([Role,UserRoleMapping,RolePrivilegeMapping]), + TypeOrmModule.forFeature([Role, UserRoleMapping, RolePrivilegeMapping]), HttpModule, PostgresModule, HasuraModule, ], controllers: [RoleController], - providers: [RoleAdapter,HasuraRoleService,PostgresRoleService], + providers: [RoleAdapter, HasuraRoleService, PostgresRoleService], }) export class RoleModule {} From 8e482722dc8440b7f46e75802006c589564aae4d Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 26 Apr 2024 22:15:21 +0530 Subject: [PATCH 284/408] Task #218147 feat : checked iss and aud valid --- src/common/guards/rbac.strategy.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/common/guards/rbac.strategy.ts b/src/common/guards/rbac.strategy.ts index 4179afc6..964d777f 100644 --- a/src/common/guards/rbac.strategy.ts +++ b/src/common/guards/rbac.strategy.ts @@ -1,11 +1,11 @@ import { ExtractJwt, Strategy } from "passport-jwt"; import { PassportStrategy } from "@nestjs/passport"; -import { Injectable } from "@nestjs/common"; +import { Injectable, UnauthorizedException } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; @Injectable() export class RbacJwtStrategy extends PassportStrategy(Strategy, "jwt-rbac") { - constructor(configService: ConfigService) { + constructor(private configService: ConfigService) { super({ jwtFromRequest: ExtractJwt.fromHeader("rbac_token"), ignoreExpiration: false, @@ -14,12 +14,14 @@ export class RbacJwtStrategy extends PassportStrategy(Strategy, "jwt-rbac") { } async validate(payload: any) { - /** - * This can be obtained via req.user in the Controllers - * This is where we validate that the user is valid and delimit the payload returned to req.user - */ - - // console.log(payload, "payload -rbac"); + if ( + !( + payload.iss === this.configService.get("ISSUER") && + payload.aud === this.configService.get("AUDIENCE") + ) + ) { + throw new UnauthorizedException(); + } return payload; } } From e5b7ed36be92dcd666fd74a4c599f3e3a387feb4 Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 29 Apr 2024 12:47:08 +0530 Subject: [PATCH 285/408] Task #218126 fix:Update Get Privilge Query to Take Multiple Role IDs --- src/adapters/postgres/rbac/role-adapter.ts | 183 ++++++++++----------- src/rbac/role/role.controller.ts | 2 +- 2 files changed, 89 insertions(+), 96 deletions(-) diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index 60f2e870..047002b9 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -24,65 +24,65 @@ export class PostgresRoleService { @InjectRepository(RolePrivilegeMapping) private readonly roleprivilegeMappingRepository: Repository ) {} - public async createRole(request: any, createRolesDto: CreateRolesDto) { +public async createRole(request: any, createRolesDto: CreateRolesDto) { - const tenant = await this.checkTenantID(createRolesDto.tenantId) - if (!tenant) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter valid tenantId", - }); - } - const roles = []; - const errors = [] - try { + const tenant = await this.checkTenantID(createRolesDto.tenantId) + if (!tenant) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter valid tenantId", + }); + } + const roles = []; + const errors = [] + try { - // Convert role name to lowercase - for (const roleDto of createRolesDto.roles) { - const tenantId = createRolesDto.tenantId; - const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); + // Convert role name to lowercase + for (const roleDto of createRolesDto.roles) { + const tenantId = createRolesDto.tenantId; + const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); - // Check if role name already exists - const existingRole = await this.roleRepository.findOne({ where: { code:code,tenantId:tenantId } }) - if (existingRole) { - errors.push({ - errorMessage: `Combination of this tenantId and the code '${code}' already exists.`, + // Check if role name already exists + const existingRole = await this.roleRepository.findOne({ where: { code:code,tenantId:tenantId } }) + if (existingRole) { + errors.push({ + errorMessage: `Combination of this tenantId and the code '${code}' already exists.`, + }); + continue; + } + + const newRoleDto = new RoleDto({ + ...roleDto, + code, + createdAt: new Date(), + updatedAt: new Date(), + createdBy: request.user.userId, // Assuming you have a user object in the request + updatedBy: request.user.userId, + tenantId, // Add the tenantId to the RoleDto }); - continue; - } + // Convert roleDto to lowercase + // const response = await this.roleRepository.save(roleDto); + const roleEntity = this.roleRepository.create(newRoleDto); - const newRoleDto = new RoleDto({ - ...roleDto, - code, - createdAt: new Date(), - updatedAt: new Date(), - createdBy: request.user.userId, // Assuming you have a user object in the request - updatedBy: request.user.userId, - tenantId, // Add the tenantId to the RoleDto + // Save the role entity to the database + const response = await this.roleRepository.save(roleEntity); + roles.push(new RolesResponseDto(response)); + } + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, }); - // Convert roleDto to lowercase - // const response = await this.roleRepository.save(roleDto); - const roleEntity = this.roleRepository.create(newRoleDto); - - // Save the role entity to the database - const response = await this.roleRepository.save(roleEntity); - roles.push(new RolesResponseDto(response)); } - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } - return { - statusCode: HttpStatus.OK, - successCount: roles.length, - errorCount: errors.length, - roles, - errors, - }; -} + return { + statusCode: HttpStatus.OK, + successCount: roles.length, + errorCount: errors.length, + roles, + errors, + }; + } public async getRole(roleId: string, request: any) { try { @@ -153,21 +153,22 @@ export class PostgresRoleService { }); } if (whereClause.userId && whereClause.tenantId && whereClause.field==="Privilege") { - const userRoleMappingData = await this.findUserRoleData(whereClause.userId, whereClause.tenantId) - const roles = []; - for (let data of userRoleMappingData) { - const result = await this.findPrivilegeByRoleId(data.roleid); - roles.push({ - roleId: data.roleid, - title: data.title, - code: data.code, - privileges: result.map((privilege) => ({ - privilegeId: privilege.privilegeid, - title: privilege.name, - code: privilege.code, - })), - }); - }return new SuccessResponse({ + const userRoleMappingData = await this.findUserRoleData(whereClause.userId, whereClause.tenantId); + const roleIds = userRoleMappingData.map(data => data.roleid); + + const result = await this.findPrivilegeByRoleId(roleIds); + + const roles = userRoleMappingData.map(data => { + const roleResult = result.find(privilegeData => privilegeData.roleid === data.roleid); + return { + roleId: data.roleid, + title: data.title, + code: data.code, + privileges: roleResult ? roleResult : [] + }; + }); + + return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Role For User with Privileges fetched successfully.", data: roles, @@ -183,23 +184,18 @@ export class PostgresRoleService { } else if (whereClause.tenantId && whereClause.field === "Privilege") { const userRoleData = await this.findRoleData(whereClause.tenantId); - const roles = []; - - for (let data of userRoleData) { - const result = await this.findPrivilegeByRoleId(data.roleId); - roles.push({ - roleId: data.roleId, - title: data.title, - code: data.code, - privileges: result.map((privilege) => ({ - privilegeId: privilege.privilegeid, - title: privilege.name, - code: privilege.code, - })), - }); - } - - return new SuccessResponse({ + const result = await this.findPrivilegeByRoleId(userRoleData.map(data => data.roleId)); + const roles = userRoleData.map(data => { + const roleResult = result.find(privilegeData => privilegeData.roleid === data.roleId); + return { + roleId: data.roleId, + title: data.title, + code: data.code, + privileges: roleResult ? roleResult : [] + }; + }); + + return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Role For Tenant with Privileges fetched successfully.", data: roles, @@ -216,9 +212,7 @@ export class PostgresRoleService { statusCode: HttpStatus.BAD_REQUEST, message: "Please Enter Valid Filter", }); - } - - } catch (e) { + }} catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, @@ -252,6 +246,7 @@ export class PostgresRoleService { }); return data; } + public async findUserRoleData(userId: string,tenantId: string){ let userRoleData = await this.userRoleMappingRepository.createQueryBuilder('urp'). innerJoin(Role,'r','r.roleId=urp.roleId'). @@ -259,14 +254,10 @@ export class PostgresRoleService { where("urp.userId= :userId",{userId}). andWhere("urp.tenantId=:tenantId",{tenantId}) .getRawMany() - // let query =`SELECT "urp"."roleId" AS "urp_roleId", "r"."name" AS "r_name", "r"."code" AS "r_code" - // FROM "UserRolesMapping" "urp" - // INNER JOIN "Roles" "r" ON "r"."roleId"="urp"."roleId" - // WHERE "urp"."userId"=$1 AND "urp"."tenantId"= $2` - // let userRoleData = await this.userRoleMappingRepository.query(query,[userId,tenantId]) return userRoleData; } - public async findPrivilegeByRoleId(roleId: string) { + + public async findPrivilegeByRoleId(roleIds: string[]) { const privileges = await this.roleprivilegeMappingRepository .createQueryBuilder("rpm") .innerJoin(Privilege, "p", "p.privilegeId=rpm.privilegeId") @@ -274,11 +265,12 @@ export class PostgresRoleService { "p.privilegeId as privilegeId", "p.name as name", "p.code as code", + "rpm.roleId as roleId" ]) - .where("rpm.roleId = :roleId", { roleId }) - .getRawMany() + .where("rpm.roleId IN (:...roleIds)", { roleIds }) + .getRawMany(); return privileges; - } +} public async checkTenantID(tenantId) { try { @@ -294,5 +286,6 @@ export class PostgresRoleService { errorMessage: error, }); } + } } diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index 1eddbae6..814ec374 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -33,7 +33,7 @@ import { RoleAdapter } from "./roleadapter" @ApiTags("rbac") @Controller("rbac/roles") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) export class RoleController { constructor(private readonly roleAdapter:RoleAdapter) { } From b73d67884839215040b5053ad719f0294854599d Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 29 Apr 2024 17:53:15 +0530 Subject: [PATCH 286/408] Fix[Bulk attendance fix] --- src/adapters/postgres/attendance-adapter.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index f2fe337a..b6e8ce38 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -561,6 +561,9 @@ export class PostgresAttendanceService { attendanceData: BulkAttendanceDTO ) { + const loginUserId=request.user.userId + + const responses = []; const errors = []; try { @@ -577,7 +580,7 @@ export class PostgresAttendanceService { tenantId:tenantId }) const attendanceRes: any = await this.updateAttendanceRecord( - request, + loginUserId, userAttendance ); From 46009fa53f724cbd2e55354849a43272234b2fd2 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 29 Apr 2024 18:19:12 +0530 Subject: [PATCH 287/408] Fix[dto fix] --- src/attendance/dto/attendance.dto.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 5fa321df..6328fe76 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -1,4 +1,4 @@ -import { ManyToOne, JoinColumn } from 'typeorm'; +import { ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'; import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, Validate, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; import { Exclude, Expose, Transform, Type } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; @@ -150,9 +150,11 @@ export class AttendanceDto { cohort: Cohort; + @CreateDateColumn() @Expose() createdAt: string; + @UpdateDateColumn() @Expose() updatedAt: string; From 53a8f41f04eb60eadc1502dcbf4ec5f1e01f400a Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 29 Apr 2024 23:06:17 +0530 Subject: [PATCH 288/408] Task #218147 refactor : modified find priviledge method --- src/authRbac/authRbac.service.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts index 2252f717..9a66808b 100644 --- a/src/authRbac/authRbac.service.ts +++ b/src/authRbac/authRbac.service.ts @@ -67,17 +67,10 @@ export class AuthRbacService { } async getPrivileges(userRoleData) { - let privileges = []; - for (let data of userRoleData) { - const result = await this.postgresRoleService.findPrivilegeByRoleId( - data.roleid - ); - privileges = result.map((privilege) => ({ - privilegeId: privilege.privilegeid, - title: privilege.name, - code: privilege.code, - })); - } + const roleIds = userRoleData.map(({ roleid }) => roleid); + const privileges = await this.postgresRoleService.findPrivilegeByRoleId( + roleIds + ); return privileges; } } From 27de8a9ab6bcc0f6958f3e9cd67afbea5ed8140e Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 30 Apr 2024 09:36:21 +0530 Subject: [PATCH 289/408] user tenent mapping --- src/adapters/assigntenantlocator.ts | 6 + src/adapters/hasura/assigntenant.adapter.ts | 23 ++++ src/adapters/postgres/assigntenant-adapter.ts | 125 ++++++++++++++++++ src/app.module.ts | 2 + src/assign-tenant/assign-tenant.apater.ts | 25 ++++ .../assign-tenant.controller.spec.ts | 18 +++ src/assign-tenant/assign-tenant.controller.ts | 105 +++++++++++++++ src/assign-tenant/assign-tenant.module.ts | 36 +++++ .../dto/assign-tenant-create.dto.ts | 50 +++++++ .../dto/assign-tenant-update.dto.ts | 54 ++++++++ .../entities/assign-tenant.entity.ts | 38 ++++++ src/assign-tenant/entities/tenant.entity.ts | 38 ++++++ 12 files changed, 520 insertions(+) create mode 100644 src/adapters/assigntenantlocator.ts create mode 100644 src/adapters/hasura/assigntenant.adapter.ts create mode 100644 src/adapters/postgres/assigntenant-adapter.ts create mode 100644 src/assign-tenant/assign-tenant.apater.ts create mode 100644 src/assign-tenant/assign-tenant.controller.spec.ts create mode 100644 src/assign-tenant/assign-tenant.controller.ts create mode 100644 src/assign-tenant/assign-tenant.module.ts create mode 100644 src/assign-tenant/dto/assign-tenant-create.dto.ts create mode 100644 src/assign-tenant/dto/assign-tenant-update.dto.ts create mode 100644 src/assign-tenant/entities/assign-tenant.entity.ts create mode 100644 src/assign-tenant/entities/tenant.entity.ts diff --git a/src/adapters/assigntenantlocator.ts b/src/adapters/assigntenantlocator.ts new file mode 100644 index 00000000..3e6e6696 --- /dev/null +++ b/src/adapters/assigntenantlocator.ts @@ -0,0 +1,6 @@ +import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; +import { UpdateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-update.dto"; +export interface IServicelocatorassignTenant { + createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto); + // updateAssignTenant(request: any, updateAssignTenantDto:UpdateAssignTenantDto); +} \ No newline at end of file diff --git a/src/adapters/hasura/assigntenant.adapter.ts b/src/adapters/hasura/assigntenant.adapter.ts new file mode 100644 index 00000000..88d06ae1 --- /dev/null +++ b/src/adapters/hasura/assigntenant.adapter.ts @@ -0,0 +1,23 @@ +import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { In, Repository } from 'typeorm'; +// import { UserRoleMapping } from 'src/rbac/assign-role/entities/assign-role.entity'; +import { UserTenantMapping } from 'src/assign-tenant/entities/assign-tenant.entity'; +import { Role } from "src/rbac/role/entities/role.entity"; +import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; +import { UpdateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-update.dto"; + + +@Injectable() +export class HasuraAssignTenantService { + constructor( + @InjectRepository(UserTenantMapping) + private userTenantMappingRepository: Repository, + + ) { } + public async createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto) { + } + public async updateAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto) { + } + +} diff --git a/src/adapters/postgres/assigntenant-adapter.ts b/src/adapters/postgres/assigntenant-adapter.ts new file mode 100644 index 00000000..97981072 --- /dev/null +++ b/src/adapters/postgres/assigntenant-adapter.ts @@ -0,0 +1,125 @@ +import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { In, Repository } from 'typeorm'; +import { UserTenantMapping } from 'src/assign-tenant/entities/assign-tenant.entity'; +import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; +import { ResponseAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; +import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; +import { SuccessResponse } from 'src/success-response'; +import { User } from "src/user/entities/user-entity"; +import { Tenants } from "src/assign-tenant/entities/tenant.entity"; + + +@Injectable() +export class PostgresAssignTenantService { + constructor( + @InjectRepository(UserTenantMapping) + private userTenantMappingRepository: Repository, + @InjectRepository(User) + private userRepository: Repository, + @InjectRepository(Tenants) + private tenantsRepository: Repository, + ) { } + public async createAssignTenant(request: any, createAssignTenantDto: CreateAssignTenantDto) { + try { + + const userId = createAssignTenantDto.userId; + const tenantIds = createAssignTenantDto.tenantId; + + // Check if tenant array is not empty + if (!tenantIds || tenantIds.length === 0) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: "Roles array cannot be empty.", + }); + } + let result = []; + let errors = []; + + for (const tenantId of tenantIds) { + // If role already exists for user, return error response + console.log(userId); + console.log(tenantId); + + let findExistingRole = await this.userTenantMappingRepository.findOne({ + where: { + userId: userId, + tenantId: tenantId, + }, + }); + if (findExistingRole) { + errors.push({ + errorMessage: `User is already exist in ${tenantId} Tenant.`, + }); + continue; + } + + // User is exist in user table + let userExist = await this.userRepository.findOne({ + where: { + userId: userId, + }, + }); + if (!userExist) { + errors.push({ + errorMessage: `User ${userId} is not exist.`, + }); + continue; + } + + // User is exist in user table + let tenantExist = await this.tenantsRepository.findOne({ + where: { + tenantId: tenantId, + }, + }); + if (!tenantExist) { + errors.push({ + errorMessage: `Tenant ${tenantId} is not exist.`, + }); + continue; + } + + + const data = await this.userTenantMappingRepository.save({ + userId: userId, + tenantId: tenantId, + createdBy: request['user'].userId, + updatedBy: request['user'].userId + }) + + result.push(new ResponseAssignTenantDto(data, `Tenant assigned successfully to the user.`)); + } + + if (result.length == 0) { + return { + statusCode: HttpStatus.BAD_REQUEST, + errorCount: errors.length, + errors, + }; + } + return { + statusCode: HttpStatus.CREATED, + successCount: result.length, + errorCount: errors.length, + data: result, + errors, + }; + } catch (error) { + if (error.code === '23503') { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: `User Id or Role Id Doesn't Exist in Database ` + }); + } + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: JSON.stringify(error) + }); + } + } + + public async updateAssignTenant(request: any, createAssignTenantDto: CreateAssignTenantDto) { + } + +} diff --git a/src/app.module.ts b/src/app.module.ts index ce29ec7c..d2bd8266 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,6 +18,7 @@ import { FieldsModule } from "./fields/fields.module"; import { AttendanceModule } from "./attendance/attendance.module"; import { UserModule } from "./user/user.module"; import { RbacModule } from "./rbac/rbac.module"; +import { AssignTenantModule } from './assign-tenant/assign-tenant.module'; @Module({ imports: [ @@ -34,6 +35,7 @@ import { RbacModule } from "./rbac/rbac.module"; AuthModule, AuthRbacModule, DatabaseModule, + AssignTenantModule, ], controllers: [AppController], providers: [AppService], diff --git a/src/assign-tenant/assign-tenant.apater.ts b/src/assign-tenant/assign-tenant.apater.ts new file mode 100644 index 00000000..1ef39d57 --- /dev/null +++ b/src/assign-tenant/assign-tenant.apater.ts @@ -0,0 +1,25 @@ +import { Injectable } from "@nestjs/common"; +import { PostgresAssignTenantService } from "src/adapters/postgres/assigntenant-adapter"; +import { HasuraAssignTenantService } from "src/adapters/hasura/assigntenant.adapter"; +import { IServicelocatorassignTenant } from "src/adapters/assigntenantlocator"; + +@Injectable() +export class AssignTenantAdapter { + constructor(private hasuraProvider: HasuraAssignTenantService, + private postgresProvider:PostgresAssignTenantService) {} + buildassignTenantAdapter(): IServicelocatorassignTenant { + let adapter: IServicelocatorassignTenant; + + switch (process.env.ADAPTERSOURCE) { + case "hasura": + adapter = this.hasuraProvider; + break; + case "postgres": + adapter = this.postgresProvider; + break; + default: + throw new Error("Invalid ADAPTERSOURCE environment variable. Please specify either 'hasura' or 'postgres'."); + } + return adapter; + } +} diff --git a/src/assign-tenant/assign-tenant.controller.spec.ts b/src/assign-tenant/assign-tenant.controller.spec.ts new file mode 100644 index 00000000..3e76c67f --- /dev/null +++ b/src/assign-tenant/assign-tenant.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AssignTenantController } from './assign-tenant.controller'; + +describe('AssignTenantController', () => { + let controller: AssignTenantController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [AssignTenantController], + }).compile(); + + controller = module.get(AssignTenantController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/assign-tenant/assign-tenant.controller.ts b/src/assign-tenant/assign-tenant.controller.ts new file mode 100644 index 00000000..8146c94c --- /dev/null +++ b/src/assign-tenant/assign-tenant.controller.ts @@ -0,0 +1,105 @@ +import { + ApiTags, + ApiBody, + ApiCreatedResponse, + ApiBasicAuth, + ApiConsumes, + ApiHeader, + ApiBadRequestResponse, + ApiInternalServerErrorResponse, + ApiOkResponse, + ApiConflictResponse, +} from "@nestjs/swagger"; +import { + Controller, + Get, + Post, + Body, + Put, + Param, + UseInterceptors, + Req, + UploadedFile, + Res, + Headers, + UseGuards, + ValidationPipe, + UsePipes, +} from "@nestjs/common"; +import { Request } from "@nestjs/common"; +import { FileInterceptor } from "@nestjs/platform-express"; + +import { Response, response } from "express"; +import { AssignTenantAdapter } from "./assign-tenant.apater"; +import { CreateAssignTenantDto } from "./dto/assign-tenant-create.dto"; +import { UpdateAssignTenantDto } from "./dto/assign-tenant-update.dto"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; + +@ApiTags("AssignTenant") +@Controller("assign-tenant") +@UseGuards(JwtAuthGuard) +export class AssignTenantController { + constructor(private readonly assignTenantAdapter: AssignTenantAdapter) { } + + //create cohort + @Post() + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "Tenant assigned successfully to the user." }) + @ApiBadRequestResponse({ description: "Bad request." }) + @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) + @ApiConflictResponse({ description: "Tenant is already assigned to this user." }) + @UsePipes(new ValidationPipe()) + @ApiBody({ type: CreateAssignTenantDto }) + public async createCohort( + @Req() request: Request, + @Body() createAssignTenantDto: CreateAssignTenantDto, + @Res() response: Response + ) { + + // createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto); + // updateAssignTenant(request: any, updateAssignTenantDto:UpdateAssignTenantDto); + + const result = await this.assignTenantAdapter.buildassignTenantAdapter().createAssignTenant( + request, + createAssignTenantDto + ); + return response.status(result.statusCode).json(result); + } + + + + + + //update + // @Put("/:cohortId") + // @ApiConsumes("multipart/form-data") + // @ApiBasicAuth("access-token") + // @UseInterceptors( + // FileInterceptor("image", { + // storage: diskStorage({ + // destination: process.env.IMAGEPATH, + // filename: editFileName, + // }), + // fileFilter: imageFileFilter, + // }) + // ) + // @ApiBody({ type: CohortUpdateDto }) + // @ApiOkResponse({ description: "Cohort has been updated successfully" }) + // @ApiBadRequestResponse({ description: "Bad request." }) + // @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) + + // public async updateCohort( + // @Param("cohortId") cohortId: string, + // @Req() request: Request, + // @Body() cohortUpdateDto: CohortUpdateDto, + // @UploadedFile() image, + // @Res() response: Response + // ) { + // const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( + // cohortId, + // request, + // cohortUpdateDto + // ); + // return response.status(result.statusCode).json(result); + // } +} diff --git a/src/assign-tenant/assign-tenant.module.ts b/src/assign-tenant/assign-tenant.module.ts new file mode 100644 index 00000000..ce7ec0c7 --- /dev/null +++ b/src/assign-tenant/assign-tenant.module.ts @@ -0,0 +1,36 @@ +import { HttpModule, Module } from '@nestjs/common'; +import { AssignTenantController } from './assign-tenant.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { UserTenantMapping } from "./entities/assign-tenant.entity"; +import { AssignTenantAdapter } from "./assign-tenant.apater"; +import { PostgresAssignTenantService } from "src/adapters/postgres/assigntenant-adapter"; +import { HasuraAssignTenantService } from "src/adapters/hasura/assigntenant.adapter"; +import { User } from "src/user/entities/user-entity"; +import { Tenants } from "src/assign-tenant/entities/tenant.entity"; + + +@Module({ + imports:[TypeOrmModule.forFeature([UserTenantMapping,User,Tenants]),HttpModule], + controllers: [AssignTenantController], + providers: [AssignTenantAdapter,HasuraAssignTenantService,PostgresAssignTenantService] + +}) +export class AssignTenantModule {} + + +// import { Module } from '@nestjs/common'; +// import { AssignRoleAdapter } from './assign-role.apater'; +// import { AssignRoleController } from './assign-role.controller'; +// import { TypeOrmModule } from '@nestjs/typeorm'; +// import { UserRoleMapping } from './entities/assign-role.entity'; +// import { Role } from "src/rbac/role/entities/role.entity"; +// import { PostgresAssignroleService } from 'src/adapters/postgres/rbac/assignrole-adapter'; +// import { HasuraAssignRoleService } from 'src/adapters/hasura/rbac/assignrole.adapter'; +// import { HttpModule } from '@nestjs/axios'; + +// @Module({ +// imports:[TypeOrmModule.forFeature([UserRoleMapping,Role]),HttpModule], +// controllers: [AssignRoleController], +// providers: [AssignRoleAdapter,HasuraAssignRoleService,PostgresAssignroleService] +// }) +// export class AssignRoleModule {} diff --git a/src/assign-tenant/dto/assign-tenant-create.dto.ts b/src/assign-tenant/dto/assign-tenant-create.dto.ts new file mode 100644 index 00000000..e85ed3b4 --- /dev/null +++ b/src/assign-tenant/dto/assign-tenant-create.dto.ts @@ -0,0 +1,50 @@ +import { Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; +import { IsNotEmpty, IsString, IsUUID, IsArray } from "class-validator"; + +export class CreateAssignTenantDto { + @ApiProperty({ + type: String, + description: "User Id of User", + default: "", + }) + @Expose() + @IsNotEmpty() + @IsUUID() + userId: string; + + + @ApiProperty({ + type: String, + description: "Tenant Id", + default: [], + }) + @Expose() + @IsArray() + @IsUUID(undefined, { each: true }) + @IsNotEmpty({ each: true }) + tenantId: string; + + constructor(obj: any) { + Object.assign(this, obj); + } + +} + +export class ResponseAssignTenantDto { + @Expose() + userId: string; + + @Expose() + tenantId: string; + + @Expose() + message: string; + + constructor(data: { userId: string; tenantId: string }, message: string) { + this.userId = data.userId; + this.tenantId = data.tenantId; + this.message = message; + } +} + diff --git a/src/assign-tenant/dto/assign-tenant-update.dto.ts b/src/assign-tenant/dto/assign-tenant-update.dto.ts new file mode 100644 index 00000000..aa3fc933 --- /dev/null +++ b/src/assign-tenant/dto/assign-tenant-update.dto.ts @@ -0,0 +1,54 @@ +import { Expose } from "class-transformer"; +import { ApiProperty } from "@nestjs/swagger"; +import { IsNotEmpty, IsString, IsUUID, IsArray } from "class-validator"; + +export class UpdateAssignTenantDto { + @ApiProperty({ + type: String, + description: "User Id of User", + default: "", + }) + @Expose() + @IsNotEmpty() + @IsUUID() + userId: string; + + + @ApiProperty({ + type: String, + description: "Tenant Id", + default: [], + }) + @Expose() + @IsArray() + @IsUUID(undefined, { each: true }) + @IsNotEmpty({ each: true }) + tenantId: string; + + constructor(obj: any) { + Object.assign(this, obj); + } + +} + +// export class ResponseAssignRoleDto { +// @Expose() +// userId: string; + +// @Expose() +// roleId: string; + +// @Expose() +// tenantId: string; + +// @Expose() +// message: string; + +// constructor(data: { userId: string; roleId: string; tenantId: string }, message: string) { +// this.userId = data.userId; +// this.roleId = data.roleId; +// this.tenantId = data.tenantId; +// this.message = message; +// } +// } + diff --git a/src/assign-tenant/entities/assign-tenant.entity.ts b/src/assign-tenant/entities/assign-tenant.entity.ts new file mode 100644 index 00000000..14733775 --- /dev/null +++ b/src/assign-tenant/entities/assign-tenant.entity.ts @@ -0,0 +1,38 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + } from "typeorm"; + + @Entity({ name: "UserTenantMapping" }) + export class UserTenantMapping { + @PrimaryGeneratedColumn("uuid") + Id: string; + + @Column("uuid") + userId: string; + + @Column("uuid") + tenantId: string; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + + @Column() + createdBy: string; + + @Column() + updatedBy: string; + } + \ No newline at end of file diff --git a/src/assign-tenant/entities/tenant.entity.ts b/src/assign-tenant/entities/tenant.entity.ts new file mode 100644 index 00000000..6cad22bf --- /dev/null +++ b/src/assign-tenant/entities/tenant.entity.ts @@ -0,0 +1,38 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + } from "typeorm"; + + @Entity({ name: "Tenants" }) + export class Tenants { + @PrimaryGeneratedColumn("uuid") + tenantId: string; + + @Column() + name: string; + + @Column() + domain: string; + + @CreateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + createdAt: Date; + + @UpdateDateColumn({ + type: "timestamp with time zone", + default: () => "CURRENT_TIMESTAMP", + }) + updatedAt: Date; + + // @Column() + // createdBy: string; + + // @Column() + // updatedBy: string; + } + \ No newline at end of file From a5c41d83e23a05940267a175ff7c97bd77f982dc Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Tue, 30 Apr 2024 19:05:29 +0530 Subject: [PATCH 290/408] Task #218350 : Create token as per tenant Id --- src/auth/auth.controller.ts | 18 ++++++++++-------- src/authRbac/authRbac.controller.ts | 10 +++++++--- src/authRbac/authRbac.service.ts | 9 ++++++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index ecac1df9..3e0f810f 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -14,12 +14,12 @@ import { SerializeOptions, Req, Res, - Request, Response, HttpStatus, HttpCode, UsePipes, ValidationPipe, + UseGuards, } from "@nestjs/common"; import { AuthDto, @@ -27,6 +27,8 @@ import { LogoutRequestBody, } from "./dto/auth-dto"; import { AuthService } from "./auth.service"; +import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { RbacAuthGuard } from "src/common/guards/rbac.guard"; @ApiTags("Auth") @Controller("auth") @@ -43,19 +45,19 @@ export class AuthController { } @Get("/user") + @ApiHeader({ + name: "rbac_token", + }) + @UseGuards(JwtAuthGuard, RbacAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) - @ApiHeader({ - name: "tenantid", - }) - public async getUserByAuth( - @Req() request: Request, - @Res() response: Response - ) { + public async getUserByAuth(@Req() request, @Res() response: Response) { + console.log(request.user, "user"); + console.log(request.user.userData, "user"); // const tenantId = headers["tenantid"]; return this.authService.getUserByAuth(request, response); } diff --git a/src/authRbac/authRbac.controller.ts b/src/authRbac/authRbac.controller.ts index b2bd7867..494d68bb 100644 --- a/src/authRbac/authRbac.controller.ts +++ b/src/authRbac/authRbac.controller.ts @@ -10,7 +10,7 @@ import { Req, } from "@nestjs/common"; import { AuthRbacService } from "./authRbac.service"; -import { ApiBasicAuth, ApiTags } from "@nestjs/swagger"; +import { ApiBasicAuth, ApiHeader, ApiTags } from "@nestjs/swagger"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("AuthRbac") @@ -20,10 +20,14 @@ export class AuthRbacController { @HttpCode(HttpStatus.OK) @Get("/token") + @ApiHeader({ + name: "tenantid", + }) @ApiBasicAuth("access-token") @UseGuards(JwtAuthGuard) signInRbac(@Req() req) { - // console.log(req.user, "user"); - return this.authService.signInRbac(req.user.username); + const tenantId = req.headers["tenantid"]; + console.log(req.user, "user", tenantId); + return this.authService.signInRbac(req.user.username, tenantId); } } diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts index 9a66808b..f45a0678 100644 --- a/src/authRbac/authRbac.service.ts +++ b/src/authRbac/authRbac.service.ts @@ -32,7 +32,7 @@ export class AuthRbacService { return token; } - async signInRbac(username: string): Promise { + async signInRbac(username: string, tenantId: string): Promise { let userData = await this.userAdapter .buildUserAdapter() .findUserDetails(null, username); @@ -45,11 +45,11 @@ export class AuthRbacService { userData["roles"] = await this.postgresRoleService.findUserRoleData( userData?.userId, - userData?.tenantId + tenantId ); userData["priviledges"] = await this.getPrivileges(userData.roles); - + userData["tenantId"] = tenantId; // console.log(userData, "roleDta"); const issuer = this.issuer; @@ -68,6 +68,9 @@ export class AuthRbacService { async getPrivileges(userRoleData) { const roleIds = userRoleData.map(({ roleid }) => roleid); + if (!roleIds.length) { + return []; + } const privileges = await this.postgresRoleService.findPrivilegeByRoleId( roleIds ); From 6e72e51c2f5040590743a409a0060ad38f458549 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Tue, 30 Apr 2024 19:06:17 +0530 Subject: [PATCH 291/408] Task #218350 : chore - removed unwanted console log --- src/authRbac/authRbac.controller.ts | 4 ---- src/authRbac/authRbac.service.ts | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/authRbac/authRbac.controller.ts b/src/authRbac/authRbac.controller.ts index 494d68bb..a4c9f58c 100644 --- a/src/authRbac/authRbac.controller.ts +++ b/src/authRbac/authRbac.controller.ts @@ -1,10 +1,7 @@ import { - Body, Controller, - Post, HttpCode, HttpStatus, - Param, Get, UseGuards, Req, @@ -27,7 +24,6 @@ export class AuthRbacController { @UseGuards(JwtAuthGuard) signInRbac(@Req() req) { const tenantId = req.headers["tenantid"]; - console.log(req.user, "user", tenantId); return this.authService.signInRbac(req.user.username, tenantId); } } diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts index f45a0678..1379aec1 100644 --- a/src/authRbac/authRbac.service.ts +++ b/src/authRbac/authRbac.service.ts @@ -3,7 +3,6 @@ import { ConfigService } from "@nestjs/config"; import { JwtService } from "@nestjs/jwt"; import { PostgresRoleService } from "src/adapters/postgres/rbac/role-adapter"; import { UserAdapter } from "src/user/useradapter"; -// import { UsersService } from '../users/users.service'; @Injectable() export class AuthRbacService { @@ -21,7 +20,7 @@ export class AuthRbacService { this.audience = this.configService.get("AUDIENCE"); this.jwt_expires_In = this.configService.get("RBAC_JWT_EXPIRES_IN"); this.jwt_secret = this.configService.get("RBAC_JWT_SECRET"); - } // private usersService: UsersService, + } async generateToken(payload) { const plainObject = JSON.parse(JSON.stringify(payload)); @@ -37,8 +36,6 @@ export class AuthRbacService { .buildUserAdapter() .findUserDetails(null, username); - // console.log(userData, "user Id"); - if (!userData) { throw new UnauthorizedException(); } @@ -50,7 +47,6 @@ export class AuthRbacService { userData["priviledges"] = await this.getPrivileges(userData.roles); userData["tenantId"] = tenantId; - // console.log(userData, "roleDta"); const issuer = this.issuer; const audience = this.audience; From 16b183924d129aca3549b47b53b5994d1ee5209a Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 1 May 2024 16:40:41 +0530 Subject: [PATCH 292/408] Cohort managenet: Minor validation changes --- src/adapters/postgres/cohort-adapter.ts | 238 +++++++++++++++--------- src/cohort/cohort.controller.ts | 13 +- src/cohort/dto/cohort-search.dto.ts | 105 ++++++++++- src/cohort/dto/cohort.dto.ts | 28 ++- 4 files changed, 296 insertions(+), 88 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 7da6e53a..54a7aa4e 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -1,27 +1,20 @@ import { ConsoleLogger, HttpStatus, Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; import { SuccessResponse } from "src/success-response"; -import { ErrorResponse } from "src/error-response"; const resolvePath = require("object-resolve-path"); import jwt_decode from "jwt-decode"; -import { CohortDto } from "src/cohort/dto/cohort.dto"; +import { CohortDto, ReturnResponseBody } from "src/cohort/dto/cohort.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { UserDto } from "src/user/dto/user.dto"; import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { CohortUpdateDto } from "src/cohort/dto/cohort-update.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesUpdateDto } from "src/fields/dto/field-values-update.dto"; -import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Fields } from "src/fields/entities/fields.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { PostgresFieldsService } from "./fields-adapter" -// import { FieldValues } from "src/fields/entities/field-values.entity"; -import { response } from "express"; -import APIResponse from "src/utils/response"; import { FieldValues } from "../../fields/entities/fields-values.entity"; -import { v4 as uuidv4 } from 'uuid'; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { isUUID } from "class-validator"; @@ -119,8 +112,7 @@ export class PostgresCohortService { public async getCohortDataWithCustomfield(cohortId: string) { const result = { - cohortData: { - } + cohortData: {} }; let customFieldsArray = []; @@ -163,7 +155,7 @@ export class PostgresCohortService { let cohortDetails = await this.cohortRepository.findOne({ where: whereClause }) - return cohortDetails; + return new ReturnResponseBody(cohortDetails); } async findCustomFields() { @@ -199,10 +191,29 @@ export class PostgresCohortService { ]); return result; } + public async validateFieldValues(field_value_array:string[]) { + let encounteredKeys = [] + for (const fieldValue of field_value_array) { + const [fieldId] = fieldValue.split(":").map(value => value.trim()); + + if (encounteredKeys.includes(fieldId)) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: `Duplicate fieldId '${fieldId}' found in fieldValues.`, + }); + } + encounteredKeys.push(fieldId); + + }; + } + public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try { - // console.log(request.user.userId) + let field_value_array = cohortCreateDto.fieldValues.split("|"); + //Check duplicate field + await this.validateFieldValues(field_value_array); + const decoded: any = jwt_decode(request.headers.authorization); cohortCreateDto.createdBy = decoded?.sub cohortCreateDto.updatedBy = decoded?.sub @@ -214,40 +225,54 @@ export class PostgresCohortService { const existData = await this.cohortRepository.find({ where: { name: cohortCreateDto.name, parentId: cohortCreateDto.parentId } }) + if (existData.length == 0) { response = await this.cohortRepository.save(cohortCreateDto); } else { - return new SuccessResponse({ - statusCode: HttpStatus.CONFLICT, - message: "Cohort name already exist for this parent.", - data: existData, - }); + if (existData[0].status == false) { + const updateData = { status: true }; + const cohortId = existData[0].cohortId; + await this.cohortRepository.update(cohortId, updateData); + const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + response = cohortData[0]; + }else{ + return new SuccessResponse({ + statusCode: HttpStatus.CONFLICT, + message: "Cohort name already exist for this parent.", + data: existData, + }); + } } } else { const existData = await this.cohortRepository.find({ where: { name: cohortCreateDto.name } }) + if (existData.length == 0) { response = await this.cohortRepository.save(cohortCreateDto); } else { - return new SuccessResponse({ - statusCode: HttpStatus.CONFLICT, - message: "Cohort name already exists.", - data: existData, - }); + if (existData[0].status == false) { + const updateData = { status: true }; + const cohortId = existData[0].cohortId; + await this.cohortRepository.update(cohortId, updateData); + const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + response = cohortData[0]; + } else { + return new SuccessResponse({ + statusCode: HttpStatus.CONFLICT, + message: "Cohort name already exists.", + data: existData, + }); + } } } - - + let cohortId = response?.cohortId; - - let field_value_array = cohortCreateDto.fieldValues.split("|"); - if (field_value_array.length > 0) { let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { + for (let i = 0; i < field_value_array.length; i++) { let fieldValues = field_value_array[i].split(":"); let fieldValueDto: FieldValuesDto = { value: fieldValues[1] ? fieldValues[1].trim() : "", @@ -258,12 +283,12 @@ export class PostgresCohortService { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; - const fieldValue = await this.fieldsService.createFieldValues(request, fieldValueDto); - } } + + response = new ReturnResponseBody(response); return new SuccessResponse({ statusCode: HttpStatus.CREATED, message: "Cohort Created Successfully.", @@ -271,10 +296,14 @@ export class PostgresCohortService { }); } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + if (e instanceof ErrorResponseTypeOrm) { + return e; + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.toString(), // or any custom error message you want + }); + } } } @@ -284,11 +313,15 @@ export class PostgresCohortService { cohortUpdateDto: CohortUpdateDto ) { try { + + let field_value_array = cohortUpdateDto.fieldValues.split("|"); + await this.validateFieldValues(field_value_array); + const decoded: any = jwt_decode(request.headers.authorization); cohortUpdateDto.updatedBy = decoded?.sub cohortUpdateDto.createdBy = decoded?.sub cohortUpdateDto.status = true; - + let response; if (!isUUID(cohortId)) { return new ErrorResponseTypeOrm({ @@ -314,20 +347,59 @@ export class PostgresCohortService { } } - const response = await this.cohortRepository.update(cohortId, updateData); - + if (cohortUpdateDto.name && cohortUpdateDto.parentId) { + const existData = await this.cohortRepository.find({ + where: { name: cohortUpdateDto.name, parentId: cohortUpdateDto.parentId } + }) + + if (existData.length == 0) { + response = await this.cohortRepository.update(cohortId, updateData); + } else { + if (existData[0].status == false) { + const updateData = { status: true }; + const cohortId = existData[0].cohortId; + await this.cohortRepository.update(cohortId, updateData); + const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + response = cohortData[0]; + }else{ + return new SuccessResponse({ + statusCode: HttpStatus.CONFLICT, + message: "Cohort name already exist for this parent please choose another name.", + data: existData, + }); + } + } + } else { + const existData = await this.cohortRepository.find({ + where: { name: cohortUpdateDto.name } + }) + + if (existData.length == 0) { + response = await this.cohortRepository.update(cohortId, updateData); + } else { + if (existData[0].status == false) { + const updateData = { status: true }; + const cohortId = existData[0].cohortId; + await this.cohortRepository.update(cohortId, updateData); + const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + response = cohortData[0]; + } else { + return new SuccessResponse({ + statusCode: HttpStatus.CONFLICT, + message: "Cohort name already exists please choose another name.", + data: existData, + }); + } + } + } if (fieldValueData['fieldValues']) { - - let field_value_array = cohortUpdateDto.fieldValues.split("|"); if (field_value_array.length > 0) { for (let i = 0; i < field_value_array.length; i++) { let fieldValues = field_value_array[i].split(":"); let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; try { - console.log("hii"); - const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) const rowid = fieldVauesRowId.fieldValuesId; @@ -337,8 +409,6 @@ export class PostgresCohortService { }; await this.fieldsService.updateFieldValues(rowid, fieldValueUpdateDto); } catch { - console.log("hii1"); - let fieldValueDto: FieldValuesDto = { value: fieldValues[1] ? fieldValues[1].trim() : "", itemId: cohortId, @@ -349,7 +419,7 @@ export class PostgresCohortService { updatedAt: new Date().toISOString(), }; // console.log(fieldValueDto); - + await this.fieldsService.createFieldValues(request, fieldValueDto); } } @@ -370,10 +440,14 @@ export class PostgresCohortService { }); } } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + if (e instanceof ErrorResponseTypeOrm) { + return e; + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.toString(), // or any custom error message you want + }); + } } } @@ -391,9 +465,6 @@ export class PostgresCohortService { offset = (limit) * (page - 1); } - if (limit === 0) { - limit = 0; - } const MAX_LIMIT = 20; const PAGE_LIMIT = 100000; @@ -412,17 +483,36 @@ export class PostgresCohortService { }); } + const allowedKeys = ["userId", "cohortId", "programId", "parentId", "name", "type", "status", "createdBy", "updatedBy"]; const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; + if (!allowedKeys.includes(key)) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `${key} Invalid key`, + }); + } else { + whereClause[key] = value; + } }); } + + let results = { cohortDetails: [], }; if (whereClause['userId']) { + const additionalFields = Object.keys(whereClause).filter(key => key !== 'userId'); + if (additionalFields.length > 0) { + // Handle the case where userId is provided along with other fields + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "When filtering by userId, do not include additional fields.", + }); + } const [cohortData] = await this.cohortMembersRepository.findAndCount({ where: whereClause, skip: offset, @@ -462,36 +552,17 @@ export class PostgresCohortService { } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + if (e instanceof ErrorResponseTypeOrm) { + return e; + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.toString(), // or any custom error message you want + }); + } } } - public async mappedResponse(result: any) { - const cohortValueResponse = result.map((item: any) => { - const cohortMapping = { - tenantId: item?.tenantId ? `${item.tenantId}` : "", - programId: item?.programId ? `${item.programId}` : "", - cohortId: item?.cohortId ? `${item.cohortId}` : "", - parentId: item?.parentId ? `${item.parentId}` : "", - name: item?.name ? `${item.name}` : "", - type: item?.type ? `${item.type}` : "", - status: item?.status ? `${item.status}` : "", - image: item?.image ? `${item.image}` : "", - createdAt: item?.createdAt ? `${item.createdAt}` : "", - updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", - createdBy: item?.createdBy ? `${item.createdBy}` : "", - updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", - referenceId: item?.referenceId ? `${item.referenceId}` : "", - metadata: item?.metadata ? `${item.metadata}` : "", - }; - return new CohortDto(cohortMapping); - }) - return cohortValueResponse; - - } public async updateCohortStatus( cohortId: string, @@ -518,12 +589,12 @@ export class PostgresCohortService { await this.cohortRepository.query(query, [cohortId]); await this.cohortMembersRepository.delete( - {cohortId:cohortId} + { cohortId: cohortId } ); await this.fieldValuesRepository.delete( - {itemId:cohortId} + { itemId: cohortId } ); - + return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -547,7 +618,8 @@ export class PostgresCohortService { const existData = await this.cohortRepository.find({ where: { - cohortId: id + cohortId: id, + status: true } }) if (existData.length !== 0) { diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 86b0fb73..cf10de35 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -47,7 +47,7 @@ import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") @Controller("cohorts") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) export class CohortController { constructor(private readonly cohortAdapter: CohortAdapter) { } @@ -101,6 +101,12 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { + const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues' ]; + const unexpectedFields = Object.keys(cohortCreateDto).filter(field => !expectedFields.includes(field)); + if (unexpectedFields.length > 0) { + throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); + } + let tenantid = headers["tenantid"]; const payload = { image: image?.filename, @@ -171,6 +177,11 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { + const expectedFields = ['cohortId','programId', 'parentId', 'name', 'type', 'fieldValues' ]; + const unexpectedFields = Object.keys(cohortUpdateDto).filter(field => !expectedFields.includes(field)); + if (unexpectedFields.length > 0) { + throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); + } const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( cohortId, request, diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index efc6af69..c113cd5a 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -1,7 +1,108 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsNumber, IsNumberString, IsObject } from "class-validator"; +import { IsNumber, IsNumberString, IsObject, IsOptional, IsString } from "class-validator"; import { CohortDto } from "./cohort.dto"; +import { Expose } from "class-transformer"; +export class setFilters { + //userIdBy + @ApiProperty({ + type: String, + description: "The cohort is createdBy", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + userId?: string; + + //userIdBy + @ApiProperty({ + type: String, + description: "The cohort is createdBy", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + cohortId?: string; + + //programId + @ApiPropertyOptional({ + type: String, + description: "The programId of the cohort", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + programId?: string; + + //parentId + @ApiPropertyOptional({ + type: String, + description: "The parentId of the cohort", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + parentId?: string; + + //name + @ApiProperty({ + type: String, + description: "The name of the cohort", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + name?: string; + + //type + @ApiProperty({ + type: String, + description: "The type of the cohort", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + type?: string; + + //status + @ApiPropertyOptional({ + type: Boolean, + description: "The status of the cohort", + default: true, + }) + @Expose() + @IsOptional() + @IsString() + status?: boolean; + + //createdBy + @ApiProperty({ + type: String, + description: "The cohort is createdBy", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + createdBy?: string; + + //updatedBy + @ApiProperty({ + type: String, + description: "The cohort is updatedBy", + default: "", + }) + @Expose() + @IsOptional() + @IsString() + updatedBy?: string; +} export class CohortSearchDto { @ApiProperty({ @@ -19,7 +120,7 @@ export class CohortSearchDto { page: number; @ApiProperty({ - type: CohortDto, + type: setFilters, description: "Filters", }) @IsObject() diff --git a/src/cohort/dto/cohort.dto.ts b/src/cohort/dto/cohort.dto.ts index 87cc65e0..31dce917 100644 --- a/src/cohort/dto/cohort.dto.ts +++ b/src/cohort/dto/cohort.dto.ts @@ -15,9 +15,9 @@ export class CohortDto { @Expose() cohortId: string; @Expose() - createdAt: string; + createdAt: Date; @Expose() - updatedAt: string; + updatedAt: Date; //programId @ApiPropertyOptional({ @@ -119,3 +119,27 @@ export class CohortDto { Object.assign(this, obj); } } + +export class ReturnResponseBody{ + @Expose() + cohortId: string; + @Expose() + parentId: string; + @Expose() + name: string; + @Expose() + type: string; + @Expose() + status: boolean; + @Expose() + tenantId: string; + + constructor(cohortDto: CohortDto) { + this.cohortId = cohortDto.cohortId; + this.parentId = cohortDto.parentId; + this.name = cohortDto.name; + this.type = cohortDto.type; + this.status = cohortDto.status; + this.tenantId = cohortDto.tenantId; + } +} From 093cd07c9e1ee49b0011428201909c60f1ce8ea6 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 2 May 2024 10:42:46 +0530 Subject: [PATCH 293/408] Change the validator for the status property from IsString to IsBoolean --- src/cohort/dto/cohort-search.dto.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index c113cd5a..0d6b4ded 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsNumber, IsNumberString, IsObject, IsOptional, IsString } from "class-validator"; +import { IsBoolean, IsNumber, IsNumberString, IsObject, IsOptional, IsString } from "class-validator"; import { CohortDto } from "./cohort.dto"; import { Expose } from "class-transformer"; @@ -78,7 +78,7 @@ export class setFilters { }) @Expose() @IsOptional() - @IsString() + @IsBoolean() status?: boolean; //createdBy From ca3f49a12c38508d171b1fc8ccea7ed586ed90e5 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 2 May 2024 10:46:02 +0530 Subject: [PATCH 294/408] Correct the type of the filters property to setFilters for better type safety. --- src/cohort/dto/cohort-search.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index 0d6b4ded..a083ba88 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -124,7 +124,7 @@ export class CohortSearchDto { description: "Filters", }) @IsObject() - filters: object; + filters: setFilters; constructor(partial: Partial) { Object.assign(this, partial); From 953217f433bb729ec99cfac4712c8ba7fd93b22d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 2 May 2024 16:43:27 +0530 Subject: [PATCH 295/408] Jira Tusk #PS-267 API to map a user to multiple tenants --- src/adapters/assigntenantlocator.ts | 2 - src/adapters/hasura/assigntenant.adapter.ts | 4 - src/adapters/postgres/assigntenant-adapter.ts | 3 - src/adapters/postgres/potsgres-module.ts | 28 +-- src/adapters/postgres/user-adapter.ts | 166 +++++++++++++++--- src/app.module.ts | 2 +- src/assign-tenant/assign-tenant.controller.ts | 40 ----- .../dto/assign-tenant-update.dto.ts | 54 ------ src/user/dto/user-create.dto.ts | 15 +- src/user/user.controller.ts | 10 +- src/user/user.module.ts | 4 +- 11 files changed, 179 insertions(+), 149 deletions(-) delete mode 100644 src/assign-tenant/dto/assign-tenant-update.dto.ts diff --git a/src/adapters/assigntenantlocator.ts b/src/adapters/assigntenantlocator.ts index 3e6e6696..2f1b6387 100644 --- a/src/adapters/assigntenantlocator.ts +++ b/src/adapters/assigntenantlocator.ts @@ -1,6 +1,4 @@ import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; -import { UpdateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-update.dto"; export interface IServicelocatorassignTenant { createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto); - // updateAssignTenant(request: any, updateAssignTenantDto:UpdateAssignTenantDto); } \ No newline at end of file diff --git a/src/adapters/hasura/assigntenant.adapter.ts b/src/adapters/hasura/assigntenant.adapter.ts index 88d06ae1..79f22a79 100644 --- a/src/adapters/hasura/assigntenant.adapter.ts +++ b/src/adapters/hasura/assigntenant.adapter.ts @@ -5,8 +5,6 @@ import { In, Repository } from 'typeorm'; import { UserTenantMapping } from 'src/assign-tenant/entities/assign-tenant.entity'; import { Role } from "src/rbac/role/entities/role.entity"; import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; -import { UpdateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-update.dto"; - @Injectable() export class HasuraAssignTenantService { @@ -17,7 +15,5 @@ export class HasuraAssignTenantService { ) { } public async createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto) { } - public async updateAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto) { - } } diff --git a/src/adapters/postgres/assigntenant-adapter.ts b/src/adapters/postgres/assigntenant-adapter.ts index 97981072..69d9b9ba 100644 --- a/src/adapters/postgres/assigntenant-adapter.ts +++ b/src/adapters/postgres/assigntenant-adapter.ts @@ -119,7 +119,4 @@ export class PostgresAssignTenantService { } } - public async updateAssignTenant(request: any, createAssignTenantDto: CreateAssignTenantDto) { - } - } diff --git a/src/adapters/postgres/potsgres-module.ts b/src/adapters/postgres/potsgres-module.ts index 89daa617..daf55b93 100644 --- a/src/adapters/postgres/potsgres-module.ts +++ b/src/adapters/postgres/potsgres-module.ts @@ -12,20 +12,23 @@ import { AttendanceEntity } from "src/attendance/entities/attendance.entity"; import { PostgresAttendanceService } from "./attendance-adapter"; import { PostgresFieldsService } from "./fields-adapter"; import { Cohort } from "src/cohort/entities/cohort.entity"; - +import { UserTenantMapping } from "src/assign-tenant/entities/assign-tenant.entity"; +import { Tenants } from "src/assign-tenant/entities/tenant.entity"; @Module({ imports: [HttpModule, - TypeOrmModule.forFeature([ - User, - Field, - FieldValues, - CohortMembers, - AttendanceEntity, - Fields, - Cohort - ]) + TypeOrmModule.forFeature([ + User, + Field, + FieldValues, + CohortMembers, + AttendanceEntity, + Fields, + Cohort, + UserTenantMapping, + Tenants + ]) ], providers: [ PostgresUserService, @@ -37,6 +40,5 @@ import { Cohort } from "src/cohort/entities/cohort.entity"; PostgresAttendanceService, PostgresFieldsService ], - }) - export class PostgresModule {} - \ No newline at end of file +}) +export class PostgresModule { } diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 65f118d6..7eb17a52 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -19,7 +19,9 @@ import axios, { AxiosInstance, AxiosRequestConfig } from "axios" import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { isUUID } from 'class-validator'; import { UserSearchDto } from 'src/user/dto/user-search.dto'; - +import { UserTenantMapping } from "src/assign-tenant/entities/assign-tenant.entity"; +import { Tenants } from "src/assign-tenant/entities/tenant.entity"; +import { ResponseAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; @Injectable() export class PostgresUserService { @@ -33,18 +35,23 @@ export class PostgresUserService { @InjectRepository(Field) private fieldsRepository: Repository, @InjectRepository(CohortMembers) - private cohortMemberRepository: Repository + private cohortMemberRepository: Repository, + @InjectRepository(UserTenantMapping) + private userTenantMappingRepository: Repository, + @InjectRepository(Tenants) + private tenantsRepository: Repository ) { } - async searchUser(tenantId: string, + async searchUser(tenantId: string, request: any, response: any, - userSearchDto: UserSearchDto){ + userSearchDto: UserSearchDto) { try { let findData = await this.findAllUserDetails(userSearchDto); - if(!findData){ - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: 'No Data Found For User',}); + if (!findData) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'No Data Found For User', + }); } return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -59,7 +66,7 @@ export class PostgresUserService { } } - async findAllUserDetails(userSearchDto){ + async findAllUserDetails(userSearchDto) { let { limit, page, filters } = userSearchDto; let offset = 0; @@ -89,8 +96,8 @@ export class PostgresUserService { try { if (!isUUID(userData.userId)) { return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: 'Please Enter Valid User ID', + statusCode: HttpStatus.BAD_REQUEST, + message: 'Please Enter Valid User ID', }); } const result = { @@ -103,13 +110,13 @@ export class PostgresUserService { this.findFilledValues(userData.userId), this.findUserDetails(userData.userId) ]); - if(!userDetails){ + if (!userDetails) { return new SuccessResponse({ statusCode: HttpStatus.NOT_FOUND, message: 'User Not Found', }); } - if(!userData.fieldValue){ + if (!userData.fieldValue) { return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', @@ -333,6 +340,10 @@ export class PostgresUserService { userCreateDto.createdBy = decoded?.sub userCreateDto.updatedBy = decoded?.sub + //Check duplicate field entry + let field_value_array = userCreateDto.fieldValues.split("|"); + await this.validateFieldValues(field_value_array); + userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); const userSchema = new UserCreateDto(userCreateDto); @@ -360,9 +371,71 @@ export class PostgresUserService { } ); userCreateDto.userId = resKeycloak; + + + // Check if tenant array is not empty + const tenantIds = userCreateDto.tenantId; + const userId = userCreateDto.userId; + let errors = []; + + if (!tenantIds || tenantIds.length === 0) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: "Tenants array cannot be empty.", + }); + } + + for (const tenantId of tenantIds) { + let findExistingRole = await this.userTenantMappingRepository.findOne({ + where: { + userId: userId, + tenantId: tenantId, + }, + }); + if (findExistingRole) { + errors.push({ + errorMessage: `User is already exist in ${tenantId} Tenant.`, + }); + continue; + } + + // User is exist in user table + let userExist = await this.usersRepository.findOne({ + where: { + userId: userId, + }, + }); + if (!userExist) { + errors.push({ + errorMessage: `User ${userId} is not exist.`, + }); + continue; + } + + // User is exist in user table + let tenantExist = await this.tenantsRepository.findOne({ + where: { + tenantId: tenantId, + }, + }); + if (!tenantExist) { + errors.push({ + errorMessage: `Tenant ${tenantId} is not exist.`, + }); + continue; + } + } + if (errors.length > 0) { + return { + statusCode: HttpStatus.BAD_REQUEST, + errorCount: errors.length, + errors, + }; + } + + let result = await this.createUserInDatabase(request, userCreateDto, cohortId); - - let field_value_array = userCreateDto.fieldValues?.split("|"); + let fieldData = {}; if (result && field_value_array?.length > 0) { let userId = result?.userId; @@ -376,7 +449,7 @@ export class PostgresUserService { if (!result) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: `Error is ${result}`, + errorMessage: `Error is ${result}`, }); } } @@ -389,7 +462,7 @@ export class PostgresUserService { } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: `Error is ${e}`, + errorMessage: `Error is ${e}`, }); } } @@ -414,14 +487,14 @@ export class PostgresUserService { user.name = userCreateDto?.name user.role = userCreateDto?.role user.mobile = Number(userCreateDto?.mobile) || null, - user.tenantId = userCreateDto?.tenantId + user.tenantId = null user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, - user.state = userCreateDto?.state, - user.district = userCreateDto?.district, - user.address = userCreateDto?.address, - user.pincode = userCreateDto?.pincode + user.state = userCreateDto?.state, + user.district = userCreateDto?.district, + user.address = userCreateDto?.address, + user.pincode = userCreateDto?.pincode if (userCreateDto?.dob) { user.dob = new Date(userCreateDto.dob); @@ -432,16 +505,45 @@ export class PostgresUserService { let cohortData = { userId: result?.userId, role: result?.role, - // createdBy:result?.userId, - // updatedBy:result?.userId, tenantId: result?.tenantId, cohortId: cohortId } await this.addCohortMember(cohortData); + + let tenantsData = { + userId: result?.userId, + tenantIds: userCreateDto?.tenantId, + } + await this.assignUserToTenant(tenantsData, request); } return result; } + async assignUserToTenant(tenantsData, request) { + try { + const tenantIds = tenantsData.tenantIds; + const userId = tenantsData.userId; + let result = []; + let errors = []; + + for (const tenantId of tenantIds) { + + + + const data = await this.userTenantMappingRepository.save({ + userId: userId, + tenantId: tenantId, + createdBy: request['user'].userId, + updatedBy: request['user'].userId + }) + + // result.push(new ResponseAssignTenantDto(data, `Tenant assigned successfully to the user.`)); + } + } catch (error) { + throw new Error(error) + } + } + async addCohortMember(cohortData) { try { let result = await this.cohortMemberRepository.insert(cohortData); @@ -566,6 +668,22 @@ export class PostgresUserService { } } + public async validateFieldValues(field_value_array:string[]) { + let encounteredKeys = [] + for (const fieldValue of field_value_array) { + const [fieldId] = fieldValue.split(":").map(value => value.trim()); + + if (encounteredKeys.includes(fieldId)) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: `Duplicate fieldId '${fieldId}' found in fieldValues.`, + }); + } + encounteredKeys.push(fieldId); + + }; +} + } diff --git a/src/app.module.ts b/src/app.module.ts index d2bd8266..8e1d8b89 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -31,11 +31,11 @@ import { AssignTenantModule } from './assign-tenant/assign-tenant.module'; AttendanceModule, CohortModule, CohortMembersModule, + AssignTenantModule, FieldsModule, AuthModule, AuthRbacModule, DatabaseModule, - AssignTenantModule, ], controllers: [AppController], providers: [AppService], diff --git a/src/assign-tenant/assign-tenant.controller.ts b/src/assign-tenant/assign-tenant.controller.ts index 8146c94c..883f00eb 100644 --- a/src/assign-tenant/assign-tenant.controller.ts +++ b/src/assign-tenant/assign-tenant.controller.ts @@ -32,7 +32,6 @@ import { FileInterceptor } from "@nestjs/platform-express"; import { Response, response } from "express"; import { AssignTenantAdapter } from "./assign-tenant.apater"; import { CreateAssignTenantDto } from "./dto/assign-tenant-create.dto"; -import { UpdateAssignTenantDto } from "./dto/assign-tenant-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("AssignTenant") @@ -56,9 +55,6 @@ export class AssignTenantController { @Res() response: Response ) { - // createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto); - // updateAssignTenant(request: any, updateAssignTenantDto:UpdateAssignTenantDto); - const result = await this.assignTenantAdapter.buildassignTenantAdapter().createAssignTenant( request, createAssignTenantDto @@ -66,40 +62,4 @@ export class AssignTenantController { return response.status(result.statusCode).json(result); } - - - - - //update - // @Put("/:cohortId") - // @ApiConsumes("multipart/form-data") - // @ApiBasicAuth("access-token") - // @UseInterceptors( - // FileInterceptor("image", { - // storage: diskStorage({ - // destination: process.env.IMAGEPATH, - // filename: editFileName, - // }), - // fileFilter: imageFileFilter, - // }) - // ) - // @ApiBody({ type: CohortUpdateDto }) - // @ApiOkResponse({ description: "Cohort has been updated successfully" }) - // @ApiBadRequestResponse({ description: "Bad request." }) - // @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) - - // public async updateCohort( - // @Param("cohortId") cohortId: string, - // @Req() request: Request, - // @Body() cohortUpdateDto: CohortUpdateDto, - // @UploadedFile() image, - // @Res() response: Response - // ) { - // const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( - // cohortId, - // request, - // cohortUpdateDto - // ); - // return response.status(result.statusCode).json(result); - // } } diff --git a/src/assign-tenant/dto/assign-tenant-update.dto.ts b/src/assign-tenant/dto/assign-tenant-update.dto.ts deleted file mode 100644 index aa3fc933..00000000 --- a/src/assign-tenant/dto/assign-tenant-update.dto.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Expose } from "class-transformer"; -import { ApiProperty } from "@nestjs/swagger"; -import { IsNotEmpty, IsString, IsUUID, IsArray } from "class-validator"; - -export class UpdateAssignTenantDto { - @ApiProperty({ - type: String, - description: "User Id of User", - default: "", - }) - @Expose() - @IsNotEmpty() - @IsUUID() - userId: string; - - - @ApiProperty({ - type: String, - description: "Tenant Id", - default: [], - }) - @Expose() - @IsArray() - @IsUUID(undefined, { each: true }) - @IsNotEmpty({ each: true }) - tenantId: string; - - constructor(obj: any) { - Object.assign(this, obj); - } - -} - -// export class ResponseAssignRoleDto { -// @Expose() -// userId: string; - -// @Expose() -// roleId: string; - -// @Expose() -// tenantId: string; - -// @Expose() -// message: string; - -// constructor(data: { userId: string; roleId: string; tenantId: string }, message: string) { -// this.userId = data.userId; -// this.roleId = data.roleId; -// this.tenantId = data.tenantId; -// this.message = message; -// } -// } - diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 7b0a73c6..d1c83172 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -5,13 +5,13 @@ import { IsEmail, IsString, IsNumber, + IsArray, + IsUUID, } from "class-validator"; import { User } from "../entities/user-entity"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class UserCreateDto { - @Expose() - tenantId: string; @Expose() userId: string; @@ -124,6 +124,17 @@ export class UserCreateDto { @Expose() fieldValues: string; + @ApiProperty({ + type: String, + description: "Tenant Id", + default: [], + }) + @Expose() + @IsArray() + @IsUUID(undefined, { each: true }) + @IsNotEmpty({ each: true }) + tenantId: string; + constructor(partial: Partial) { Object.assign(this, partial); } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 29ea8a07..3f157e84 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -84,16 +84,16 @@ export class UserController { @ApiBody({ type: UserCreateDto }) @ApiForbiddenResponse({ description: "User Already Exists"}) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) - @ApiHeader({ - name: "tenantid", - }) + // @ApiHeader({ + // name: "tenantid", + // }) async createUser( - @Headers() headers, + // @Headers() headers, @Req() request: Request, @Body() userCreateDto: UserCreateDto, @Res() response: Response ) { - userCreateDto.tenantId = headers["tenantid"]; + // userCreateDto.tenantId = headers["tenantid"]; const result = await this.userAdapter.buildUserAdapter().createUser(request, userCreateDto); return response.status(result.statusCode).json(result); } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 43abf0cb..a2776f8a 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -9,10 +9,12 @@ import { User } from "./entities/user-entity"; import { FieldValues } from "./entities/field-value-entities"; import { Field } from "./entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; +import { UserTenantMapping } from "src/assign-tenant/entities/assign-tenant.entity"; +import { Tenants } from "src/assign-tenant/entities/tenant.entity"; @Module({ imports: [ - TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers]), + TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers,UserTenantMapping,Tenants]), HttpModule, HasuraModule, PostgresModule, From 7a68a84f539e5364adf743156b2900cbf98b6c6a Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 3 May 2024 12:28:23 +0530 Subject: [PATCH 296/408] Resolve PR chnages --- src/adapters/assigntenantlocator.ts | 4 +- src/adapters/hasura/assigntenant.adapter.ts | 19 ---------- .../hasura/usertenantmapping.adapter.ts | 17 +++++++++ src/adapters/postgres/potsgres-module.ts | 4 +- src/adapters/postgres/user-adapter.ts | 5 +-- ...dapter.ts => usertenantmapping-adapter.ts} | 38 ++++++++----------- src/app.module.ts | 2 +- src/user/dto/user-create.dto.ts | 2 +- src/user/user.controller.ts | 5 --- src/user/user.module.ts | 4 +- .../assign-tenant-mapping.controller.spec.ts} | 2 +- .../assign-tenant-mapping.module.ts} | 12 +++--- .../dto/user-tenant-mapping.dto.ts} | 2 +- .../entities/tenant.entity.ts | 6 --- .../entities/user-tenant-mapping.entity.ts} | 0 .../user-tenant-mapping.apater.ts} | 6 +-- .../user-tenant-mapping.controller.ts} | 13 +++---- 17 files changed, 59 insertions(+), 82 deletions(-) delete mode 100644 src/adapters/hasura/assigntenant.adapter.ts create mode 100644 src/adapters/hasura/usertenantmapping.adapter.ts rename src/adapters/postgres/{assigntenant-adapter.ts => usertenantmapping-adapter.ts} (70%) rename src/{assign-tenant/assign-tenant.controller.spec.ts => userTenantMapping/assign-tenant-mapping.controller.spec.ts} (86%) rename src/{assign-tenant/assign-tenant.module.ts => userTenantMapping/assign-tenant-mapping.module.ts} (76%) rename src/{assign-tenant/dto/assign-tenant-create.dto.ts => userTenantMapping/dto/user-tenant-mapping.dto.ts} (96%) rename src/{assign-tenant => userTenantMapping}/entities/tenant.entity.ts (86%) rename src/{assign-tenant/entities/assign-tenant.entity.ts => userTenantMapping/entities/user-tenant-mapping.entity.ts} (100%) rename src/{assign-tenant/assign-tenant.apater.ts => userTenantMapping/user-tenant-mapping.apater.ts} (80%) rename src/{assign-tenant/assign-tenant.controller.ts => userTenantMapping/user-tenant-mapping.controller.ts} (79%) diff --git a/src/adapters/assigntenantlocator.ts b/src/adapters/assigntenantlocator.ts index 2f1b6387..039d111a 100644 --- a/src/adapters/assigntenantlocator.ts +++ b/src/adapters/assigntenantlocator.ts @@ -1,4 +1,4 @@ -import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; +import { AssignTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; export interface IServicelocatorassignTenant { - createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto); + userTenantMapping(request: any, assignTenantMappingDto:AssignTenantMappingDto); } \ No newline at end of file diff --git a/src/adapters/hasura/assigntenant.adapter.ts b/src/adapters/hasura/assigntenant.adapter.ts deleted file mode 100644 index 79f22a79..00000000 --- a/src/adapters/hasura/assigntenant.adapter.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { In, Repository } from 'typeorm'; -// import { UserRoleMapping } from 'src/rbac/assign-role/entities/assign-role.entity'; -import { UserTenantMapping } from 'src/assign-tenant/entities/assign-tenant.entity'; -import { Role } from "src/rbac/role/entities/role.entity"; -import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; - -@Injectable() -export class HasuraAssignTenantService { - constructor( - @InjectRepository(UserTenantMapping) - private userTenantMappingRepository: Repository, - - ) { } - public async createAssignTenant(request: any, createAssignTenantDto:CreateAssignTenantDto) { - } - -} diff --git a/src/adapters/hasura/usertenantmapping.adapter.ts b/src/adapters/hasura/usertenantmapping.adapter.ts new file mode 100644 index 00000000..f2e05e83 --- /dev/null +++ b/src/adapters/hasura/usertenantmapping.adapter.ts @@ -0,0 +1,17 @@ +import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { In, Repository } from 'typeorm'; +import { UserTenantMapping } from 'src/userTenantMapping/entities/user-tenant-mapping.entity'; +import { AssignTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; + +@Injectable() +export class HasuraAssignTenantService { + constructor( + @InjectRepository(UserTenantMapping) + private userTenantMappingRepository: Repository, + + ) { } + public async userTenantMapping(request: any, assignTenantMappingDto:AssignTenantMappingDto) { + } + +} diff --git a/src/adapters/postgres/potsgres-module.ts b/src/adapters/postgres/potsgres-module.ts index daf55b93..07a020da 100644 --- a/src/adapters/postgres/potsgres-module.ts +++ b/src/adapters/postgres/potsgres-module.ts @@ -12,8 +12,8 @@ import { AttendanceEntity } from "src/attendance/entities/attendance.entity"; import { PostgresAttendanceService } from "./attendance-adapter"; import { PostgresFieldsService } from "./fields-adapter"; import { Cohort } from "src/cohort/entities/cohort.entity"; -import { UserTenantMapping } from "src/assign-tenant/entities/assign-tenant.entity"; -import { Tenants } from "src/assign-tenant/entities/tenant.entity"; +import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; +import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; @Module({ diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 7eb17a52..5a238971 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -19,9 +19,8 @@ import axios, { AxiosInstance, AxiosRequestConfig } from "axios" import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { isUUID } from 'class-validator'; import { UserSearchDto } from 'src/user/dto/user-search.dto'; -import { UserTenantMapping } from "src/assign-tenant/entities/assign-tenant.entity"; -import { Tenants } from "src/assign-tenant/entities/tenant.entity"; -import { ResponseAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; +import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; +import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; @Injectable() export class PostgresUserService { diff --git a/src/adapters/postgres/assigntenant-adapter.ts b/src/adapters/postgres/usertenantmapping-adapter.ts similarity index 70% rename from src/adapters/postgres/assigntenant-adapter.ts rename to src/adapters/postgres/usertenantmapping-adapter.ts index 69d9b9ba..772fb0f4 100644 --- a/src/adapters/postgres/assigntenant-adapter.ts +++ b/src/adapters/postgres/usertenantmapping-adapter.ts @@ -1,13 +1,12 @@ import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { In, Repository } from 'typeorm'; -import { UserTenantMapping } from 'src/assign-tenant/entities/assign-tenant.entity'; -import { CreateAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; -import { ResponseAssignTenantDto } from "src/assign-tenant/dto/assign-tenant-create.dto"; +import { UserTenantMapping } from 'src/userTenantMapping/entities/user-tenant-mapping.entity'; +import { AssignTenantMappingDto,ResponseAssignTenantDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { SuccessResponse } from 'src/success-response'; import { User } from "src/user/entities/user-entity"; -import { Tenants } from "src/assign-tenant/entities/tenant.entity"; +import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; @Injectable() @@ -20,27 +19,26 @@ export class PostgresAssignTenantService { @InjectRepository(Tenants) private tenantsRepository: Repository, ) { } - public async createAssignTenant(request: any, createAssignTenantDto: CreateAssignTenantDto) { + + public async userTenantMapping(request: any, assignTenantMappingDto: AssignTenantMappingDto) { try { - const userId = createAssignTenantDto.userId; - const tenantIds = createAssignTenantDto.tenantId; + const userId = assignTenantMappingDto.userId; + const tenantIds = assignTenantMappingDto.tenantId; // Check if tenant array is not empty if (!tenantIds || tenantIds.length === 0) { return new SuccessResponse({ statusCode: HttpStatus.BAD_REQUEST, - message: "Roles array cannot be empty.", + message: "Please provide at least one tenant Id", }); } + let result = []; let errors = []; for (const tenantId of tenantIds) { - // If role already exists for user, return error response - console.log(userId); - console.log(tenantId); - + // check if user tenant mapping exists. let findExistingRole = await this.userTenantMappingRepository.findOne({ where: { userId: userId, @@ -54,7 +52,7 @@ export class PostgresAssignTenantService { continue; } - // User is exist in user table + // check if user exists let userExist = await this.userRepository.findOne({ where: { userId: userId, @@ -62,12 +60,12 @@ export class PostgresAssignTenantService { }); if (!userExist) { errors.push({ - errorMessage: `User ${userId} is not exist.`, + errorMessage: `User ${userId} does not exist.`, }); continue; } - // User is exist in user table + // check if tenant exists let tenantExist = await this.tenantsRepository.findOne({ where: { tenantId: tenantId, @@ -75,7 +73,7 @@ export class PostgresAssignTenantService { }); if (!tenantExist) { errors.push({ - errorMessage: `Tenant ${tenantId} is not exist.`, + errorMessage: `Tenant ${tenantId} does not exist.`, }); continue; } @@ -88,7 +86,7 @@ export class PostgresAssignTenantService { updatedBy: request['user'].userId }) - result.push(new ResponseAssignTenantDto(data, `Tenant assigned successfully to the user.`)); + result.push(new ResponseAssignTenantDto(data, `User is successfully added to the Tenants.`)); } if (result.length == 0) { @@ -106,12 +104,6 @@ export class PostgresAssignTenantService { errors, }; } catch (error) { - if (error.code === '23503') { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: `User Id or Role Id Doesn't Exist in Database ` - }); - } return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: JSON.stringify(error) diff --git a/src/app.module.ts b/src/app.module.ts index 8e1d8b89..c831791e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,7 +18,7 @@ import { FieldsModule } from "./fields/fields.module"; import { AttendanceModule } from "./attendance/attendance.module"; import { UserModule } from "./user/user.module"; import { RbacModule } from "./rbac/rbac.module"; -import { AssignTenantModule } from './assign-tenant/assign-tenant.module'; +import { AssignTenantModule } from './userTenantMapping/assign-tenant-mapping.module'; @Module({ imports: [ diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index d1c83172..b2d6b4d1 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -133,7 +133,7 @@ export class UserCreateDto { @IsArray() @IsUUID(undefined, { each: true }) @IsNotEmpty({ each: true }) - tenantId: string; + tenantId: string[]; constructor(partial: Partial) { Object.assign(this, partial); diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 3f157e84..c0382ad7 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -84,16 +84,11 @@ export class UserController { @ApiBody({ type: UserCreateDto }) @ApiForbiddenResponse({ description: "User Already Exists"}) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) - // @ApiHeader({ - // name: "tenantid", - // }) async createUser( - // @Headers() headers, @Req() request: Request, @Body() userCreateDto: UserCreateDto, @Res() response: Response ) { - // userCreateDto.tenantId = headers["tenantid"]; const result = await this.userAdapter.buildUserAdapter().createUser(request, userCreateDto); return response.status(result.statusCode).json(result); } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index a2776f8a..03d83d8c 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -9,8 +9,8 @@ import { User } from "./entities/user-entity"; import { FieldValues } from "./entities/field-value-entities"; import { Field } from "./entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; -import { UserTenantMapping } from "src/assign-tenant/entities/assign-tenant.entity"; -import { Tenants } from "src/assign-tenant/entities/tenant.entity"; +import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; +import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; @Module({ imports: [ diff --git a/src/assign-tenant/assign-tenant.controller.spec.ts b/src/userTenantMapping/assign-tenant-mapping.controller.spec.ts similarity index 86% rename from src/assign-tenant/assign-tenant.controller.spec.ts rename to src/userTenantMapping/assign-tenant-mapping.controller.spec.ts index 3e76c67f..91860489 100644 --- a/src/assign-tenant/assign-tenant.controller.spec.ts +++ b/src/userTenantMapping/assign-tenant-mapping.controller.spec.ts @@ -1,5 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { AssignTenantController } from './assign-tenant.controller'; +import { AssignTenantController } from './user-tenant-mapping.controller'; describe('AssignTenantController', () => { let controller: AssignTenantController; diff --git a/src/assign-tenant/assign-tenant.module.ts b/src/userTenantMapping/assign-tenant-mapping.module.ts similarity index 76% rename from src/assign-tenant/assign-tenant.module.ts rename to src/userTenantMapping/assign-tenant-mapping.module.ts index ce7ec0c7..0a011fb1 100644 --- a/src/assign-tenant/assign-tenant.module.ts +++ b/src/userTenantMapping/assign-tenant-mapping.module.ts @@ -1,12 +1,12 @@ import { HttpModule, Module } from '@nestjs/common'; -import { AssignTenantController } from './assign-tenant.controller'; +import { AssignTenantController } from './user-tenant-mapping.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { UserTenantMapping } from "./entities/assign-tenant.entity"; -import { AssignTenantAdapter } from "./assign-tenant.apater"; -import { PostgresAssignTenantService } from "src/adapters/postgres/assigntenant-adapter"; -import { HasuraAssignTenantService } from "src/adapters/hasura/assigntenant.adapter"; +import { UserTenantMapping } from "./entities/user-tenant-mapping.entity"; +import { AssignTenantAdapter } from "./user-tenant-mapping.apater"; +import { PostgresAssignTenantService } from "src/adapters/postgres/usertenantmapping-adapter"; +import { HasuraAssignTenantService } from "src/adapters/hasura/usertenantmapping.adapter"; import { User } from "src/user/entities/user-entity"; -import { Tenants } from "src/assign-tenant/entities/tenant.entity"; +import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; @Module({ diff --git a/src/assign-tenant/dto/assign-tenant-create.dto.ts b/src/userTenantMapping/dto/user-tenant-mapping.dto.ts similarity index 96% rename from src/assign-tenant/dto/assign-tenant-create.dto.ts rename to src/userTenantMapping/dto/user-tenant-mapping.dto.ts index e85ed3b4..e98376e6 100644 --- a/src/assign-tenant/dto/assign-tenant-create.dto.ts +++ b/src/userTenantMapping/dto/user-tenant-mapping.dto.ts @@ -2,7 +2,7 @@ import { Expose } from "class-transformer"; import { ApiProperty } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsUUID, IsArray } from "class-validator"; -export class CreateAssignTenantDto { +export class AssignTenantMappingDto { @ApiProperty({ type: String, description: "User Id of User", diff --git a/src/assign-tenant/entities/tenant.entity.ts b/src/userTenantMapping/entities/tenant.entity.ts similarity index 86% rename from src/assign-tenant/entities/tenant.entity.ts rename to src/userTenantMapping/entities/tenant.entity.ts index 6cad22bf..d7312eb6 100644 --- a/src/assign-tenant/entities/tenant.entity.ts +++ b/src/userTenantMapping/entities/tenant.entity.ts @@ -28,11 +28,5 @@ import { default: () => "CURRENT_TIMESTAMP", }) updatedAt: Date; - - // @Column() - // createdBy: string; - - // @Column() - // updatedBy: string; } \ No newline at end of file diff --git a/src/assign-tenant/entities/assign-tenant.entity.ts b/src/userTenantMapping/entities/user-tenant-mapping.entity.ts similarity index 100% rename from src/assign-tenant/entities/assign-tenant.entity.ts rename to src/userTenantMapping/entities/user-tenant-mapping.entity.ts diff --git a/src/assign-tenant/assign-tenant.apater.ts b/src/userTenantMapping/user-tenant-mapping.apater.ts similarity index 80% rename from src/assign-tenant/assign-tenant.apater.ts rename to src/userTenantMapping/user-tenant-mapping.apater.ts index 1ef39d57..01aba8dd 100644 --- a/src/assign-tenant/assign-tenant.apater.ts +++ b/src/userTenantMapping/user-tenant-mapping.apater.ts @@ -1,13 +1,13 @@ import { Injectable } from "@nestjs/common"; -import { PostgresAssignTenantService } from "src/adapters/postgres/assigntenant-adapter"; -import { HasuraAssignTenantService } from "src/adapters/hasura/assigntenant.adapter"; +import { PostgresAssignTenantService } from "src/adapters/postgres/usertenantmapping-adapter"; +import { HasuraAssignTenantService } from "src/adapters/hasura/usertenantmapping.adapter"; import { IServicelocatorassignTenant } from "src/adapters/assigntenantlocator"; @Injectable() export class AssignTenantAdapter { constructor(private hasuraProvider: HasuraAssignTenantService, private postgresProvider:PostgresAssignTenantService) {} - buildassignTenantAdapter(): IServicelocatorassignTenant { + buildAssignTenantAdapter(): IServicelocatorassignTenant { let adapter: IServicelocatorassignTenant; switch (process.env.ADAPTERSOURCE) { diff --git a/src/assign-tenant/assign-tenant.controller.ts b/src/userTenantMapping/user-tenant-mapping.controller.ts similarity index 79% rename from src/assign-tenant/assign-tenant.controller.ts rename to src/userTenantMapping/user-tenant-mapping.controller.ts index 883f00eb..045cd7bb 100644 --- a/src/assign-tenant/assign-tenant.controller.ts +++ b/src/userTenantMapping/user-tenant-mapping.controller.ts @@ -30,8 +30,8 @@ import { Request } from "@nestjs/common"; import { FileInterceptor } from "@nestjs/platform-express"; import { Response, response } from "express"; -import { AssignTenantAdapter } from "./assign-tenant.apater"; -import { CreateAssignTenantDto } from "./dto/assign-tenant-create.dto"; +import { AssignTenantAdapter } from "./user-tenant-mapping.apater"; +import { AssignTenantMappingDto } from "./dto/user-tenant-mapping.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("AssignTenant") @@ -48,16 +48,15 @@ export class AssignTenantController { @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) @ApiConflictResponse({ description: "Tenant is already assigned to this user." }) @UsePipes(new ValidationPipe()) - @ApiBody({ type: CreateAssignTenantDto }) + @ApiBody({ type: AssignTenantMappingDto }) public async createCohort( @Req() request: Request, - @Body() createAssignTenantDto: CreateAssignTenantDto, + @Body() assignTenantMappingDto: AssignTenantMappingDto, @Res() response: Response ) { - - const result = await this.assignTenantAdapter.buildassignTenantAdapter().createAssignTenant( + const result = await this.assignTenantAdapter.buildAssignTenantAdapter().userTenantMapping( request, - createAssignTenantDto + assignTenantMappingDto ); return response.status(result.statusCode).json(result); } From b036a6abb6b1e474263faae402534255fb2c1e3d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 3 May 2024 12:39:07 +0530 Subject: [PATCH 297/408] Resolve PR chnages --- src/app.module.ts | 2 +- ...ontroller.spec.ts => user-tenant-mapping.controller.spec.ts} | 0 ...n-tenant-mapping.module.ts => user-tenant-mapping.module.ts} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename src/userTenantMapping/{assign-tenant-mapping.controller.spec.ts => user-tenant-mapping.controller.spec.ts} (100%) rename src/userTenantMapping/{assign-tenant-mapping.module.ts => user-tenant-mapping.module.ts} (100%) diff --git a/src/app.module.ts b/src/app.module.ts index c831791e..96f2222d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,7 +18,7 @@ import { FieldsModule } from "./fields/fields.module"; import { AttendanceModule } from "./attendance/attendance.module"; import { UserModule } from "./user/user.module"; import { RbacModule } from "./rbac/rbac.module"; -import { AssignTenantModule } from './userTenantMapping/assign-tenant-mapping.module'; +import { AssignTenantModule } from './userTenantMapping/user-tenant-mapping.module'; @Module({ imports: [ diff --git a/src/userTenantMapping/assign-tenant-mapping.controller.spec.ts b/src/userTenantMapping/user-tenant-mapping.controller.spec.ts similarity index 100% rename from src/userTenantMapping/assign-tenant-mapping.controller.spec.ts rename to src/userTenantMapping/user-tenant-mapping.controller.spec.ts diff --git a/src/userTenantMapping/assign-tenant-mapping.module.ts b/src/userTenantMapping/user-tenant-mapping.module.ts similarity index 100% rename from src/userTenantMapping/assign-tenant-mapping.module.ts rename to src/userTenantMapping/user-tenant-mapping.module.ts From c1a0ae9b37deb3c0476c9f98e881ec7b9d10e2e8 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 3 May 2024 12:40:34 +0530 Subject: [PATCH 298/408] Resolve PR chnages --- .../{assigntenantlocator.ts => usertenantmappinglocator.ts} | 0 src/userTenantMapping/user-tenant-mapping.apater.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/adapters/{assigntenantlocator.ts => usertenantmappinglocator.ts} (100%) diff --git a/src/adapters/assigntenantlocator.ts b/src/adapters/usertenantmappinglocator.ts similarity index 100% rename from src/adapters/assigntenantlocator.ts rename to src/adapters/usertenantmappinglocator.ts diff --git a/src/userTenantMapping/user-tenant-mapping.apater.ts b/src/userTenantMapping/user-tenant-mapping.apater.ts index 01aba8dd..09deb08a 100644 --- a/src/userTenantMapping/user-tenant-mapping.apater.ts +++ b/src/userTenantMapping/user-tenant-mapping.apater.ts @@ -1,7 +1,7 @@ import { Injectable } from "@nestjs/common"; import { PostgresAssignTenantService } from "src/adapters/postgres/usertenantmapping-adapter"; import { HasuraAssignTenantService } from "src/adapters/hasura/usertenantmapping.adapter"; -import { IServicelocatorassignTenant } from "src/adapters/assigntenantlocator"; +import { IServicelocatorassignTenant } from "src/adapters/usertenantmappinglocator"; @Injectable() export class AssignTenantAdapter { From e6242c2f24d38c39f6dce8963fd6932bb56b1d19 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 3 May 2024 14:32:44 +0530 Subject: [PATCH 299/408] Resolve PR chnages --- ...dapter.ts => userTenantMapping.adapter.ts} | 0 src/adapters/postgres/user-adapter.ts | 133 +++++++++--------- ...dapter.ts => userTenantMapping-adapter.ts} | 68 ++++----- src/user/dto/user-create.dto.ts | 2 +- src/user/user.controller.ts | 1 + .../dto/user-tenant-mapping.dto.ts | 2 +- ...ater.ts => user-tenant-mapping.adapter.ts} | 4 +- .../user-tenant-mapping.controller.ts | 3 +- .../user-tenant-mapping.module.ts | 6 +- 9 files changed, 111 insertions(+), 108 deletions(-) rename src/adapters/hasura/{usertenantmapping.adapter.ts => userTenantMapping.adapter.ts} (100%) rename src/adapters/postgres/{usertenantmapping-adapter.ts => userTenantMapping-adapter.ts} (67%) rename src/userTenantMapping/{user-tenant-mapping.apater.ts => user-tenant-mapping.adapter.ts} (93%) diff --git a/src/adapters/hasura/usertenantmapping.adapter.ts b/src/adapters/hasura/userTenantMapping.adapter.ts similarity index 100% rename from src/adapters/hasura/usertenantmapping.adapter.ts rename to src/adapters/hasura/userTenantMapping.adapter.ts diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 5a238971..8c5b1a02 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -340,8 +340,10 @@ export class PostgresUserService { userCreateDto.updatedBy = decoded?.sub //Check duplicate field entry - let field_value_array = userCreateDto.fieldValues.split("|"); - await this.validateFieldValues(field_value_array); + if (userCreateDto.fieldValues) { + let field_value_array = userCreateDto.fieldValues.split("|"); + await this.validateFieldValues(field_value_array); + } userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); const userSchema = new UserCreateDto(userCreateDto); @@ -372,6 +374,8 @@ export class PostgresUserService { userCreateDto.userId = resKeycloak; + + // Check if tenant array is not empty const tenantIds = userCreateDto.tenantId; const userId = userCreateDto.userId; @@ -384,51 +388,12 @@ export class PostgresUserService { }); } - for (const tenantId of tenantIds) { - let findExistingRole = await this.userTenantMappingRepository.findOne({ - where: { - userId: userId, - tenantId: tenantId, - }, - }); - if (findExistingRole) { - errors.push({ - errorMessage: `User is already exist in ${tenantId} Tenant.`, - }); - continue; - } - - // User is exist in user table - let userExist = await this.usersRepository.findOne({ - where: { - userId: userId, - }, - }); - if (!userExist) { - errors.push({ - errorMessage: `User ${userId} is not exist.`, - }); - continue; - } - - // User is exist in user table - let tenantExist = await this.tenantsRepository.findOne({ - where: { - tenantId: tenantId, - }, - }); - if (!tenantExist) { - errors.push({ - errorMessage: `Tenant ${tenantId} is not exist.`, - }); - continue; - } - } + if (errors.length > 0) { return { - statusCode: HttpStatus.BAD_REQUEST, - errorCount: errors.length, - errors, + statusCode: HttpStatus.BAD_REQUEST, + errorCount: errors.length, + errors, }; } @@ -436,20 +401,23 @@ export class PostgresUserService { let result = await this.createUserInDatabase(request, userCreateDto, cohortId); let fieldData = {}; - if (result && field_value_array?.length > 0) { - let userId = result?.userId; - for (let i = 0; i < field_value_array?.length; i++) { - let fieldValues = field_value_array[i].split(":"); - fieldData = { - fieldId: fieldValues[0], - value: fieldValues[1] - } - let result = await this.updateCustomFields(userId, fieldData); - if (!result) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: `Error is ${result}`, - }); + if (userCreateDto.fieldValues) { + let field_value_array = userCreateDto.fieldValues.split("|"); + if (result && field_value_array?.length > 0) { + let userId = result?.userId; + for (let i = 0; i < field_value_array?.length; i++) { + let fieldValues = field_value_array[i].split(":"); + fieldData = { + fieldId: fieldValues[0], + value: fieldValues[1] + } + let result = await this.updateCustomFields(userId, fieldData); + if (!result) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: `Error is ${result}`, + }); + } } } } @@ -526,8 +494,47 @@ export class PostgresUserService { let errors = []; for (const tenantId of tenantIds) { - + let findExistingRole = await this.userTenantMappingRepository.findOne({ + where: { + userId: userId, + tenantId: tenantId, + }, + }); + if (findExistingRole) { + errors.push({ + errorMessage: `User is already exist in ${tenantId} Tenant.`, + }); + continue; + } + // User is exist in user table + let userExist = await this.usersRepository.findOne({ + where: { + userId: userId, + }, + }); + if (!userExist) { + errors.push({ + errorMessage: `User ${userId} is not exist.`, + }); + continue; + } + + // User is exist in user table + let tenantExist = await this.tenantsRepository.findOne({ + where: { + tenantId: tenantId, + }, + }); + if (!tenantExist) { + errors.push({ + errorMessage: `Tenant ${tenantId} is not exist.`, + }); + continue; + } + } + + for (const tenantId of tenantIds) { const data = await this.userTenantMappingRepository.save({ userId: userId, @@ -667,7 +674,7 @@ export class PostgresUserService { } } - public async validateFieldValues(field_value_array:string[]) { + public async validateFieldValues(field_value_array: string[]) { let encounteredKeys = [] for (const fieldValue of field_value_array) { const [fieldId] = fieldValue.split(":").map(value => value.trim()); @@ -680,8 +687,8 @@ export class PostgresUserService { } encounteredKeys.push(fieldId); - }; -} + }; + } } diff --git a/src/adapters/postgres/usertenantmapping-adapter.ts b/src/adapters/postgres/userTenantMapping-adapter.ts similarity index 67% rename from src/adapters/postgres/usertenantmapping-adapter.ts rename to src/adapters/postgres/userTenantMapping-adapter.ts index 772fb0f4..a89f6f2d 100644 --- a/src/adapters/postgres/usertenantmapping-adapter.ts +++ b/src/adapters/postgres/userTenantMapping-adapter.ts @@ -20,6 +20,35 @@ export class PostgresAssignTenantService { private tenantsRepository: Repository, ) { } + private async validateUserTenantMapping(userId: string, tenantId: string, errors: any[]) { + // check if user tenant mapping exists. + const existingMapping = await this.userTenantMappingRepository.findOne({ + where: { userId, tenantId }, + }); + if (existingMapping) { + errors.push({ + errorMessage: `User already exists in Tenant ${tenantId}.`, + }); + return false; + } + + // check if user exists + const userExist = await this.userRepository.findOne({ where: { userId } }); + if (!userExist) { + errors.push({ errorMessage: `User ${userId} does not exist.` }); + return false; + } + + // check if tenant exists + const tenantExist = await this.tenantsRepository.findOne({ where: { tenantId } }); + if (!tenantExist) { + errors.push({ errorMessage: `Tenant ${tenantId} does not exist.` }); + return false; + } + + return true; + } + public async userTenantMapping(request: any, assignTenantMappingDto: AssignTenantMappingDto) { try { @@ -38,47 +67,12 @@ export class PostgresAssignTenantService { let errors = []; for (const tenantId of tenantIds) { - // check if user tenant mapping exists. - let findExistingRole = await this.userTenantMappingRepository.findOne({ - where: { - userId: userId, - tenantId: tenantId, - }, - }); - if (findExistingRole) { - errors.push({ - errorMessage: `User is already exist in ${tenantId} Tenant.`, - }); - continue; - } + const isValid = await this.validateUserTenantMapping(userId, tenantId, errors); - // check if user exists - let userExist = await this.userRepository.findOne({ - where: { - userId: userId, - }, - }); - if (!userExist) { - errors.push({ - errorMessage: `User ${userId} does not exist.`, - }); + if (!isValid) { continue; } - // check if tenant exists - let tenantExist = await this.tenantsRepository.findOne({ - where: { - tenantId: tenantId, - }, - }); - if (!tenantExist) { - errors.push({ - errorMessage: `Tenant ${tenantId} does not exist.`, - }); - continue; - } - - const data = await this.userTenantMappingRepository.save({ userId: userId, tenantId: tenantId, diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index b2d6b4d1..d1c83172 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -133,7 +133,7 @@ export class UserCreateDto { @IsArray() @IsUUID(undefined, { each: true }) @IsNotEmpty({ each: true }) - tenantId: string[]; + tenantId: string; constructor(partial: Partial) { Object.assign(this, partial); diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index c0382ad7..e5b87f25 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -85,6 +85,7 @@ export class UserController { @ApiForbiddenResponse({ description: "User Already Exists"}) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) async createUser( + @Headers() headers, @Req() request: Request, @Body() userCreateDto: UserCreateDto, @Res() response: Response diff --git a/src/userTenantMapping/dto/user-tenant-mapping.dto.ts b/src/userTenantMapping/dto/user-tenant-mapping.dto.ts index e98376e6..f5f29a98 100644 --- a/src/userTenantMapping/dto/user-tenant-mapping.dto.ts +++ b/src/userTenantMapping/dto/user-tenant-mapping.dto.ts @@ -23,7 +23,7 @@ export class AssignTenantMappingDto { @IsArray() @IsUUID(undefined, { each: true }) @IsNotEmpty({ each: true }) - tenantId: string; + tenantId: string[]; constructor(obj: any) { Object.assign(this, obj); diff --git a/src/userTenantMapping/user-tenant-mapping.apater.ts b/src/userTenantMapping/user-tenant-mapping.adapter.ts similarity index 93% rename from src/userTenantMapping/user-tenant-mapping.apater.ts rename to src/userTenantMapping/user-tenant-mapping.adapter.ts index 09deb08a..f96061f2 100644 --- a/src/userTenantMapping/user-tenant-mapping.apater.ts +++ b/src/userTenantMapping/user-tenant-mapping.adapter.ts @@ -1,6 +1,6 @@ import { Injectable } from "@nestjs/common"; -import { PostgresAssignTenantService } from "src/adapters/postgres/usertenantmapping-adapter"; -import { HasuraAssignTenantService } from "src/adapters/hasura/usertenantmapping.adapter"; +import { PostgresAssignTenantService } from "src/adapters/postgres/userTenantMapping-adapter"; +import { HasuraAssignTenantService } from "src/adapters/hasura/userTenantMapping.adapter"; import { IServicelocatorassignTenant } from "src/adapters/usertenantmappinglocator"; @Injectable() diff --git a/src/userTenantMapping/user-tenant-mapping.controller.ts b/src/userTenantMapping/user-tenant-mapping.controller.ts index 045cd7bb..6e184d5e 100644 --- a/src/userTenantMapping/user-tenant-mapping.controller.ts +++ b/src/userTenantMapping/user-tenant-mapping.controller.ts @@ -30,7 +30,7 @@ import { Request } from "@nestjs/common"; import { FileInterceptor } from "@nestjs/platform-express"; import { Response, response } from "express"; -import { AssignTenantAdapter } from "./user-tenant-mapping.apater"; +import { AssignTenantAdapter } from "./user-tenant-mapping.adapter"; import { AssignTenantMappingDto } from "./dto/user-tenant-mapping.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @@ -50,6 +50,7 @@ export class AssignTenantController { @UsePipes(new ValidationPipe()) @ApiBody({ type: AssignTenantMappingDto }) public async createCohort( + @Headers() headers, @Req() request: Request, @Body() assignTenantMappingDto: AssignTenantMappingDto, @Res() response: Response diff --git a/src/userTenantMapping/user-tenant-mapping.module.ts b/src/userTenantMapping/user-tenant-mapping.module.ts index 0a011fb1..df4362a7 100644 --- a/src/userTenantMapping/user-tenant-mapping.module.ts +++ b/src/userTenantMapping/user-tenant-mapping.module.ts @@ -2,9 +2,9 @@ import { HttpModule, Module } from '@nestjs/common'; import { AssignTenantController } from './user-tenant-mapping.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UserTenantMapping } from "./entities/user-tenant-mapping.entity"; -import { AssignTenantAdapter } from "./user-tenant-mapping.apater"; -import { PostgresAssignTenantService } from "src/adapters/postgres/usertenantmapping-adapter"; -import { HasuraAssignTenantService } from "src/adapters/hasura/usertenantmapping.adapter"; +import { AssignTenantAdapter } from "./user-tenant-mapping.adapter"; +import { PostgresAssignTenantService } from "src/adapters/postgres/userTenantMapping-adapter"; +import { HasuraAssignTenantService } from "src/adapters/hasura/userTenantMapping.adapter"; import { User } from "src/user/entities/user-entity"; import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; From 9d39fb2f347db5688ef48f454e0a690ebd744076 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 3 May 2024 17:57:47 +0530 Subject: [PATCH 300/408] Resolve PR chnages --- src/adapters/postgres/user-adapter.ts | 106 ++++++++---------- .../postgres/userTenantMapping-adapter.ts | 2 +- src/user/user.controller.ts | 2 + 3 files changed, 47 insertions(+), 63 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 8c5b1a02..c44b10f4 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -25,6 +25,7 @@ import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; @Injectable() export class PostgresUserService { axios = require("axios"); + constructor( // private axiosInstance: AxiosInstance, @InjectRepository(User) @@ -38,7 +39,7 @@ export class PostgresUserService { @InjectRepository(UserTenantMapping) private userTenantMappingRepository: Repository, @InjectRepository(Tenants) - private tenantsRepository: Repository + private tenantsRepository: Repository, ) { } async searchUser(tenantId: string, request: any, @@ -342,7 +343,37 @@ export class PostgresUserService { //Check duplicate field entry if (userCreateDto.fieldValues) { let field_value_array = userCreateDto.fieldValues.split("|"); - await this.validateFieldValues(field_value_array); + const validateField = await this.validateFieldValues(field_value_array); + + if(validateField == false){ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: "Duplicate fieldId found in fieldValues.", + }); + } + } + + // Check if tenant array is not empty + const tenantIds = userCreateDto.tenantId; + const userId = userCreateDto.userId; + let errors = []; + + if (!tenantIds || tenantIds.length === 0) { + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: "Tenants array cannot be empty.", + }); + } + + //Check tenent is exist or not + for (const tenantId of tenantIds) { + const validate = await this.validateUserTenantMapping(userId, tenantId); + if (validate == false) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Tenant ${tenantId} does not exist.`, + }); + } } userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); @@ -376,18 +407,6 @@ export class PostgresUserService { - // Check if tenant array is not empty - const tenantIds = userCreateDto.tenantId; - const userId = userCreateDto.userId; - let errors = []; - - if (!tenantIds || tenantIds.length === 0) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: "Tenants array cannot be empty.", - }); - } - if (errors.length > 0) { return { @@ -494,62 +513,28 @@ export class PostgresUserService { let errors = []; for (const tenantId of tenantIds) { - let findExistingRole = await this.userTenantMappingRepository.findOne({ - where: { - userId: userId, - tenantId: tenantId, - }, - }); - if (findExistingRole) { - errors.push({ - errorMessage: `User is already exist in ${tenantId} Tenant.`, - }); - continue; - } - - // User is exist in user table - let userExist = await this.usersRepository.findOne({ - where: { - userId: userId, - }, - }); - if (!userExist) { - errors.push({ - errorMessage: `User ${userId} is not exist.`, - }); - continue; - } - - // User is exist in user table - let tenantExist = await this.tenantsRepository.findOne({ - where: { - tenantId: tenantId, - }, - }); - if (!tenantExist) { - errors.push({ - errorMessage: `Tenant ${tenantId} is not exist.`, - }); - continue; - } - } - - for (const tenantId of tenantIds) { - const data = await this.userTenantMappingRepository.save({ userId: userId, tenantId: tenantId, createdBy: request['user'].userId, updatedBy: request['user'].userId }) - - // result.push(new ResponseAssignTenantDto(data, `Tenant assigned successfully to the user.`)); } } catch (error) { throw new Error(error) } } + public async validateUserTenantMapping(userId: string, tenantId: string) { + // check if tenant exists + const tenantExist = await this.tenantsRepository.findOne({ where: { tenantId: tenantId } }); + if (!tenantExist) { + return false + } else { + return true + } + } + async addCohortMember(cohortData) { try { let result = await this.cohortMemberRepository.insert(cohortData); @@ -680,10 +665,7 @@ export class PostgresUserService { const [fieldId] = fieldValue.split(":").map(value => value.trim()); if (encounteredKeys.includes(fieldId)) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: `Duplicate fieldId '${fieldId}' found in fieldValues.`, - }); + return false } encounteredKeys.push(fieldId); diff --git a/src/adapters/postgres/userTenantMapping-adapter.ts b/src/adapters/postgres/userTenantMapping-adapter.ts index a89f6f2d..73e19ad5 100644 --- a/src/adapters/postgres/userTenantMapping-adapter.ts +++ b/src/adapters/postgres/userTenantMapping-adapter.ts @@ -20,7 +20,7 @@ export class PostgresAssignTenantService { private tenantsRepository: Repository, ) { } - private async validateUserTenantMapping(userId: string, tenantId: string, errors: any[]) { + public async validateUserTenantMapping(userId: string, tenantId: string, errors: any[]) { // check if user tenant mapping exists. const existingMapping = await this.userTenantMappingRepository.findOne({ where: { userId, tenantId }, diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index e5b87f25..be296bb5 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -29,6 +29,7 @@ import { ApiNotFoundResponse, ApiInternalServerErrorResponse, ApiBadRequestResponse, + ApiConflictResponse, } from "@nestjs/swagger"; import { UserSearchDto } from "./dto/user-search.dto"; @@ -84,6 +85,7 @@ export class UserController { @ApiBody({ type: UserCreateDto }) @ApiForbiddenResponse({ description: "User Already Exists"}) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) + @ApiConflictResponse({ description: "Duplicate data." }) async createUser( @Headers() headers, @Req() request: Request, From c202df59f7e78606b8b0da859cba59d293785a4c Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Mon, 6 May 2024 22:58:28 +0530 Subject: [PATCH 301/408] Fix[attendance list API ] --- src/adapters/hasura/attendance.adapter.ts | 6 +- src/adapters/postgres/attendance-adapter.ts | 312 ++++++++++++------- src/attendance/attendance.controller.ts | 10 +- src/attendance/dto/attendance-search.dto.ts | 176 ++++++----- src/attendance/dto/attendance.dto.ts | 47 ++- src/attendance/entities/attendance.entity.ts | 3 + 6 files changed, 355 insertions(+), 199 deletions(-) diff --git a/src/adapters/hasura/attendance.adapter.ts b/src/adapters/hasura/attendance.adapter.ts index 2ca696f0..80874673 100644 --- a/src/adapters/hasura/attendance.adapter.ts +++ b/src/adapters/hasura/attendance.adapter.ts @@ -203,7 +203,7 @@ export class AttendanceHasuraService implements IServicelocator { let offset = 0; if (attendanceSearchDto.page > 1) { offset = - parseInt(attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); + (attendanceSearchDto.limit) * (attendanceSearchDto.page - 1); } attendanceSearchDto.filters["tenantId"] = tenantId ? tenantId : ""; @@ -247,8 +247,8 @@ export class AttendanceHasuraService implements IServicelocator { } }`, variables: { - limit: parseInt(attendanceSearchDto.limit) - ? parseInt(attendanceSearchDto.limit) + limit: (attendanceSearchDto.limit) + ? (attendanceSearchDto.limit) : 10, offset: offset, filters: attendanceSearchDto.filters, diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index b6e8ce38..ccf41db1 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -2,8 +2,8 @@ import { User } from '../../user/entities/user-entity'; import { ConfigService } from '@nestjs/config'; import { InjectRepository } from "@nestjs/typeorm"; import { AttendanceEntity } from "../../attendance/entities/attendance.entity"; -import { Repository,Between } from "typeorm"; -import { HttpStatus, Injectable } from "@nestjs/common"; +import { Repository, Between, In, MoreThanOrEqual, LessThanOrEqual } from "typeorm"; +import { ConsoleLogger, HttpStatus, Injectable } from "@nestjs/common"; import { AttendanceSearchDto } from "../../attendance/dto/attendance-search.dto"; import { SuccessResponse } from 'src/success-response'; import { AttendanceDto, BulkAttendanceDTO } from '../../attendance/dto/attendance.dto'; @@ -12,6 +12,7 @@ import { AttendanceStatsDto } from '../../attendance/dto/attendance-stats.dto'; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; const moment = require('moment'); +const facetedSearch = require("in-memory-faceted-search"); @Injectable() export class PostgresAttendanceService { @@ -34,94 +35,190 @@ export class PostgresAttendanceService { async searchAttendance(tenantId: string, request: any, attendanceSearchDto: AttendanceSearchDto) { try { - let { limit, page, filters } = attendanceSearchDto; + let { limit, page, filters, facets } = attendanceSearchDto; + // Set default limit to 0 if not provided if (!limit) { - limit = '0'; + limit = 10; } - + let offset = 0; + // Calculate offset based on page number if (page > 1) { - offset = parseInt(limit) * (page - 1); + offset = (limit) * (page - 1); } - - const UserKeys = this.userRepository.metadata.columns.map((column) => column.propertyName); - const AttendaceKeys = this.attendanceRepository.metadata.columns.map((column) => column.propertyName); - const CohortMembersKeys = this.cohortMembersRepository.metadata.columns.map((column) => column.propertyName); - - let whereClause = `u."tenantId" = $1`; // Default WHERE clause for filtering by tenantId - let queryParams = [tenantId]; // Parameters for the query - let attendanceList = ''; + + // Get column names from metadata + const attendanceKeys = this.attendanceRepository.metadata.columns.map((column) => column.propertyName); + + let whereClause: any = { tenantId }; + // Default WHERE clause for filtering by tenantId + if (filters && Object.keys(filters).length > 0) { - let index = 2; // Starting index for additional parameters for (const [key, value] of Object.entries(filters)) { - if (UserKeys.includes(key)) { - whereClause += ` AND u."${key}" = $${index}`; - queryParams.push(value); - } else if (AttendaceKeys.includes(key)) { + if (attendanceKeys.includes(key)) { if (key === "attendanceDate") { - attendanceList = ` AND (a."attendanceDate" = $${index} OR a."attendanceDate" IS NULL)`; + // For attendanceDate, consider NULL values as well + whereClause[key] = In([value, null]); } - whereClause += ` AND a."${key}" = $${index}`; - queryParams.push(value); - } else if (CohortMembersKeys.includes(key)) { - whereClause += ` AND cm."${key}" = $${index}`; - queryParams.push(value); - } else if (filters.fromDate && filters.toDate) { - whereClause += ` AND a."attendanceDate" BETWEEN $${index} AND $${index + 1}`; - queryParams.push(filters.fromDate); - queryParams.push(filters.toDate); - index += 1; // Increment index for toDate parameter - } else { + whereClause[key] = value; + } + + else if (filters.fromDate && filters.toDate) { + + + // Convert fromDate and toDate strings to Date objects + const fromDate = new Date(filters.fromDate); + const toDate = new Date(filters.toDate); + + // Construct the whereClause with the date range using Between + whereClause["attendanceDate"] = Between(fromDate, toDate); + } + else { + // If filter key is invalid, return a BadRequest response return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `${key} Invalid key`, + errorMessage: `${key} Invalid filter key`, }); } - index += 1; // Increment index for next parameter } + } - - const query = ` - SELECT u.*, cm.*, a.* - FROM "Users" u - INNER JOIN "CohortMembers" cm ON cm."userId" = u."userId" - LEFT JOIN "Attendance" a ON a."userId" = cm."userId" ${attendanceList} - WHERE ${whereClause}; - `; - const results = await this.attendanceRepository.query(query, queryParams); - const mappedResponse = await this.mappedResponse(results); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: mappedResponse, + + // Fetch data from the database + const attendanceList = await this.attendanceRepository.find({ + where: whereClause }); + + const paginatedAttendanceList = attendanceList.slice(offset, offset + (limit)); + + if (facets && facets.length > 0) { + let facetFields = []; + // Check for invalid facets + for (const facet of facets) { + if (!attendanceKeys.includes(facet)) { + // If facet is not present in attendanceKeys, return a BadRequest response + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `${facet} Invalid facet`, + }); + } + facetFields.push({ name: facet, field: facet }); + } + + + + + // Process the data to calculate counts based on facets + const tree = await this.facetedSearch({ data: attendanceList, facets: facetFields }); + // const result = Object.entries(tree).map(([key, value]) => ({ [key]: value })); + + let result = []; + // Process the data to calculate counts based on facets + for (const facet of facetFields) { + const { field } = facet; + const tree = await this.facetedSearch({ data: attendanceList, facets: [facet] }); + const formattedData = Object.entries(tree[field]).map(([key, value]) => ({ [key]: value })); + result.push({ [field]: formattedData }); // Modified the structure here + } + + + + // Return success response with counts + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: { + result: result, + }, + }); + } + else { + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: { + attendanceList: paginatedAttendanceList + }, + }); + + + } } catch (error) { - if (error.code=== "22P02"){ + if (error.code === "22P02") { + // Handle invalid input value error return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `Invalid value Entered For ${error.routine}`, - }) + errorMessage: `Invalid value entered for ${error.routine}`, + }); } + // Handle other errors with internal server error response return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, + errorMessage: error, // Use error message if available }); } } + async facetedSearch({ data, facets }) { + const tree = []; + // Iterate over facets + for (const facet of facets) { + const { field } = facet; + + // Initialize main facet in tree + tree[field] = {}; + + // Iterate over data to count occurrences of each field value + for (const item of data) { + const value = item[field]; + const attendanceValue = item["attendance"]; + + // If contextId doesn't exist in the tree, initialize it with an empty object + if (!tree[field][value]) { + tree[field][value] = {}; + } + + // Increment count for attendanceValue + if (!tree[field][value][attendanceValue]) { + tree[field][value][attendanceValue] = 1; + } else { + tree[field][value][attendanceValue]++; + } + } + + // Calculate percentage for each contextId + // Calculate percentage for each contextId + for (const value in tree[field]) { + const counts = tree[field][value]; + const totalCount = Object.values(counts).reduce((acc: number, curr: unknown) => acc + (curr as number), 0); + + for (const key in counts) { + const count = counts[key]; + const percentage = (count / Number(totalCount)) * 100; // Convert totalCount to a number + // counts[key + "_count"] = count; + counts[key + "_percentage"] = percentage.toFixed(2); // Round percentage to two decimal places + } + } + + } + return tree; + } + + + async attendanceReport(attendanceStatsDto: AttendanceStatsDto) { let { contextId, limit, offset, filters } = attendanceStatsDto; try { - + let nameFilter = ''; let userFilter = ''; let dateFilter = ''; let queryParams: any[] = [contextId]; let subqueryParams: any[] = [contextId]; // Initialize query parameters array let paramIndex = 1; // Initialize parameter index - + if (filters && filters.search) { nameFilter = `AND u."name" ILIKE $${++paramIndex}`; // Increment paramIndex queryParams.push(`%${filters.search.trim()}%`); @@ -134,14 +231,14 @@ export class PostgresAttendanceService { } if (filters && filters.fromDate && filters.toDate) { - dateFilter = `WHERE aa."attendanceDate" >= $${++paramIndex} AND aa."attendanceDate" <= $${++paramIndex}`; + dateFilter = `WHERE aa."attendanceDate" >= $${++paramIndex} AND aa."attendanceDate" <= $${++paramIndex}`; queryParams.push(filters.fromDate); queryParams.push(filters.toDate); subqueryParams.push(filters.fromDate); subqueryParams.push(filters.toDate); } - + let query = ` SELECT u."userId", @@ -174,7 +271,7 @@ export class PostgresAttendanceService { GROUP BY u."userId", u."name", aa_stats."total_attendance", aa_stats."present_count" `; - + if (filters) { if (filters.nameOrder && (filters.nameOrder === "asc" || filters.nameOrder === "desc")) { query += ` ORDER BY "name" ${filters.nameOrder}`; @@ -185,14 +282,14 @@ export class PostgresAttendanceService { query += ` LIMIT $${++paramIndex} OFFSET $${++paramIndex}`; - + queryParams.push(limit); queryParams.push(offset); - - + + const result = await this.attendanceRepository.query(query, queryParams); - + if (!filters || !filters?.userId) { // We don't need average for single user const countquery = ` @@ -229,7 +326,7 @@ export class PostgresAttendanceService { GROUP BY u."userId", u."name", aa_stats."total_attendance", aa_stats."present_count" ) AS subquery`; - + const average = await this.attendanceRepository.query(countquery, subqueryParams); const report = await this.mapResponseforReport(result); @@ -252,7 +349,7 @@ export class PostgresAttendanceService { }); } - + } catch (error) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, @@ -260,19 +357,19 @@ export class PostgresAttendanceService { }); } } - - - - - - + + + + + + public async mappedResponse(result: any) { const attendanceResponse = result.map((item: any) => { const dateObject = new Date(item.attendanceDate); - const formattedDate = moment(dateObject).format('YYYY-MM-DD'); const attendanceMapping = { + const formattedDate = moment(dateObject).format('YYYY-MM-DD'); const attendanceMapping = { tenantId: item?.tenantId ? `${item.tenantId}` : "", attendanceId: item?.attendanceId ? `${item.attendanceId}` : "", userId: item?.userId ? `${item.userId}` : "", @@ -291,8 +388,8 @@ export class PostgresAttendanceService { updatedAt: item?.updatedAt ? `${item.updatedAt}` : "", createdBy: item?.createdBy ? `${item.createdBy}` : "", updatedBy: item?.updatedBy ? `${item.updatedBy}` : "", - username:item?.username ? `${item.username}` : "", - role:item?.role ? `${item.role}` : "", + username: item?.username ? `${item.username}` : "", + role: item?.role ? `${item.role}` : "", }; @@ -310,7 +407,7 @@ export class PostgresAttendanceService { userId: item?.userId ? `${item.userId}` : "", attendance_percentage: item?.attendance_percentage ? `${item.attendance_percentage}` : "", }; - + return new AttendanceStatsDto(attendanceReportMapping); }); @@ -348,14 +445,14 @@ export class PostgresAttendanceService { try { - const Isvalid = await this.validateUserForCohort(attendanceDto.userId,attendanceDto.contextId) + const Isvalid = await this.validateUserForCohort(attendanceDto.userId, attendanceDto.contextId) - if(!Isvalid){ + if (!Isvalid) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, errorMessage: "Invalid combination of contextId and userId", - }); + }); } @@ -366,14 +463,12 @@ export class PostgresAttendanceService { userId: attendanceDto.userId, }; - const attendanceFound: any = await this.searchAttendance( attendanceDto.tenantId, loginUserId, attendanceToSearch ); - if (attendanceFound instanceof ErrorResponseTypeOrm) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, @@ -382,12 +477,12 @@ export class PostgresAttendanceService { } if ( - attendanceFound.data.length > 0 && attendanceFound.data[0].attendanceId != "" && - attendanceFound.statusCode === 200 && attendanceFound instanceof SuccessResponse + attendanceFound.data.attendanceList.length > 0 ) { + attendanceDto.updatedBy = loginUserId - return await this.updateAttendance( - attendanceFound.data[0].attendanceId, + return await this.updateAttendance( + attendanceFound.data.attendanceList[0].attendanceId, loginUserId, attendanceDto ); @@ -420,6 +515,7 @@ export class PostgresAttendanceService { where: { attendanceId }, }); + if (!attendanceRecord) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, @@ -427,8 +523,8 @@ export class PostgresAttendanceService { }); } - - this.attendanceRepository.merge(attendanceRecord, attendanceDto); + Object.assign(attendanceRecord, attendanceDto); + // this.attendanceRepository.merge(attendanceRecord, attendanceDto); // Save the updated attendance record const updatedAttendanceRecord = await this.attendanceRepository.save( @@ -448,14 +544,14 @@ export class PostgresAttendanceService { errorMessage: "Please provide valid contextId", }); } - else{ + else { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: error, }) } - + } } @@ -465,8 +561,6 @@ export class PostgresAttendanceService { */ public async createAttendance(request: any, attendanceDto: AttendanceDto) { - - try { const attendance = this.attendanceRepository.create(attendanceDto); const result = await this.attendanceRepository.save(attendance); @@ -561,7 +655,7 @@ export class PostgresAttendanceService { attendanceData: BulkAttendanceDTO ) { - const loginUserId=request.user.userId + const loginUserId = request.user.userId const responses = []; @@ -577,25 +671,34 @@ export class PostgresAttendanceService { contextId: attendanceData.contextId, attendance: attendance.attendance, userId: attendance.userId, - tenantId:tenantId + tenantId: tenantId, + remark: attendance.remark, + latitude: attendance.latitude, + longitude: attendance.longitude, + image: attendance.image, + metaData: attendance.metaData, + syncTime: attendance.syncTime, + session: attendance.session, + contextType: attendance.contextType, }) + const attendanceRes: any = await this.updateAttendanceRecord( loginUserId, userAttendance ); - if (attendanceRes?.statusCode === 200||attendanceRes?.statusCode === 201) { + if (attendanceRes?.statusCode === 200 || attendanceRes?.statusCode === 201) { responses.push(attendanceRes.data); } - else { + else { errors.push({ userId: attendance.userId, attendanceRes, }); } count++; - - + + } } catch (e) { return new ErrorResponseTypeOrm({ @@ -617,19 +720,18 @@ export class PostgresAttendanceService { - public async validateUserForCohort(userId,cohortId) - { - const attendanceRecord = await this.cohortMembersRepository.findOne({ - where: { userId, cohortId } // Include cohortId in the where clause - }); - if(attendanceRecord){ - return true - }else{ - return false - } - + public async validateUserForCohort(userId, cohortId) { + const attendanceRecord = await this.cohortMembersRepository.findOne({ + where: { userId, cohortId } // Include cohortId in the where clause + }); + if (attendanceRecord) { + return true + } else { + return false } + } + } diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index 4384aa0a..b7eae755 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -88,7 +88,7 @@ export class AttendanceController { @ApiBody({ type: AttendanceDto }) // @UseInterceptors(ClassSerializerInterceptor) @ApiHeader({ - name: "tenantid", + name: "tenantid" }) @UsePipes(ValidationPipe) public async createAttendace( @@ -110,7 +110,7 @@ export class AttendanceController { - @Post("/search") + @Post("/list") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Attendance List" }) @ApiBadRequestResponse({ description: "Bad Request" }) @@ -131,6 +131,12 @@ export class AttendanceController { @Res() response: Response ) { let tenantid = headers["tenantid"]; + if (!tenantid) { + return response.status(HttpStatus.BAD_REQUEST).json({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "tenantId is missing in headers", + }); + } const result = await this.attendaceAdapter.buildAttenceAdapter().searchAttendance( tenantid, diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index aaa3abff..7e5ff4de 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -1,97 +1,105 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsOptional, IsUUID, Matches, Validate, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator"; -import { isBefore, isSameDay } from "date-fns"; -import { UserDto } from "src/user/dto/user.dto"; -import { AttendanceDto } from "./attendance.dto"; -import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; -import { Type } from "class-transformer"; - - -export class AttendanceFiltersDto { - @ApiPropertyOptional() - @IsOptional() - @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) - fromDate?: string; - - @ApiPropertyOptional() - @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) - @IsOptional() - toDate?: string; - - @ApiPropertyOptional() - @IsUUID() - @IsOptional() - cohortId ?:string - - @ApiPropertyOptional() - role ?: string - - @ApiPropertyOptional({ - type: String, - description: "The date of the attendance in format yyyy-mm-dd", - default:"yyyy-mm-dd" - }) - @IsOptional() - @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) - attendanceDate ?:Date - - - @ApiPropertyOptional() - @IsUUID() - @IsOptional() - userId?: string - - // @ApiPropertyOptional() - - - [key: string]: any; // Allows additional dynamic keys -} - -@ValidatorConstraint({ name: "validDateRange", async: false }) -export class ValidDateRangeConstraint implements ValidatorConstraintInterface { - validate(value: any, args: ValidationArguments) { - const { toDate, fromDate } = value; - - // If either fromDate or toDate is not provided, validation passes - if (!fromDate || !toDate) { - return true; + import { ApiAcceptedResponse, ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; + import { IsArray, IsNotEmpty, IsNumber, IsOptional, IsString, IsUUID, Matches, Validate, ValidateIf, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface, isNotEmpty } from "class-validator"; + import { isBefore, isSameDay } from "date-fns"; + import { UserDto } from "src/user/dto/user.dto"; + import { AttendanceDto } from "./attendance.dto"; + import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; + import { Type } from "class-transformer"; + + export class AttendanceFiltersDto { + @ApiPropertyOptional() + @IsOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + fromDate?: Date; + + @ApiPropertyOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @IsOptional() + toDate?: Date; + + @ApiPropertyOptional() + @IsUUID() + @IsOptional() + cohortId ?:string + + @ApiPropertyOptional() + scope ?: string + + @ApiPropertyOptional({ + type: String, + description: "The date of the attendance in format yyyy-mm-dd", + default:"yyyy-mm-dd" + }) + @IsOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + attendanceDate ?:Date + + + @ApiPropertyOptional() + @IsUUID() + @IsOptional() + userId?: string + + // @ApiPropertyOptional() + + + [key: string]: any; // Allows additional dynamic keys + } + + @ValidatorConstraint({ name: "validDateRange", async: false }) + export class ValidDateRangeConstraint implements ValidatorConstraintInterface { + validate(value: any, args: ValidationArguments) { + const { toDate, fromDate } = value; + + // If either fromDate or toDate is not provided, validation passes + if (!fromDate || !toDate) { + return true; + } + + return isBefore(new Date(fromDate), new Date(toDate)) || isSameDay(new Date(fromDate), new Date(toDate)); } - return isBefore(new Date(fromDate), new Date(toDate)) || isSameDay(new Date(fromDate), new Date(toDate)); + defaultMessage(args: ValidationArguments) { + return "Invalid date range. 'toDate' must be after or equal to 'fromDate'."; + } } - defaultMessage(args: ValidationArguments) { - return "Invalid date range. 'toDate' must be after or equal to 'fromDate'."; - } -} + export class AttendanceSearchDto { + @ApiProperty({ + type: Number, + description: "Limit", + }) + @ValidateIf(o => !o.facets) + @IsNotEmpty() + @IsNumber({}, { message: 'Limit must be a number' }) + limit: number; -export class AttendanceSearchDto { - @ApiProperty({ - type: String, - description: "Limit", - }) - limit: string; + @ApiProperty({ + type: Number, + description: "number", + }) + page: number; - @ApiProperty({ - type: Number, - description: "number", - }) - page: number; + @ApiPropertyOptional({ + type: AttendanceFiltersDto, + description: "Filters", + }) + @ValidateNested({ each: true }) + @Type(() => AttendanceFiltersDto) + // @Validate(ValidDateRangeConstraint, { message: "Invalid date range." }) + filters: AttendanceFiltersDto - @ApiPropertyOptional({ - type: AttendanceFiltersDto, - description: "Filters", - }) - @ValidateNested({ each: true }) - @Type(() => AttendanceFiltersDto) - // @Validate(ValidDateRangeConstraint, { message: "Invalid date range." }) - filters: AttendanceFiltersDto + @ApiPropertyOptional({ + description: "Facets", + }) + facets?: string[]; - constructor(partial: Partial) { - Object.assign(this, partial); + + constructor(partial: Partial) { + Object.assign(this, partial); + } } -} diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 6328fe76..7defd361 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -72,11 +72,7 @@ export class AttendanceDto { @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) attendance: string; - @ApiProperty({ - type: String, - description: "The remark of the attendance", - default: "", - }) + @Expose() @ApiPropertyOptional() remark: string; @@ -164,6 +160,9 @@ export class AttendanceDto { @Expose() updatedBy: string; + @Expose() + scope: string; + constructor(obj: any) { Object.assign(this, obj); } @@ -187,6 +186,44 @@ export class UserAttendanceDTO { @IsNotEmpty() @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) attendance: string; + + + @Expose() + @ApiPropertyOptional() + remark: string; + + @Expose() + @ApiPropertyOptional() + latitude: number; + + @Expose() + @ApiPropertyOptional() + longitude: number; + + + @Expose() + @ApiPropertyOptional() + image: string; + + @ApiPropertyOptional() + @Expose() + metaData: string; + + @ApiPropertyOptional() + @Expose() + syncTime: string; + + @ApiPropertyOptional() + @Expose() + session: string; + + @ApiPropertyOptional({ + type: String, + description: "The contextType of the attendance", + default: "", + }) + @Expose() + contextType: string; } export class BulkAttendanceDTO { diff --git a/src/attendance/entities/attendance.entity.ts b/src/attendance/entities/attendance.entity.ts index 38e21164..82c75827 100644 --- a/src/attendance/entities/attendance.entity.ts +++ b/src/attendance/entities/attendance.entity.ts @@ -63,6 +63,9 @@ export class AttendanceEntity { @Column() updatedBy: string; + @Column() + scope: string; + constructor(obj: Partial) { Object.assign(this, obj); } From 8fda1b4c08cfad85dd6567df0a8aa0415bdd2fc0 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 7 May 2024 13:17:49 +0530 Subject: [PATCH 302/408] Dto class name changes --- src/adapters/hasura/userTenantMapping.adapter.ts | 4 ++-- src/adapters/postgres/userTenantMapping-adapter.ts | 4 ++-- src/adapters/usertenantmappinglocator.ts | 4 ++-- src/userTenantMapping/dto/user-tenant-mapping.dto.ts | 2 +- src/userTenantMapping/user-tenant-mapping.controller.ts | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/adapters/hasura/userTenantMapping.adapter.ts b/src/adapters/hasura/userTenantMapping.adapter.ts index f2e05e83..2b04e38c 100644 --- a/src/adapters/hasura/userTenantMapping.adapter.ts +++ b/src/adapters/hasura/userTenantMapping.adapter.ts @@ -2,7 +2,7 @@ import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nes import { InjectRepository } from '@nestjs/typeorm'; import { In, Repository } from 'typeorm'; import { UserTenantMapping } from 'src/userTenantMapping/entities/user-tenant-mapping.entity'; -import { AssignTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; +import { UserTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; @Injectable() export class HasuraAssignTenantService { @@ -11,7 +11,7 @@ export class HasuraAssignTenantService { private userTenantMappingRepository: Repository, ) { } - public async userTenantMapping(request: any, assignTenantMappingDto:AssignTenantMappingDto) { + public async userTenantMapping(request: any, assignTenantMappingDto:UserTenantMappingDto) { } } diff --git a/src/adapters/postgres/userTenantMapping-adapter.ts b/src/adapters/postgres/userTenantMapping-adapter.ts index 73e19ad5..c8f7fb30 100644 --- a/src/adapters/postgres/userTenantMapping-adapter.ts +++ b/src/adapters/postgres/userTenantMapping-adapter.ts @@ -2,7 +2,7 @@ import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nes import { InjectRepository } from '@nestjs/typeorm'; import { In, Repository } from 'typeorm'; import { UserTenantMapping } from 'src/userTenantMapping/entities/user-tenant-mapping.entity'; -import { AssignTenantMappingDto,ResponseAssignTenantDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; +import { UserTenantMappingDto,ResponseAssignTenantDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { SuccessResponse } from 'src/success-response'; import { User } from "src/user/entities/user-entity"; @@ -49,7 +49,7 @@ export class PostgresAssignTenantService { return true; } - public async userTenantMapping(request: any, assignTenantMappingDto: AssignTenantMappingDto) { + public async userTenantMapping(request: any, assignTenantMappingDto: UserTenantMappingDto) { try { const userId = assignTenantMappingDto.userId; diff --git a/src/adapters/usertenantmappinglocator.ts b/src/adapters/usertenantmappinglocator.ts index 039d111a..07bcd65e 100644 --- a/src/adapters/usertenantmappinglocator.ts +++ b/src/adapters/usertenantmappinglocator.ts @@ -1,4 +1,4 @@ -import { AssignTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; +import { UserTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; export interface IServicelocatorassignTenant { - userTenantMapping(request: any, assignTenantMappingDto:AssignTenantMappingDto); + userTenantMapping(request: any, assignTenantMappingDto:UserTenantMappingDto); } \ No newline at end of file diff --git a/src/userTenantMapping/dto/user-tenant-mapping.dto.ts b/src/userTenantMapping/dto/user-tenant-mapping.dto.ts index f5f29a98..d1ee71c6 100644 --- a/src/userTenantMapping/dto/user-tenant-mapping.dto.ts +++ b/src/userTenantMapping/dto/user-tenant-mapping.dto.ts @@ -2,7 +2,7 @@ import { Expose } from "class-transformer"; import { ApiProperty } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsUUID, IsArray } from "class-validator"; -export class AssignTenantMappingDto { +export class UserTenantMappingDto { @ApiProperty({ type: String, description: "User Id of User", diff --git a/src/userTenantMapping/user-tenant-mapping.controller.ts b/src/userTenantMapping/user-tenant-mapping.controller.ts index 6e184d5e..5db5f912 100644 --- a/src/userTenantMapping/user-tenant-mapping.controller.ts +++ b/src/userTenantMapping/user-tenant-mapping.controller.ts @@ -31,7 +31,7 @@ import { FileInterceptor } from "@nestjs/platform-express"; import { Response, response } from "express"; import { AssignTenantAdapter } from "./user-tenant-mapping.adapter"; -import { AssignTenantMappingDto } from "./dto/user-tenant-mapping.dto"; +import { UserTenantMappingDto } from "./dto/user-tenant-mapping.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("AssignTenant") @@ -48,16 +48,16 @@ export class AssignTenantController { @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) @ApiConflictResponse({ description: "Tenant is already assigned to this user." }) @UsePipes(new ValidationPipe()) - @ApiBody({ type: AssignTenantMappingDto }) + @ApiBody({ type: UserTenantMappingDto }) public async createCohort( @Headers() headers, @Req() request: Request, - @Body() assignTenantMappingDto: AssignTenantMappingDto, + @Body() userTenantMappingDto: UserTenantMappingDto, @Res() response: Response ) { const result = await this.assignTenantAdapter.buildAssignTenantAdapter().userTenantMapping( request, - assignTenantMappingDto + userTenantMappingDto ); return response.status(result.statusCode).json(result); } From 8fb8e3c01dfe1dec370b84862affdbf44b1eca53 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 7 May 2024 17:12:52 +0530 Subject: [PATCH 303/408] Task #218686 refactor findUserDetails to get tenants associated with user --- src/adapters/postgres/user-adapter.ts | 25 ++++++++++++++++++- src/user/entities/user-entity.ts | 11 +++++++- .../entities/user-tenant-mapping.entity.ts | 12 ++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index c44b10f4..7b59400f 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -255,10 +255,33 @@ export class PostgresUserService { delete whereClause.userId; whereClause.username = username; } - let userDetails = await this.usersRepository.findOne({ + let getUserDetails = await this.usersRepository.findOne({ where: whereClause }) + + const tenentDetails = await this.allUsersTenent(getUserDetails.userId) + let userDetails = { + userId: getUserDetails.userId, + userName: getUserDetails.username, + name: getUserDetails.name, + role: getUserDetails.role, + district: getUserDetails.district, + state: getUserDetails.state, + mobile: getUserDetails.mobile, + } + userDetails['tenantData']=tenentDetails; return userDetails; + + } + async allUsersTenent(userId: string){ + const query = ` + SELECT T.name AS tenantName, T.*, UTM."Id" AS userTenantMappingId + FROM public."UserTenantMapping" UTM + LEFT JOIN public."Tenants" T + ON T."tenantId" = UTM."tenantId" + WHERE UTM."userId" = $1`; + const result = await this.usersRepository.query(query, [userId]); + return result; } async findCustomFields(userData, role) { let customFields = await this.fieldsRepository.find({ diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts index a6963982..aea16248 100644 --- a/src/user/entities/user-entity.ts +++ b/src/user/entities/user-entity.ts @@ -1,4 +1,5 @@ -import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm"; +import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn, OneToMany } from "typeorm"; +import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; @Entity({ name: "Users" }) export class User { @@ -53,4 +54,12 @@ export class User { @Column({ default: "active" }) status: string; userRoleMappings: User; + + + // @OneToMany(() => CohortMembers, cohortMember => cohortMember.cohort) + // cohortMembers: CohortMembers[]; + + @OneToMany(() => UserTenantMapping, userTenantMapping => userTenantMapping.user) + userTenantMapping: UserTenantMapping[]; + } diff --git a/src/userTenantMapping/entities/user-tenant-mapping.entity.ts b/src/userTenantMapping/entities/user-tenant-mapping.entity.ts index 14733775..f2bf29a8 100644 --- a/src/userTenantMapping/entities/user-tenant-mapping.entity.ts +++ b/src/userTenantMapping/entities/user-tenant-mapping.entity.ts @@ -4,8 +4,11 @@ import { Column, CreateDateColumn, UpdateDateColumn, + ManyToOne, + JoinColumn, } from "typeorm"; - + import { User } from "src/user/entities/user-entity"; + @Entity({ name: "UserTenantMapping" }) export class UserTenantMapping { @PrimaryGeneratedColumn("uuid") @@ -34,5 +37,12 @@ import { @Column() updatedBy: string; + + + + @ManyToOne(() => User, user => user.userTenantMapping) + @JoinColumn({ name: 'userId' }) + user: User; + } \ No newline at end of file From c64048543ccabd0cead94e0ad8e71e164e309b7d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 7 May 2024 17:19:34 +0530 Subject: [PATCH 304/408] Task #218686 refactor findUserDetails to get tenants associated with user --- src/adapters/postgres/user-adapter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 7b59400f..09cdec30a 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -275,7 +275,7 @@ export class PostgresUserService { } async allUsersTenent(userId: string){ const query = ` - SELECT T.name AS tenantName, T.*, UTM."Id" AS userTenantMappingId + SELECT T.name AS tenantName, T."tenantId", UTM."Id" AS userTenantMappingId FROM public."UserTenantMapping" UTM LEFT JOIN public."Tenants" T ON T."tenantId" = UTM."tenantId" From 405f8ab53fc4bad1dc4cb675d130000292be475f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 7 May 2024 18:03:11 +0530 Subject: [PATCH 305/408] veriable name changes --- src/adapters/postgres/user-adapter.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 09cdec30a..580909f5 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -255,22 +255,22 @@ export class PostgresUserService { delete whereClause.userId; whereClause.username = username; } - let getUserDetails = await this.usersRepository.findOne({ + let userDetails = await this.usersRepository.findOne({ where: whereClause }) - const tenentDetails = await this.allUsersTenent(getUserDetails.userId) - let userDetails = { - userId: getUserDetails.userId, - userName: getUserDetails.username, - name: getUserDetails.name, - role: getUserDetails.role, - district: getUserDetails.district, - state: getUserDetails.state, - mobile: getUserDetails.mobile, + const tenentDetails = await this.allUsersTenent(userDetails.userId) + let userData = { + userId: userDetails.userId, + userName: userDetails.username, + name: userDetails.name, + role: userDetails.role, + district: userDetails.district, + state: userDetails.state, + mobile: userDetails.mobile, } - userDetails['tenantData']=tenentDetails; - return userDetails; + userData['tenantData']=tenentDetails; + return userData; } async allUsersTenent(userId: string){ From f5f79a65167fee5c1f386310b9c2c2f2bd15efc7 Mon Sep 17 00:00:00 2001 From: vaishali_k Date: Tue, 7 May 2024 20:11:38 +0530 Subject: [PATCH 306/408] Issue #0 fix: error while compiling 'in-memory-faceted-search' module not found --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index ed8ad249..58a4c265 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "express": "^4.17.3", "form-data": "^4.0.0", "graphql-tag": "^2.12.6", + "in-memory-faceted-search": "^1.0.1", "jwt-decode": "^3.1.2", "moment": "^2.30.1", "multer": "^1.4.4", From 427b71c82290af285ab35ec84a56b7570e4e809b Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Tue, 7 May 2024 20:49:27 +0530 Subject: [PATCH 307/408] Fix[Mark and update attendance change with additional column scope] --- src/adapters/postgres/attendance-adapter.ts | 29 ++++---- src/attendance/dto/attendance-search.dto.ts | 7 +- src/attendance/dto/attendance.dto.ts | 81 ++++++++++----------- 3 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index ccf41db1..72e79b9b 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -487,6 +487,9 @@ export class PostgresAttendanceService { attendanceDto ); } else { + if (!attendanceDto.scope) { + attendanceDto.scope = "student" + } attendanceDto.createdBy = loginUserId; attendanceDto.updatedBy = loginUserId; return await this.createAttendance(loginUserId, attendanceDto); @@ -523,8 +526,7 @@ export class PostgresAttendanceService { }); } - Object.assign(attendanceRecord, attendanceDto); - // this.attendanceRepository.merge(attendanceRecord, attendanceDto); + this.attendanceRepository.merge(attendanceRecord, attendanceDto); // Save the updated attendance record const updatedAttendanceRecord = await this.attendanceRepository.save( @@ -668,18 +670,19 @@ export class PostgresAttendanceService { const userAttendance = new AttendanceDto({ attendanceDate: attendanceData.attendanceDate, - contextId: attendanceData.contextId, - attendance: attendance.attendance, - userId: attendance.userId, + contextId: attendanceData?.contextId, + scope: attendanceData?.scope, + attendance: attendance?.attendance, + userId: attendance?.userId, tenantId: tenantId, - remark: attendance.remark, - latitude: attendance.latitude, - longitude: attendance.longitude, - image: attendance.image, - metaData: attendance.metaData, - syncTime: attendance.syncTime, - session: attendance.session, - contextType: attendance.contextType, + remark: attendance?.remark, + latitude: attendance?.latitude, + longitude: attendance?.longitude, + image: attendance?.image, + metaData: attendance?.metaData, + syncTime: attendance?.syncTime, + session: attendance?.session, + contextType: attendance?.contextType, }) const attendanceRes: any = await this.updateAttendanceRecord( diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index 7e5ff4de..0c3bd24a 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -7,12 +7,12 @@ import { Type } from "class-transformer"; export class AttendanceFiltersDto { - @ApiPropertyOptional() + @ApiPropertyOptional({default:"yyyy-mm-dd"}) @IsOptional() @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) fromDate?: Date; - @ApiPropertyOptional() + @ApiPropertyOptional({default:"yyyy-mm-dd"}) @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @IsOptional() toDate?: Date; @@ -20,7 +20,7 @@ @ApiPropertyOptional() @IsUUID() @IsOptional() - cohortId ?:string + contextId ?:string @ApiPropertyOptional() scope ?: string @@ -94,6 +94,7 @@ @ApiPropertyOptional({ description: "Facets", + example: [ "contextId","userId","scope"] }) facets?: string[]; diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 7defd361..38093e92 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -1,5 +1,5 @@ import { ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'; -import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, Validate, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; +import { IsDate, IsDateString, IsDefined, IsEnum, IsUUID, Matches, Validate, ValidateIf, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; import { Exclude, Expose, Transform, Type } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsNotEmpty, IsString, IsObject } from 'class-validator'; @@ -10,18 +10,24 @@ import { Cohort } from 'src/cohort/entities/cohort.entity'; //for student valid enum are[present,absent] //for teacher valid enum are[present,on-leave,half-day] -enum Attendance{ - present="present", - absent="absent", - onLeave="on-leave", - halfDay="half-day" +enum Attendance { + present = "present", + absent = "absent", + onLeave = "on-leave", + halfDay = "half-day" +} + +enum Scope { + self = 'self', + student = 'student', } @ValidatorConstraint({ name: 'isNotAfterToday', async: false }) export class IsNotAfterToday implements ValidatorConstraintInterface { validate(date: Date, args: ValidationArguments) { const currentDateIST = addHours(new Date(), 5.5); - return isBefore(date, currentDateIST); } + return isBefore(date, currentDateIST); + } defaultMessage(args: ValidationArguments) { return 'Attendance date must not be after today'; @@ -34,7 +40,7 @@ export class AttendanceDto { @Expose() tenantId: string; - @ApiProperty({ + @ApiProperty({ type: String, description: "The userid of the attendance", default: "", @@ -45,7 +51,7 @@ export class AttendanceDto { @Expose() userId: string; - @ManyToOne(() => User, {nullable:true}) + @ManyToOne(() => User, { nullable: true }) @JoinColumn({ name: 'userId' }) user: User; @@ -58,7 +64,7 @@ export class AttendanceDto { @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @Validate(IsNotAfterToday, { message: 'Attendance date must not be after today', - }) + }) @Expose() attendanceDate: Date; @@ -69,38 +75,25 @@ export class AttendanceDto { }) @Expose() @IsNotEmpty() - @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) + @IsEnum(Attendance, { message: "Please enter valid enum values for attendance [present, absent,on-leave, half-day]" }) attendance: string; - + @Expose() @ApiPropertyOptional() remark: string; - @ApiProperty({ - type: String, - description: "The latitude of the attendance", - default: 0, - }) + @Expose() @ApiPropertyOptional() latitude: number; - @ApiProperty({ - type: String, - description: "The longitude of the attendance", - default: 0, - }) + @Expose() @ApiPropertyOptional() longitude: number; - @ApiProperty({ - type: "string", - format: "binary", - description: "The image of person", - default: "NA", - }) + @Expose() @ApiPropertyOptional() image: string; @@ -125,11 +118,6 @@ export class AttendanceDto { @Expose() contextType: string; - @ApiProperty({ - type: String, - description: "The contextId of the attendance", - default: "", - }) @ApiProperty({ type: String, description: "The contextId of the attendance", @@ -143,7 +131,7 @@ export class AttendanceDto { @ManyToOne(() => Cohort, { nullable: true }) // Define the ManyToOne relationship with Cohort entity @JoinColumn({ name: "contextId", referencedColumnName: "cohortId" }) // Map contextId to cohortId column in Cohort table - cohort: Cohort; + cohort: Cohort; @CreateDateColumn() @@ -160,13 +148,13 @@ export class AttendanceDto { @Expose() updatedBy: string; - @Expose() - scope: string; + @ApiPropertyOptional() + @ValidateIf(o => o.scope !== undefined && o.scope !== null) @IsEnum(Scope, { message: "Please enter valid enum values for scope [self, student]" }) + scope: string constructor(obj: any) { Object.assign(this, obj); } - } @@ -184,7 +172,7 @@ export class UserAttendanceDTO { }) @Expose() @IsNotEmpty() - @IsEnum(Attendance,{message:"Please enter valid enum values for attendance [present, absent,on-leave, half-day]"}) + @IsEnum(Attendance, { message: "Please enter valid enum values for attendance [present, absent,on-leave, half-day]" }) attendance: string; @@ -235,25 +223,30 @@ export class BulkAttendanceDTO { @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) @Validate(IsNotAfterToday, { message: 'Attendance date must not be after today', - }) + }) @Expose() attendanceDate: Date; @IsUUID() - @Expose() - @IsNotEmpty() - @ApiProperty() + @Expose() + @IsNotEmpty() + @ApiProperty() contextId: string; + @ApiPropertyOptional() + @ValidateIf(o => o.scope !== undefined && o.scope !== null) + @IsEnum(Scope, { message: "Please enter valid enum values for scope [self, student]" }) + scope: string + @ApiProperty({ type: [UserAttendanceDTO], // Specify the type of userAttendance as an array of UserAttendanceDTO description: 'List of user attendance details', }) @ValidateNested({ each: true }) - @Type(() => UserAttendanceDTO) - // Adjust the max size according to your requirements + @Type(() => UserAttendanceDTO) + // Adjust the max size according to your requirements userAttendance: UserAttendanceDTO[]; constructor(obj: any) { From c9f7f7fd1a0656ddd8c005066566d5c0698c6f5f Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 8 May 2024 09:51:10 +0530 Subject: [PATCH 308/408] Fix[Set default limit for attendance search to 20] --- src/adapters/postgres/attendance-adapter.ts | 2 +- src/attendance/dto/attendance-search.dto.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 72e79b9b..12e5c362 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -38,7 +38,7 @@ export class PostgresAttendanceService { let { limit, page, filters, facets } = attendanceSearchDto; // Set default limit to 0 if not provided if (!limit) { - limit = 10; + limit = 20; } let offset = 0; diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index 0c3bd24a..7a3b5bee 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -67,11 +67,11 @@ export class AttendanceSearchDto { - @ApiProperty({ + @ApiPropertyOptional({ type: Number, description: "Limit", }) - @ValidateIf(o => !o.facets) + @IsOptional() @IsNotEmpty() @IsNumber({}, { message: 'Limit must be a number' }) limit: number; From ab19d60aec9402a2efbc2b4fff6ad4bf63c36131 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 8 May 2024 09:57:33 +0530 Subject: [PATCH 309/408] Fix[attendance enum change] --- src/attendance/dto/attendance.dto.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/attendance/dto/attendance.dto.ts b/src/attendance/dto/attendance.dto.ts index 38093e92..6442f8dd 100644 --- a/src/attendance/dto/attendance.dto.ts +++ b/src/attendance/dto/attendance.dto.ts @@ -13,8 +13,7 @@ import { Cohort } from 'src/cohort/entities/cohort.entity'; enum Attendance { present = "present", absent = "absent", - onLeave = "on-leave", - halfDay = "half-day" + onLeave = "on-leave" } enum Scope { @@ -75,7 +74,7 @@ export class AttendanceDto { }) @Expose() @IsNotEmpty() - @IsEnum(Attendance, { message: "Please enter valid enum values for attendance [present, absent,on-leave, half-day]" }) + @IsEnum(Attendance, { message: "Please enter valid enum values for attendance [present, absent,on-leave]" }) attendance: string; From 19040ff1e80f5b3879b355865794e7cea845c864 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 8 May 2024 11:00:16 +0530 Subject: [PATCH 310/408] query changes --- src/adapters/postgres/user-adapter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 580909f5..56471bf1 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -256,7 +256,8 @@ export class PostgresUserService { whereClause.username = username; } let userDetails = await this.usersRepository.findOne({ - where: whereClause + where: whereClause, + select: ["userId", "username", "name", "role", "district","state","mobile"] }) const tenentDetails = await this.allUsersTenent(userDetails.userId) From 994f5ccbde63d4af33fb635efb04009bb035c2f4 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 8 May 2024 11:30:20 +0530 Subject: [PATCH 311/408] update user api --- src/adapters/postgres/user-adapter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 56471bf1..92c6fb81 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -308,7 +308,7 @@ export class PostgresUserService { await this.updateBasicUserDetails(userDto.userId, userDto.userData); updatedData['basicDetails'] = userDto.userData; } - if (userDto.customFields.length > 0) { + if (userDto?.customFields?.length > 0) { for (let data of userDto.customFields) { const result = await this.updateCustomFields(userDto.userId, data); if (result) { From faafadc866ec817f9ef4b5d7f99e77a3adb613e2 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 8 May 2024 13:14:08 +0530 Subject: [PATCH 312/408] filter Changes --- src/adapters/postgres/user-adapter.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 92c6fb81..160bba04 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -261,17 +261,9 @@ export class PostgresUserService { }) const tenentDetails = await this.allUsersTenent(userDetails.userId) - let userData = { - userId: userDetails.userId, - userName: userDetails.username, - name: userDetails.name, - role: userDetails.role, - district: userDetails.district, - state: userDetails.state, - mobile: userDetails.mobile, - } - userData['tenantData']=tenentDetails; - return userData; + + userDetails['tenantData'] = tenentDetails; + return userDetails; } async allUsersTenent(userId: string){ From 4eecd27829ee7968a586a464dc9ad1bf68ce3b90 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 8 May 2024 16:18:03 +0530 Subject: [PATCH 313/408] Task #218277 : feat - added permission decorator --- src/common/decorators/permission.decorator.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/common/decorators/permission.decorator.ts diff --git a/src/common/decorators/permission.decorator.ts b/src/common/decorators/permission.decorator.ts new file mode 100644 index 00000000..ecc191a0 --- /dev/null +++ b/src/common/decorators/permission.decorator.ts @@ -0,0 +1,12 @@ +import { SetMetadata, createParamDecorator, ExecutionContext } from '@nestjs/common'; + +// Define a custom decorator to set permission metadata +export const Permissions = (...permissions: string[]) => SetMetadata('permissions', permissions); + +// Create a custom decorator to access permissions metadata +export const PermissionsDecorator = createParamDecorator( + (data: unknown, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + return request.permissions; + }, +); From 08dd2b68334c86a8069298bcb9e2021ced962f0f Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 8 May 2024 16:28:08 +0530 Subject: [PATCH 314/408] Task #218277 : feat - addded rbac strategy and guard --- src/authRbac/authRbac.service.ts | 2 +- src/common/guards/rbac.guard.ts | 32 +++++++++++++++++++++++++++--- src/common/guards/rbac.strategy.ts | 25 ++++++++++++++++++++--- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts index 1379aec1..e8dfd1e6 100644 --- a/src/authRbac/authRbac.service.ts +++ b/src/authRbac/authRbac.service.ts @@ -45,7 +45,7 @@ export class AuthRbacService { tenantId ); - userData["priviledges"] = await this.getPrivileges(userData.roles); + userData["privileges"] = await this.getPrivileges(userData.roles); userData["tenantId"] = tenantId; const issuer = this.issuer; diff --git a/src/common/guards/rbac.guard.ts b/src/common/guards/rbac.guard.ts index 93240b90..a80f8137 100644 --- a/src/common/guards/rbac.guard.ts +++ b/src/common/guards/rbac.guard.ts @@ -1,5 +1,31 @@ -import { Injectable } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; +import { ExecutionContext, Injectable } from "@nestjs/common"; +import { Reflector } from "@nestjs/core"; +import { AuthGuard } from "@nestjs/passport"; +import { Observable } from "rxjs"; @Injectable() -export class RbacAuthGuard extends AuthGuard('jwt-rbac') {} +export class RbacAuthGuard extends AuthGuard("jwt-rbac") { + constructor(private readonly reflector: Reflector) { + super(); + } + + canActivate( + context: ExecutionContext + ): boolean | Promise | Observable { + const requiredPermissions = this.reflector.get( + "permissions", + context.getHandler() + ); + + const payload = super.getRequest(context).user; + + if (!requiredPermissions) { + return true; // No permissions required, allow access + } + payload.requiredPermissions = requiredPermissions; + + const request = context.switchToHttp().getRequest(); + request.requiredPermissions = requiredPermissions; + return super.canActivate(context); + } +} diff --git a/src/common/guards/rbac.strategy.ts b/src/common/guards/rbac.strategy.ts index 964d777f..cf3ad857 100644 --- a/src/common/guards/rbac.strategy.ts +++ b/src/common/guards/rbac.strategy.ts @@ -10,18 +10,37 @@ export class RbacJwtStrategy extends PassportStrategy(Strategy, "jwt-rbac") { jwtFromRequest: ExtractJwt.fromHeader("rbac_token"), ignoreExpiration: false, secretOrKey: configService.get("RBAC_JWT_SECRET"), + passReqToCallback: true, }); } - async validate(payload: any) { + async validate(request: any, payload: any) { + const requiredPermissions = request.user.requiredPermissions; + const userPermissions = payload.userData.privileges.map(({ code }) => code); + const roles = payload.userData.roles.map(({ code }) => code); + + if (roles.includes("admin")) { + return payload; + } + if ( !( payload.iss === this.configService.get("ISSUER") && - payload.aud === this.configService.get("AUDIENCE") + payload.aud === this.configService.get("AUDIENCE") && + userPermissions.length > 0 ) ) { throw new UnauthorizedException(); } - return payload; + + const isAuthorized = requiredPermissions.every((permission: string) => + userPermissions.includes(permission) + ); + + if (isAuthorized) { + return payload; + } + + throw new UnauthorizedException(); } } From 4886164e806b1439f106e05b47f98056e22b90b0 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 8 May 2024 16:40:45 +0530 Subject: [PATCH 315/408] Task #218763 - fix: issue for user Auth API --- src/auth/auth.controller.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 3e0f810f..95756994 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -29,6 +29,7 @@ import { import { AuthService } from "./auth.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { RbacAuthGuard } from "src/common/guards/rbac.guard"; +import { Permissions } from "src/common/decorators/permission.decorator"; @ApiTags("Auth") @Controller("auth") @@ -45,10 +46,7 @@ export class AuthController { } @Get("/user") - @ApiHeader({ - name: "rbac_token", - }) - @UseGuards(JwtAuthGuard, RbacAuthGuard) + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -57,7 +55,7 @@ export class AuthController { }) public async getUserByAuth(@Req() request, @Res() response: Response) { console.log(request.user, "user"); - console.log(request.user.userData, "user"); + console.log(request.user.userData, "userData"); // const tenantId = headers["tenantid"]; return this.authService.getUserByAuth(request, response); } From 68d79e70073602e9dc11405e2e6ec490a7c1e2f3 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 8 May 2024 17:59:42 +0530 Subject: [PATCH 316/408] chore: uncommented role auth guard --- src/rbac/role/role.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index 7954bf9c..faf553cf 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -35,7 +35,7 @@ import { RoleAdapter } from "./roleadapter" @ApiTags("rbac") @Controller("rbac/roles") -// @UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard) export class RoleController { constructor(private readonly roleAdapter:RoleAdapter) { } From a2b04f1094caa6ae5c82c2a66ab80f374d8bc5ae Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Thu, 9 May 2024 13:22:52 +0530 Subject: [PATCH 317/408] Task:PS-338-chore[change in response structure for list API] --- src/adapters/postgres/attendance-adapter.ts | 6 +-- src/attendance/attendance.controller.ts | 42 --------------------- src/attendance/dto/attendance-search.dto.ts | 15 ++++++++ 3 files changed, 17 insertions(+), 46 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 12e5c362..054f3028 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -110,15 +110,13 @@ export class PostgresAttendanceService { // Process the data to calculate counts based on facets const tree = await this.facetedSearch({ data: attendanceList, facets: facetFields }); - // const result = Object.entries(tree).map(([key, value]) => ({ [key]: value })); - let result = []; + let result = {}; // Process the data to calculate counts based on facets for (const facet of facetFields) { const { field } = facet; const tree = await this.facetedSearch({ data: attendanceList, facets: [facet] }); - const formattedData = Object.entries(tree[field]).map(([key, value]) => ({ [key]: value })); - result.push({ [field]: formattedData }); // Modified the structure here + result[field] = tree[field]; } diff --git a/src/attendance/attendance.controller.ts b/src/attendance/attendance.controller.ts index b7eae755..ca226b9a 100644 --- a/src/attendance/attendance.controller.ts +++ b/src/attendance/attendance.controller.ts @@ -174,46 +174,4 @@ export class AttendanceController { return response.status(result.statusCode).json(result); } - @Post("/average-report") - @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Average attendance Report" }) - @ApiBadRequestResponse({ description: "Bad Request" }) - @ApiInternalServerErrorResponse({ description: "Internal Server error" }) - @ApiBody({ type: AttendanceStatsDto }) - @SerializeOptions({ - strategy: "excludeAll", - }) - @UsePipes(ValidationPipe) - public async report( - @Headers() headers, - @Req() request: Request, - @Res() response: Response, - @Body() attendanceStatsDto: AttendanceStatsDto - ) { - let tenantid = headers["tenantid"]; - - const result = await this.attendaceAdapter.buildAttenceAdapter().attendanceReport( - attendanceStatsDto - ); - return response.status(result.statusCode).json(result); - } - - /** No longer required in Shiksha 2.0 */ - /* - @Get("usersegment/:attendance") - @UseInterceptors(ClassSerializerInterceptor) - // @ApiBasicAuth("access-token") - @ApiOkResponse({ description: " Ok." }) - @ApiForbiddenResponse({ description: "Forbidden" }) - @ApiQuery({ name: "groupId", required: false }) - @ApiQuery({ name: "date" }) - public async userSegment( - @Query("groupId") groupId: string, - @Param("attendance") attendance: string, - @Query("date") date: string, - @Req() request: Request - ) { - return await this.service.userSegment(groupId, attendance, date, request); - } - */ } diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index 7a3b5bee..2fc18850 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -6,10 +6,25 @@ import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; import { Type } from "class-transformer"; + + @ValidatorConstraint({ name: 'isNotAfterFromDate', async: false }) +export class IsFromDateBeforeToDateConstraint implements ValidatorConstraintInterface { + validate(fromDate: Date, args: ValidationArguments) { + const toDate = args.object[args.constraints[0]]; + const res = isSameDay(fromDate, toDate) || isBefore(fromDate, toDate); + return res + } + + defaultMessage(args: ValidationArguments) { + return 'From Date must be before or equal to To Date'; + } +} + export class AttendanceFiltersDto { @ApiPropertyOptional({default:"yyyy-mm-dd"}) @IsOptional() @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @Validate(IsFromDateBeforeToDateConstraint, ['toDate']) fromDate?: Date; @ApiPropertyOptional({default:"yyyy-mm-dd"}) From 85fef885847337624e1eed0eb2a0402996f1d19b Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 9 May 2024 19:12:27 +0530 Subject: [PATCH 318/408] Task #218845 : chore - added error handling and validation to rbac token api --- src/authRbac/authRbac.controller.ts | 7 +++++++ src/authRbac/authRbac.service.ts | 12 +++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/authRbac/authRbac.controller.ts b/src/authRbac/authRbac.controller.ts index a4c9f58c..04568afc 100644 --- a/src/authRbac/authRbac.controller.ts +++ b/src/authRbac/authRbac.controller.ts @@ -5,10 +5,12 @@ import { Get, UseGuards, Req, + BadRequestException, } from "@nestjs/common"; import { AuthRbacService } from "./authRbac.service"; import { ApiBasicAuth, ApiHeader, ApiTags } from "@nestjs/swagger"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { isUUID } from "class-validator"; @ApiTags("AuthRbac") @Controller("auth/rbac") @@ -19,11 +21,16 @@ export class AuthRbacController { @Get("/token") @ApiHeader({ name: "tenantid", + required: true, + description: "Tenant Id", }) @ApiBasicAuth("access-token") @UseGuards(JwtAuthGuard) signInRbac(@Req() req) { const tenantId = req.headers["tenantid"]; + if (!isUUID(tenantId)) { + throw new BadRequestException("Please add valid Tenant ID"); + } return this.authService.signInRbac(req.user.username, tenantId); } } diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts index e8dfd1e6..7a60600b 100644 --- a/src/authRbac/authRbac.service.ts +++ b/src/authRbac/authRbac.service.ts @@ -1,4 +1,8 @@ -import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { + BadRequestException, + Injectable, + UnauthorizedException, +} from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { JwtService } from "@nestjs/jwt"; import { PostgresRoleService } from "src/adapters/postgres/rbac/role-adapter"; @@ -36,8 +40,10 @@ export class AuthRbacService { .buildUserAdapter() .findUserDetails(null, username); - if (!userData) { - throw new UnauthorizedException(); + if (!userData || !tenantId || !userData?.roles?.length) { + throw new BadRequestException( + "User details or tenant not found for user" + ); } userData["roles"] = await this.postgresRoleService.findUserRoleData( From af6777f5e0f7c36ff488f8d2c114d2a0794b1760 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 9 May 2024 19:13:51 +0530 Subject: [PATCH 319/408] Task #218845 : chore - removed console logs --- src/auth/auth.controller.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 95756994..f75ac149 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -54,9 +54,6 @@ export class AuthController { strategy: "excludeAll", }) public async getUserByAuth(@Req() request, @Res() response: Response) { - console.log(request.user, "user"); - console.log(request.user.userData, "userData"); - // const tenantId = headers["tenantid"]; return this.authService.getUserByAuth(request, response); } From 8f5f979b5463d40fe9802794db6610b4bc3da96c Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 9 May 2024 20:18:41 +0530 Subject: [PATCH 320/408] Task #218845 : refactor - RBAC token to reduce size --- src/authRbac/authRbac.service.ts | 15 +++++++++++---- src/common/guards/rbac.guard.ts | 6 +++--- src/common/guards/rbac.strategy.ts | 5 +++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/authRbac/authRbac.service.ts b/src/authRbac/authRbac.service.ts index 7a60600b..f758bb10 100644 --- a/src/authRbac/authRbac.service.ts +++ b/src/authRbac/authRbac.service.ts @@ -40,18 +40,23 @@ export class AuthRbacService { .buildUserAdapter() .findUserDetails(null, username); - if (!userData || !tenantId || !userData?.roles?.length) { + if (!userData || !tenantId) { throw new BadRequestException( "User details or tenant not found for user" ); } - userData["roles"] = await this.postgresRoleService.findUserRoleData( + const userRoles = await this.postgresRoleService.findUserRoleData( userData?.userId, tenantId ); - userData["privileges"] = await this.getPrivileges(userData.roles); + if (!userRoles?.length) { + throw new BadRequestException("Roles not found for user"); + } + + userData["roles"] = userRoles.map(({ code }) => code); + userData["privileges"] = await this.getPrivileges(userRoles); userData["tenantId"] = tenantId; const issuer = this.issuer; @@ -73,9 +78,11 @@ export class AuthRbacService { if (!roleIds.length) { return []; } - const privileges = await this.postgresRoleService.findPrivilegeByRoleId( + const privilegesData = await this.postgresRoleService.findPrivilegeByRoleId( roleIds ); + + const privileges = privilegesData.map(({ code }) => code); return privileges; } } diff --git a/src/common/guards/rbac.guard.ts b/src/common/guards/rbac.guard.ts index a80f8137..b8e6a586 100644 --- a/src/common/guards/rbac.guard.ts +++ b/src/common/guards/rbac.guard.ts @@ -12,6 +12,7 @@ export class RbacAuthGuard extends AuthGuard("jwt-rbac") { canActivate( context: ExecutionContext ): boolean | Promise | Observable { + // Required permissions come from permission decorator for each API end point const requiredPermissions = this.reflector.get( "permissions", context.getHandler() @@ -23,9 +24,8 @@ export class RbacAuthGuard extends AuthGuard("jwt-rbac") { return true; // No permissions required, allow access } payload.requiredPermissions = requiredPermissions; - - const request = context.switchToHttp().getRequest(); - request.requiredPermissions = requiredPermissions; + // const request = context.switchToHttp().getRequest(); + // request.requiredPermissions = requiredPermissions; return super.canActivate(context); } } diff --git a/src/common/guards/rbac.strategy.ts b/src/common/guards/rbac.strategy.ts index cf3ad857..5a790f81 100644 --- a/src/common/guards/rbac.strategy.ts +++ b/src/common/guards/rbac.strategy.ts @@ -16,8 +16,9 @@ export class RbacJwtStrategy extends PassportStrategy(Strategy, "jwt-rbac") { async validate(request: any, payload: any) { const requiredPermissions = request.user.requiredPermissions; - const userPermissions = payload.userData.privileges.map(({ code }) => code); - const roles = payload.userData.roles.map(({ code }) => code); + + const userPermissions = payload.userData.privileges; + const roles = payload.userData.roles; if (roles.includes("admin")) { return payload; From 35152a2365a53ffc126a017f44cfcf40df748ad3 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 10 May 2024 09:55:59 +0530 Subject: [PATCH 321/408] response body changes --- .../postgres/cohortMembers-adapter.ts | 26 +++++++------------ src/cohortMembers/cohortMember.service.ts | 6 ++--- .../dto/cohortMembers-search.dto.ts | 4 +-- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index 60a9dc0d..3ff0d06c 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -85,15 +85,14 @@ export class PostgresCohortMembersService { role: data?.role, district: data?.district, state: data?.state, - mobile: data?.mobile, - customField: [], + mobile: data?.mobile }; if (fieldShowHide === "false") { results.userDetails.push(userDetails); } else { - const fieldValues = await this.getFieldandFieldValues(data.userId); - userDetails.customField.push(fieldValues); + const fieldValues = await this.getFieldandFieldValues(data.userId); + userDetails['customField'] = fieldValues; results.userDetails.push(userDetails); } } @@ -159,11 +158,9 @@ export class PostgresCohortMembersService { let { limit, page, filters } = cohortMembersSearchDto; let offset = 0; if (page > 1) { - offset = parseInt(limit) * (page - 1); - } - if (limit.trim() === "") { - limit = "0"; + offset = limit * (page - 1); } + const whereClause = {}; if (filters && Object.keys(filters).length > 0) { Object.entries(filters).forEach(([key, value]) => { @@ -212,26 +209,23 @@ export class PostgresCohortMembersService { const [userData] = await this.cohortMembersRepository.findAndCount({ where: whereClause, skip: offset, - take: parseInt(limit), + take: limit, }); - let results = { - userDetails: [], - }; + let results = {}; if (whereClause["cohortId"]) { - let cohortDetails = await this.getUserDetails( + results = await this.getUserDetails( whereClause["cohortId"], "cohortId", "true" ); - results.userDetails.push(cohortDetails); } + if (whereClause["userId"]) { - let cohortDetails = await this.getUserDetails( + results = await this.getUserDetails( whereClause["userId"], "userId", "true" ); - results.userDetails.push(cohortDetails); } return new SuccessResponse({ diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 8a5f036b..f805b736 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -83,12 +83,12 @@ export class CohortMembersService { try { let { limit, page, filters } = cohortMembersSearchDto; if (!limit) { - limit = "0"; + limit = 0; } let offset = 0; if (page > 1) { - offset = parseInt(limit) * (page - 1); + offset = limit * (page - 1); } const whereClause = {}; @@ -113,7 +113,7 @@ export class CohortMembersService { let filterDetails = { where: data.cohortId, - take: parseInt(limit), + take: limit, skip: offset, }; diff --git a/src/cohortMembers/dto/cohortMembers-search.dto.ts b/src/cohortMembers/dto/cohortMembers-search.dto.ts index b91425fe..f5f207de 100644 --- a/src/cohortMembers/dto/cohortMembers-search.dto.ts +++ b/src/cohortMembers/dto/cohortMembers-search.dto.ts @@ -2,10 +2,10 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; export class CohortMembersSearchDto { @ApiProperty({ - type: String, + type: Number, description: "Limit", }) - limit: string; + limit: number; @ApiProperty({ type: Number, From 685381082e54bd272027c717026a2e8198b920c3 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Fri, 10 May 2024 10:01:03 +0530 Subject: [PATCH 322/408] response body changes --- src/cohortMembers/cohortMember.service.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index f805b736..23bd38fe 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -82,9 +82,6 @@ export class CohortMembersService { try { let { limit, page, filters } = cohortMembersSearchDto; - if (!limit) { - limit = 0; - } let offset = 0; if (page > 1) { From 64ee1b32ee79a09e92ea3ea94e0d7fd4c2bab092 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Fri, 10 May 2024 13:46:01 +0530 Subject: [PATCH 323/408] Task #218848: feat - config List for privileges --- src/common/decorators/permission.config.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/common/decorators/permission.config.ts diff --git a/src/common/decorators/permission.config.ts b/src/common/decorators/permission.config.ts new file mode 100644 index 00000000..0861cdfd --- /dev/null +++ b/src/common/decorators/permission.config.ts @@ -0,0 +1,22 @@ +/** +List of permssions in the system +*/ + +export const PERMISSIONS = { + USERS_CREATE: "users.create", + USERS_READ: "users.read", + USERS_UPDATE: "users.update", + USERS_DELETE: "users.delete", + ATTENDANCE_CREATE: "attendance.create", + ATTENDANCE_READ: "attendance.read", + ATTENDANCE_UPDATE: "attendance.update", + ATTENDANCE_DELETE: "attendance.delete", + COHORT_CREATE: "cohort.create", + COHORT_READ: "cohort.read", + COHORT_UPDATE: "cohort.update", + COHORT_DELETE: "cohort.delete", + COHORTMEMBERS_CREATE: "cohortmembers.create", + COHORTMEMBERS_READ: "cohortmembers.read", + COHORTMEMBERS_UPDATE: "cohortmembers.update", + COHORTMEMBERS_DELETE: "cohortmembers.delete", +}; From 2a6c57a79ac0783632c7d2887188c56c1efb1070 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 10 May 2024 14:12:28 +0530 Subject: [PATCH 324/408] Task #216365 fix: Added Email Support in Create Users API and Updated Search Error message --- src/adapters/postgres/user-adapter.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 160bba04..bee881b7 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -47,10 +47,10 @@ export class PostgresUserService { userSearchDto: UserSearchDto) { try { let findData = await this.findAllUserDetails(userSearchDto); - if (!findData) { + if (!findData.length) { return new SuccessResponse({ statusCode: HttpStatus.BAD_REQUEST, - message: 'No Data Found For User', + message: 'Either Filter is wrong or No Data Found For the User', }); } return new SuccessResponse({ @@ -89,6 +89,7 @@ export class PostgresUserService { skip: offset, take: parseInt(limit), }); + console.log(results); return results; } @@ -419,12 +420,7 @@ export class PostgresUserService { } ); userCreateDto.userId = resKeycloak; - - - - - - if (errors.length > 0) { + if (errors.length > 0) { return { statusCode: HttpStatus.BAD_REQUEST, errorCount: errors.length, @@ -487,16 +483,17 @@ export class PostgresUserService { const user = new User() user.username = userCreateDto?.username user.name = userCreateDto?.name + user.email = userCreateDto?.email user.role = userCreateDto?.role user.mobile = Number(userCreateDto?.mobile) || null, - user.tenantId = null + user.tenantId = null user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, - user.state = userCreateDto?.state, - user.district = userCreateDto?.district, - user.address = userCreateDto?.address, - user.pincode = userCreateDto?.pincode + user.state = userCreateDto?.state, + user.district = userCreateDto?.district, + user.address = userCreateDto?.address, + user.pincode = userCreateDto?.pincode if (userCreateDto?.dob) { user.dob = new Date(userCreateDto.dob); From 081052638dd8a205d25b85cd01e589eb761dd30c Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sat, 11 May 2024 09:52:11 +0530 Subject: [PATCH 325/408] User: Editable fields show and update --- src/adapters/postgres/user-adapter.ts | 57 +++++++++++++++++++++------ src/user/entities/field-entity.ts | 3 ++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index bee881b7..dbfc5e01 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -89,7 +89,6 @@ export class PostgresUserService { skip: offset, take: parseInt(limit), }); - console.log(results); return results; } @@ -126,6 +125,7 @@ export class PostgresUserService { } const customFields = await this.findCustomFields(userData, userDetails.role) + result.userData = userDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { @@ -134,6 +134,8 @@ export class PostgresUserService { fieldId: data.fieldId, label: data.label, value: fieldValue || '', + isRequired: data.fieldAttributes ? data.fieldAttributes['isRequired'] : '', + isEditable: data.fieldAttributes ? data.fieldAttributes['isEditable'] : '', options: data?.fieldParams?.['options'] || {}, type: data.type || '' }; @@ -143,7 +145,7 @@ export class PostgresUserService { return new SuccessResponse({ statusCode: HttpStatus.OK, - message: 'Ok.', + message: 'User detais Fetched Succcessfully.', data: result, }); @@ -284,12 +286,17 @@ export class PostgresUserService { contextType: role.toUpperCase() } }) + return customFields; } async findFilledValues(userId: string) { - let query = `SELECT U."userId",F."fieldId",F."value" FROM public."Users" U - LEFT JOIN public."FieldValues" F - ON U."userId" = F."itemId" where U."userId" =$1`; + let query = `SELECT U."userId",FV."fieldId",FV."value", F."fieldAttributes" FROM public."Users" U + LEFT JOIN public."FieldValues" FV + ON U."userId" = FV."itemId" + LEFT JOIN public."Fields" F + ON F."fieldId" = FV."fieldId" + where U."userId" =$1`; + let result = await this.usersRepository.query(query, [userId]); return result; } @@ -297,24 +304,50 @@ export class PostgresUserService { async updateUser(userDto, response) { try { let updatedData = {}; + let errorMessage; if (userDto.userData || Object.keys(userDto.userData).length > 0) { await this.updateBasicUserDetails(userDto.userId, userDto.userData); updatedData['basicDetails'] = userDto.userData; } + if (userDto?.customFields?.length > 0) { + + const getFieldsAttributesQuery = ` + SELECT * + FROM "public"."Fields" + WHERE "contextType"='STUDENT' AND "fieldAttributes"->>'isEditable' = $1 + `; + const getFieldsAttributesParams = ['true']; + const getFieldsAttributes = await this.fieldsRepository.query(getFieldsAttributesQuery, getFieldsAttributesParams); + + let isEditableFieldId = []; + for (let fieldDetails of getFieldsAttributes) { + isEditableFieldId.push(fieldDetails.fieldId); + } + + // let errorMessage = []; + let unEditableIdes = []; for (let data of userDto.customFields) { - const result = await this.updateCustomFields(userDto.userId, data); - if (result) { - if (!updatedData['customFields']) - updatedData['customFields'] = []; - updatedData['customFields'].push(result); + if(isEditableFieldId.includes(data.fieldId)){ + const result = await this.updateCustomFields(userDto.userId, data); + if (result) { + if (!updatedData['customFields']) + updatedData['customFields'] = []; + updatedData['customFields'].push(result); + } + }else{ + unEditableIdes.push(data.fieldId) } } + if (unEditableIdes.length > 0) { + errorMessage = `Uneditable fields: ${unEditableIdes.join(', ')}` + } } - return new SuccessResponse({ + return ({ statusCode: 200, - message: "ok", + message: "User has been updated successfully.", data: updatedData, + error:errorMessage }); } catch (e) { return new ErrorResponseTypeOrm({ diff --git a/src/user/entities/field-entity.ts b/src/user/entities/field-entity.ts index bc5aaec8..77df953a 100644 --- a/src/user/entities/field-entity.ts +++ b/src/user/entities/field-entity.ts @@ -76,4 +76,7 @@ export class Field { @Column({ type: 'jsonb', nullable: true }) fieldParams: object; + + @Column({ type: 'jsonb', nullable: true }) + fieldAttributes: object; } From 4e7367f4ebcb752a82d43cdbc577075041ddd601 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 14 May 2024 16:46:39 +0530 Subject: [PATCH 326/408] JIRA PS-371 User create wrapper API - mapping user to tenanat with roles, adding field Values, adding users to cohorts --- src/adapters/hasura/cohortMembers.adapter.ts | 110 ++++--- src/adapters/hasura/user.adapter.ts | 232 ++++++------- .../postgres/cohortMembers-adapter.ts | 167 ++++++++-- src/adapters/postgres/potsgres-module.ts | 6 +- .../postgres/rbac/assignrole-adapter.ts | 2 +- src/adapters/postgres/user-adapter.ts | 309 +++++++++++------- src/cohortMembers/cohortMember.service.ts | 2 - .../dto/cohortMembers-search.dto.ts | 2 +- src/cohortMembers/dto/cohortMembers.dto.ts | 36 +- .../entities/cohort-member.entity.ts | 6 - .../assign-role/assign-role.controller.ts | 4 +- src/user/dto/user-create.dto.ts | 69 ++-- src/user/entities/user-entity.ts | 6 - src/user/user.controller.ts | 8 +- src/user/user.module.ts | 6 +- 15 files changed, 566 insertions(+), 399 deletions(-) diff --git a/src/adapters/hasura/cohortMembers.adapter.ts b/src/adapters/hasura/cohortMembers.adapter.ts index 15a37f73..4b388c8c 100644 --- a/src/adapters/hasura/cohortMembers.adapter.ts +++ b/src/adapters/hasura/cohortMembers.adapter.ts @@ -6,6 +6,7 @@ const resolvePath = require("object-resolve-path"); import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-search.dto"; import { IServicelocatorcohortMembers } from "../cohortMembersservicelocator"; +import { CohortMembersUpdateDto } from "src/cohortMembers/dto/cohortMember-update.dto"; @Injectable() export class HasuraCohortMembersService @@ -79,66 +80,67 @@ export class HasuraCohortMembersService public async updateCohortMembers( cohortMembershipId: string, request: any, - cohortMembersDto: CohortMembersDto + cohortMembersUpdateDto: CohortMembersUpdateDto, + response: any ) { - var axios = require("axios"); + // var axios = require("axios"); - let query = ""; - Object.keys(cohortMembersDto).forEach((e) => { - if (cohortMembersDto[e] && cohortMembersDto[e] != "") { - if (Array.isArray(cohortMembersDto[e])) { - query += `${e}: "${JSON.stringify(cohortMembersDto[e])}", `; - } else { - query += `${e}: "${cohortMembersDto[e]}", `; - } - } - }); + // let query = ""; + // Object.keys(cohortMembersDto).forEach((e) => { + // if (cohortMembersDto[e] && cohortMembersDto[e] != "") { + // if (Array.isArray(cohortMembersDto[e])) { + // query += `${e}: "${JSON.stringify(cohortMembersDto[e])}", `; + // } else { + // query += `${e}: "${cohortMembersDto[e]}", `; + // } + // } + // }); - var data = { - query: ` - mutation UpdateCohortMembers($cohortMembershipId:uuid!) { - update_CohortMembers_by_pk( - pk_columns: { - cohortMembershipId: $cohortMembershipId - }, - _set: { - ${query} - } - ) { - cohortMembershipId - } - } - `, - variables: { - cohortMembershipId: cohortMembershipId, - }, - }; + // var data = { + // query: ` + // mutation UpdateCohortMembers($cohortMembershipId:uuid!) { + // update_CohortMembers_by_pk( + // pk_columns: { + // cohortMembershipId: $cohortMembershipId + // }, + // _set: { + // ${query} + // } + // ) { + // cohortMembershipId + // } + // } + // `, + // variables: { + // cohortMembershipId: cohortMembershipId, + // }, + // }; - var config = { - method: "post", - url: process.env.REGISTRYHASURA, - headers: { - "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - "Content-Type": "application/json", - }, - data: data, - }; + // var config = { + // method: "post", + // url: process.env.REGISTRYHASURA, + // headers: { + // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, + // "Content-Type": "application/json", + // }, + // data: data, + // }; - const response = await axios(config); + // const response = await axios(config); - if (response?.data?.errors) { - return new ErrorResponse({ - errorCode: response?.data?.errors[0]?.extensions?.code, - errorMessage: response?.data?.errors[0]?.message, - }); - } else { - let result = response.data.data; - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } + // if (response?.data?.errors) { + // return new ErrorResponse({ + // errorCode: response?.data?.errors[0]?.extensions?.code, + // errorMessage: response?.data?.errors[0]?.message, + // }); + // } else { + // let result = response.data.data; + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } } public async mappedResponse(result: any) { diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 9681ebb7..63f17a0e 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -144,126 +144,126 @@ export class HasuraUserService implements IServicelocator { // } public async checkAndAddUser(request: any, userDto: UserCreateDto) { - try { - const decoded: any = jwt_decode(request.headers.authorization); - const altUserRoles = - decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; - - const userId = - decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - userDto.createdBy = userId; - userDto.updatedBy = userId; - - if ( - !userDto.username || - !userDto.password || - !userDto.role || - !userDto.name - ) { - return new ErrorResponse({ - errorCode: "400", - errorMessage: "Name, username, password and role are required", - }); - } - - const keycloakResponse = await getKeycloakAdminToken(); - const token = keycloakResponse.data.access_token; - - const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( - userDto.username, - token - ); - if (usernameExistsInKeycloak?.data[0]?.username) { - const usernameExistsInDB: any = await this.getUserByUsername( - usernameExistsInKeycloak?.data[0]?.username, - request - ); - if (usernameExistsInDB?.statusCode === 200) { - if (usernameExistsInDB?.data) { - return usernameExistsInDB; - } else { - const resetPasswordRes: any = await this.resetKeycloakPassword( - request, - token, - userDto.password, - usernameExistsInKeycloak?.data[0]?.id - ); - - if (resetPasswordRes.statusCode !== 204) { - return new ErrorResponse({ - errorCode: "400", - errorMessage: "Something went wrong in password reset", - }); - } - - userDto.userId = usernameExistsInKeycloak?.data[0]?.id; - const newlyCreatedDbUser = await this.createUserInDatabase( - request, - userDto - ); - - return newlyCreatedDbUser; - } - } else { - return usernameExistsInDB; - } - } else { - return await this.createUser(request, userDto); - } - } catch (e) { - console.error(e); - return e; - } + // try { + // const decoded: any = jwt_decode(request.headers.authorization); + // const altUserRoles = + // decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; + + // const userId = + // decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + // userDto.createdBy = userId; + // userDto.updatedBy = userId; + + // if ( + // !userDto.username || + // !userDto.password || + // !userDto.role || + // !userDto.name + // ) { + // return new ErrorResponse({ + // errorCode: "400", + // errorMessage: "Name, username, password and role are required", + // }); + // } + + // const keycloakResponse = await getKeycloakAdminToken(); + // const token = keycloakResponse.data.access_token; + + // const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( + // userDto.username, + // token + // ); + // if (usernameExistsInKeycloak?.data[0]?.username) { + // const usernameExistsInDB: any = await this.getUserByUsername( + // usernameExistsInKeycloak?.data[0]?.username, + // request + // ); + // if (usernameExistsInDB?.statusCode === 200) { + // if (usernameExistsInDB?.data) { + // return usernameExistsInDB; + // } else { + // const resetPasswordRes: any = await this.resetKeycloakPassword( + // request, + // token, + // userDto.password, + // usernameExistsInKeycloak?.data[0]?.id + // ); + + // if (resetPasswordRes.statusCode !== 204) { + // return new ErrorResponse({ + // errorCode: "400", + // errorMessage: "Something went wrong in password reset", + // }); + // } + + // userDto.userId = usernameExistsInKeycloak?.data[0]?.id; + // const newlyCreatedDbUser = await this.createUserInDatabase( + // request, + // userDto + // ); + + // return newlyCreatedDbUser; + // } + // } else { + // return usernameExistsInDB; + // } + // } else { + // return await this.createUser(request, userDto); + // } + // } catch (e) { + // console.error(e); + // return e; + // } } public async createUser(request: any, userCreateDto: UserCreateDto) { // It is considered that if user is not present in keycloak it is not present in database as well - try { - const decoded: any = jwt_decode(request.headers.authorization); - const userRoles = - decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; - - const userId = - decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - userCreateDto.createdBy = userId; - userCreateDto.updatedBy = userId; - - userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); - - const userSchema = new UserCreateDto(userCreateDto); - - let errKeycloak = ""; - let resKeycloak = ""; - - // if (altUserRoles.includes("systemAdmin")) { - - const keycloakResponse = await getKeycloakAdminToken(); - const token = keycloakResponse.data.access_token; - - resKeycloak = await createUserInKeyCloak(userSchema, token).catch( - (error) => { - errKeycloak = error.response?.data.errorMessage; - - return new ErrorResponse({ - errorCode: "500", - errorMessage: "Someting went wrong", - }); - } - ); - // } else { - // return new ErrorResponse({ - // errorCode: "401", - // errorMessage: "Unauthorized", - // }); - // } - - // Add userId created in keycloak as user Id of ALT user - userCreateDto.userId = resKeycloak; - return await this.createUserInDatabase(request, userCreateDto); - } catch (e) { - console.error(e); - return e; - } + // try { + // const decoded: any = jwt_decode(request.headers.authorization); + // const userRoles = + // decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; + + // const userId = + // decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; + // userCreateDto.createdBy = userId; + // userCreateDto.updatedBy = userId; + + // userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); + + // const userSchema = new UserCreateDto(userCreateDto); + + // let errKeycloak = ""; + // let resKeycloak = ""; + + // // if (altUserRoles.includes("systemAdmin")) { + + // const keycloakResponse = await getKeycloakAdminToken(); + // const token = keycloakResponse.data.access_token; + + // resKeycloak = await createUserInKeyCloak(userSchema, token).catch( + // (error) => { + // errKeycloak = error.response?.data.errorMessage; + + // return new ErrorResponse({ + // errorCode: "500", + // errorMessage: "Someting went wrong", + // }); + // } + // ); + // // } else { + // // return new ErrorResponse({ + // // errorCode: "401", + // // errorMessage: "Unauthorized", + // // }); + // // } + + // // Add userId created in keycloak as user Id of ALT user + // userCreateDto.userId = resKeycloak; + // return await this.createUserInDatabase(request, userCreateDto); + // } catch (e) { + // console.error(e); + // return e; + // } } async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index 3ff0d06c..2f3b1fd7 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -30,7 +30,7 @@ export class PostgresCohortMembersService { private usersRepository: Repository, @InjectRepository(Cohort) private cohortRepository: Repository - ) {} + ) { } async getCohortMembers(cohortId: any, fieldvalue: any) { try { @@ -91,7 +91,7 @@ export class PostgresCohortMembersService { if (fieldShowHide === "false") { results.userDetails.push(userDetails); } else { - const fieldValues = await this.getFieldandFieldValues(data.userId); + const fieldValues = await this.getFieldandFieldValues(data.userId); userDetails['customField'] = fieldValues; results.userDetails.push(userDetails); } @@ -151,6 +151,7 @@ export class PostgresCohortMembersService { let result = await this.usersRepository.query(query, [searchData]); return result; } + public async searchCohortMembers( cohortMembersSearchDto: CohortMembersSearchDto ) { @@ -206,27 +207,32 @@ export class PostgresCohortMembersService { }); } } - const [userData] = await this.cohortMembersRepository.findAndCount({ - where: whereClause, - skip: offset, - take: limit, - }); + + // console.log("USER DATA ",userData) let results = {}; - if (whereClause["cohortId"]) { - results = await this.getUserDetails( - whereClause["cohortId"], - "cohortId", - "true" - ); - } - - if (whereClause["userId"]) { - results = await this.getUserDetails( - whereClause["userId"], - "userId", - "true" + let where = []; + if (whereClause["cohortId"]) { + where.push(["cohortId", whereClause["cohortId"]]); + } + if (whereClause["userId"]) { + where.push(["userId", whereClause["userId"]]); + } + if (whereClause["role"]) { + where.push(["role", whereClause["role"]]); + } + let options = []; + if (limit) { + options.push(['limit',limit]); + } + if (offset) { + options.push(['offset',offset]); + } + + results = await this.getCohortMemberUserDetails( + where, + "true", + options ); - } return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -234,6 +240,7 @@ export class PostgresCohortMembersService { data: results, }); } catch (e) { + console.log(e) return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, errorMessage: e, @@ -241,16 +248,62 @@ export class PostgresCohortMembersService { } } + async getCohortMemberUserDetails(where: any, fieldShowHide: any, options: any) { + let results = { + userDetails: [], + }; + + let getUserDetails = await this.getUsers(where, options); + + for (let data of getUserDetails) { + let userDetails = { + userId: data?.userId, + userName: data?.userName, + name: data?.name, + role: data?.role, + district: data?.district, + state: data?.state, + mobile: data?.mobile + }; + + if (fieldShowHide === "false") { + results.userDetails.push(userDetails); + } else { + const fieldValues = await this.getFieldandFieldValues(data.userId); + userDetails['customField'] = fieldValues; + results.userDetails.push(userDetails); + } + } + + return results; + } + public async createCohortMembers( loginUser: any, cohortMembers: CohortMembersDto, response: any ) { - const apiId = "api.cohortMember.createCohortMembers"; try { cohortMembers.createdBy = loginUser; cohortMembers.updatedBy = loginUser; + + await this.validateEntity(this.cohortRepository, { cohortId: cohortMembers.cohortId }, `Cohort Id does not exist.`); + await this.validateEntity(this.usersRepository, { userId: cohortMembers.userId }, `User Id does not exist.`); + + const existrole = await this.cohortMembersRepository.find({ + where:{ + userId: cohortMembers.userId, + cohortId: cohortMembers.cohortId + } + }) + if(existrole.length>0){ + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: `This user '${cohortMembers.userId}' already assign for this cohort '${cohortMembers.cohortId}'.`, + }); + } + // Create a new CohortMembers entity and populate it with cohortMembers data const savedCohortMember = await this.cohortMembersRepository.save( cohortMembers @@ -262,9 +315,70 @@ export class PostgresCohortMembersService { data: savedCohortMember, }); } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, + if (e instanceof ErrorResponseTypeOrm) { + return e; + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.toString(), // or any custom error message you want + }); + } + } + } + + async getUsers(where: any, options: any) { + let query = ``; + let whereCase = ``; + let optionsCase = ``; + let isRoleCondition = 0; + console.log("WHERE ",where) + console.log("LENGTH ",where.length); + if (where.length > 0) { + whereCase = `where `; + where.forEach((value,index) => { + if(value[0]=="role") { + isRoleCondition=1; + whereCase += `R."name"='${value[1]}' `; + } else { + whereCase += `CM."${value[0]}"='${value[1]}' `; + } + if(index != (where.length-1)) { + whereCase += ` AND ` + } + }) + } + + if (options.length > 0) { + options.forEach((value,index) => { + optionsCase = `${value[0]} ${value[1]} `; + }) + } + + if(isRoleCondition == 0) { + query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + INNER JOIN public."Users" U + ON CM."userId" = U."userId" ${whereCase} ${optionsCase}`; + } + else { + query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + INNER JOIN public."Users" U + ON CM."userId" = U."userId" + INNER JOIN public."UserRolesMapping" UR + ON UR."userId" = U."userId" + INNER JOIN public."Roles" R + ON R."roleId" = UR."roleId" ${whereCase} ${optionsCase}`; + } + let result = await this.usersRepository.query(query); + return result; + + } + + async validateEntity(repository, whereCondition, errorMessage) { + const validation = await repository.find({ where: whereCondition }); + if (validation.length == 0) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: errorMessage, }); } } @@ -320,8 +434,8 @@ export class PostgresCohortMembersService { } } + public async deleteCohortMemberById( - tenantId: string, cohortMembershipId: any, response: any, request: any @@ -331,7 +445,6 @@ export class PostgresCohortMembersService { try { const cohortMember = await this.cohortMembersRepository.find({ where: { - tenantId: tenantId, cohortMembershipId: cohortMembershipId, }, }); diff --git a/src/adapters/postgres/potsgres-module.ts b/src/adapters/postgres/potsgres-module.ts index 07a020da..352f2be4 100644 --- a/src/adapters/postgres/potsgres-module.ts +++ b/src/adapters/postgres/potsgres-module.ts @@ -14,6 +14,8 @@ import { PostgresFieldsService } from "./fields-adapter"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; +import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; +import { Role } from "src/rbac/role/entities/role.entity"; @Module({ @@ -27,7 +29,9 @@ import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; Fields, Cohort, UserTenantMapping, - Tenants + Tenants, + UserRoleMapping, + Role ]) ], providers: [ diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts index acd4c0ac..72b1f4ab 100644 --- a/src/adapters/postgres/rbac/assignrole-adapter.ts +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -112,6 +112,7 @@ export class PostgresAssignroleService { message: 'Please Enter Valid User ID', }); } + let result = await this.checkExistingRole(userId); if (!result) { return new SuccessResponse({ @@ -207,7 +208,6 @@ export class PostgresAssignroleService { async checkExistingRole(userId) { const result = await this.userRoleMappingRepository.findOne({ where: { userId }, - relations: ['user'] }) return result; } diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index dbfc5e01..06c01ac6 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -13,14 +13,16 @@ import { import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; import { Field } from '../../user/entities/field-entity'; -import APIResponse from '../../utils/response'; import { CohortMembers } from 'src/cohortMembers/entities/cohort-member.entity'; -import axios, { AxiosInstance, AxiosRequestConfig } from "axios" import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { isUUID } from 'class-validator'; import { UserSearchDto } from 'src/user/dto/user-search.dto'; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; +import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; +import { Cohort } from "src/cohort/entities/cohort.entity"; +import { Role } from "src/rbac/role/entities/role.entity"; +import { log } from 'console'; @Injectable() export class PostgresUserService { @@ -40,6 +42,12 @@ export class PostgresUserService { private userTenantMappingRepository: Repository, @InjectRepository(Tenants) private tenantsRepository: Repository, + @InjectRepository(UserRoleMapping) + private userRoleMappingRepository: Repository, + @InjectRepository(Cohort) + private cohortRepository: Repository, + @InjectRepository(Role) + private roleRepository: Repository, ) { } async searchUser(tenantId: string, request: any, @@ -106,27 +114,34 @@ export class PostgresUserService { }; let customFieldsArray = []; - const [filledValues, userDetails] = await Promise.all([ + const [filledValues, userDetails, userRole] = await Promise.all([ this.findFilledValues(userData.userId), - this.findUserDetails(userData.userId) + this.findUserDetails(userData.userId), + this.findUserRoles(userData.userId,userData.tenantId) ]); + + if(userRole){ + userDetails['role'] = userRole.title; + } + if (!userDetails) { return new SuccessResponse({ statusCode: HttpStatus.NOT_FOUND, message: 'User Not Found', }); - } + } if (!userData.fieldValue) { return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', data: userDetails, }); - } - const customFields = await this.findCustomFields(userData, userDetails.role) - - + } + const customFields = await this.findCustomFields(userData) + result.userData = userDetails; + console.log(); + const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { const fieldValue = filledValuesMap.get(data.fieldId); @@ -141,7 +156,11 @@ export class PostgresUserService { }; customFieldsArray.push(customField); } + + + result.userData['customFields'] = customFieldsArray; + return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -252,6 +271,26 @@ export class PostgresUserService { return result } + async findUserRoles(userId:string, tenantId:string) { + + const getRole = await this.userRoleMappingRepository.findOne({ + where:{ + userId:userId, + tenantId:tenantId + } + }) + + let role + + role = await this.roleRepository.findOne({ + where:{ + roleId:getRole.roleId, + }, + select: ["title"] + }) + return role + } + async findUserDetails(userId, username?: any) { let whereClause: any = { userId: userId }; if (username && userId === null) { @@ -260,7 +299,7 @@ export class PostgresUserService { } let userDetails = await this.usersRepository.findOne({ where: whereClause, - select: ["userId", "username", "name", "role", "district","state","mobile"] + select: ["userId", "username", "name", "district", "state", "mobile"] }) const tenentDetails = await this.allUsersTenent(userDetails.userId) @@ -269,7 +308,7 @@ export class PostgresUserService { return userDetails; } - async allUsersTenent(userId: string){ + async allUsersTenent(userId: string) { const query = ` SELECT T.name AS tenantName, T."tenantId", UTM."Id" AS userTenantMappingId FROM public."UserTenantMapping" UTM @@ -279,14 +318,13 @@ export class PostgresUserService { const result = await this.usersRepository.query(query, [userId]); return result; } - async findCustomFields(userData, role) { + async findCustomFields(userData) { let customFields = await this.fieldsRepository.find({ where: { context: userData.context, - contextType: role.toUpperCase() } }) - + return customFields; } async findFilledValues(userId: string) { @@ -296,7 +334,7 @@ export class PostgresUserService { LEFT JOIN public."Fields" F ON F."fieldId" = FV."fieldId" where U."userId" =$1`; - + let result = await this.usersRepository.query(query, [userId]); return result; } @@ -309,7 +347,7 @@ export class PostgresUserService { await this.updateBasicUserDetails(userDto.userId, userDto.userData); updatedData['basicDetails'] = userDto.userData; } - + if (userDto?.customFields?.length > 0) { const getFieldsAttributesQuery = ` @@ -319,8 +357,8 @@ export class PostgresUserService { `; const getFieldsAttributesParams = ['true']; const getFieldsAttributes = await this.fieldsRepository.query(getFieldsAttributesQuery, getFieldsAttributesParams); - - let isEditableFieldId = []; + + let isEditableFieldId = []; for (let fieldDetails of getFieldsAttributes) { isEditableFieldId.push(fieldDetails.fieldId); } @@ -328,14 +366,14 @@ export class PostgresUserService { // let errorMessage = []; let unEditableIdes = []; for (let data of userDto.customFields) { - if(isEditableFieldId.includes(data.fieldId)){ + if (isEditableFieldId.includes(data.fieldId)) { const result = await this.updateCustomFields(userDto.userId, data); if (result) { if (!updatedData['customFields']) updatedData['customFields'] = []; updatedData['customFields'].push(result); } - }else{ + } else { unEditableIdes.push(data.fieldId) } } @@ -347,7 +385,7 @@ export class PostgresUserService { statusCode: 200, message: "User has been updated successfully.", data: updatedData, - error:errorMessage + error: errorMessage }); } catch (e) { return new ErrorResponseTypeOrm({ @@ -385,8 +423,6 @@ export class PostgresUserService { // It is considered that if user is not present in keycloak it is not present in database as well try { const decoded: any = jwt_decode(request.headers.authorization); - let cohortId = userCreateDto.cohortId; - delete userCreateDto?.cohortId; userCreateDto.createdBy = decoded?.sub userCreateDto.updatedBy = decoded?.sub @@ -395,109 +431,123 @@ export class PostgresUserService { let field_value_array = userCreateDto.fieldValues.split("|"); const validateField = await this.validateFieldValues(field_value_array); - if(validateField == false){ + if (validateField == false) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.CONFLICT, errorMessage: "Duplicate fieldId found in fieldValues.", }); } } + + // check and validate all fields + let validateBodyFields = await this.validateBodyFields(userCreateDto) - // Check if tenant array is not empty - const tenantIds = userCreateDto.tenantId; - const userId = userCreateDto.userId; - let errors = []; + if (validateBodyFields == true) { + userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); + const userSchema = new UserCreateDto(userCreateDto); - if (!tenantIds || tenantIds.length === 0) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: "Tenants array cannot be empty.", - }); - } + let errKeycloak = ""; + let resKeycloak = ""; - //Check tenent is exist or not - for (const tenantId of tenantIds) { - const validate = await this.validateUserTenantMapping(userId, tenantId); - if (validate == false) { + const keycloakResponse = await getKeycloakAdminToken(); + const token = keycloakResponse.data.access_token; + let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) + let checkUserinDb = await this.checkUserinKeyCloakandDb(userCreateDto.username); + if (checkUserinKeyCloakandDb) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `Tenant ${tenantId} does not exist.`, + statusCode: HttpStatus.FORBIDDEN, + errorMessage: "User Already Exist", }); } + resKeycloak = await createUserInKeyCloak(userSchema, token).catch( + (error) => { + errKeycloak = error.response?.data.errorMessage; + + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + ); + userCreateDto.userId = resKeycloak; + + let result = await this.createUserInDatabase(request, userCreateDto); + + let fieldData = {}; + if (userCreateDto.fieldValues) { + let field_value_array = userCreateDto.fieldValues.split("|"); + if (result && field_value_array?.length > 0) { + let userId = result?.userId; + for (let i = 0; i < field_value_array?.length; i++) { + let fieldValues = field_value_array[i].split(":"); + fieldData = { + fieldId: fieldValues[0], + value: fieldValues[1] + } + let result = await this.updateCustomFields(userId, fieldData); + if (!result) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: `Error is ${result}`, + }); + } + } + } + } + return new SuccessResponse({ + statusCode: 200, + message: "User has been created successfully.", + data: result, + }); } + } catch (e) { + if (e instanceof ErrorResponseTypeOrm) { + return e; + } else { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e.toString(), // or any custom error message you want + }); + } + } + } - userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); - const userSchema = new UserCreateDto(userCreateDto); + async validateBodyFields(userCreateDto) { + for (const tenantCohortRoleMapping of userCreateDto.tenantCohortRoleMapping) { - let errKeycloak = ""; - let resKeycloak = ""; + const { tenantId, cohortId, roleId } = tenantCohortRoleMapping; - const keycloakResponse = await getKeycloakAdminToken(); - const token = keycloakResponse.data.access_token; - let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) - let checkUserinDb = await this.checkUserinKeyCloakandDb(userCreateDto.username); - if (checkUserinKeyCloakandDb) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.FORBIDDEN, - errorMessage: "User Already Exist", + const [tenantExists, cohortExists, roleExists] = await Promise.all([ + this.tenantsRepository.find({ where: { tenantId } }), + this.cohortRepository.find({ where: { tenantId, cohortId } }), + this.roleRepository.find({ where: { roleId } }) + ]); + + if (tenantExists.length === 0) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Tenant Id '${tenantId}' does not exist.`, }); } - resKeycloak = await createUserInKeyCloak(userSchema, token).catch( - (error) => { - errKeycloak = error.response?.data.errorMessage; - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); - } - ); - userCreateDto.userId = resKeycloak; - if (errors.length > 0) { - return { + if (cohortExists.length === 0) { + throw new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, - errorCount: errors.length, - errors, - }; + errorMessage: `Cohort Id '${cohortId}' does not exist for this tenant '${tenantId}'.`, + }); } - - let result = await this.createUserInDatabase(request, userCreateDto, cohortId); - - let fieldData = {}; - if (userCreateDto.fieldValues) { - let field_value_array = userCreateDto.fieldValues.split("|"); - if (result && field_value_array?.length > 0) { - let userId = result?.userId; - for (let i = 0; i < field_value_array?.length; i++) { - let fieldValues = field_value_array[i].split(":"); - fieldData = { - fieldId: fieldValues[0], - value: fieldValues[1] - } - let result = await this.updateCustomFields(userId, fieldData); - if (!result) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: `Error is ${result}`, - }); - } - } - } + if (roleExists.length === 0) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Role Id '${roleId}' does not exist.`, + }); } - return new SuccessResponse({ - statusCode: 200, - message: "ok", - data: result, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: `Error is ${e}`, - }); } + return true; } + // Can be Implemeneted after we know what are the unique entties async checkUserinKeyCloakandDb(userDto) { const keycloakResponse = await getKeycloakAdminToken(); @@ -512,60 +562,69 @@ export class PostgresUserService { return false; } - async createUserInDatabase(request: any, userCreateDto: UserCreateDto, cohortId) { + async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { const user = new User() user.username = userCreateDto?.username user.name = userCreateDto?.name user.email = userCreateDto?.email - user.role = userCreateDto?.role user.mobile = Number(userCreateDto?.mobile) || null, - user.tenantId = null user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, - user.state = userCreateDto?.state, - user.district = userCreateDto?.district, - user.address = userCreateDto?.address, - user.pincode = userCreateDto?.pincode + user.state = userCreateDto?.state, + user.district = userCreateDto?.district, + user.address = userCreateDto?.address, + user.pincode = userCreateDto?.pincode if (userCreateDto?.dob) { user.dob = new Date(userCreateDto.dob); } - + let result = await this.usersRepository.save(user); + if (result) { - let cohortData = { - userId: result?.userId, - role: result?.role, - tenantId: result?.tenantId, - cohortId: cohortId - } - await this.addCohortMember(cohortData); + for (let mapData of userCreateDto.tenantCohortRoleMapping) { + let cohortData = { + userId: result?.userId, + cohortId: mapData?.cohortId + } - let tenantsData = { - userId: result?.userId, - tenantIds: userCreateDto?.tenantId, + await this.addCohortMember(cohortData); + + let tenantRoleMappingData = { + userId: result?.userId, + tenantRoleMapping: mapData, + } + await this.assignUserToTenant(tenantRoleMappingData, request); } - await this.assignUserToTenant(tenantsData, request); } return result; } async assignUserToTenant(tenantsData, request) { try { - const tenantIds = tenantsData.tenantIds; - const userId = tenantsData.userId; - let result = []; - let errors = []; + const tenantId = tenantsData?.tenantRoleMapping?.tenantId; + const userId = tenantsData?.userId; + const roleId = tenantsData?.tenantRoleMapping?.roleId; - for (const tenantId of tenantIds) { - const data = await this.userTenantMappingRepository.save({ + if (roleId) { + const data = await this.userRoleMappingRepository.save({ userId: userId, tenantId: tenantId, + roleId: roleId, createdBy: request['user'].userId, updatedBy: request['user'].userId }) } + + const data = await this.userTenantMappingRepository.save({ + userId: userId, + tenantId: tenantId, + createdBy: request['user'].userId, + updatedBy: request['user'].userId + }) + + } catch (error) { throw new Error(error) } diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts index 23bd38fe..ca92ca50 100644 --- a/src/cohortMembers/cohortMember.service.ts +++ b/src/cohortMembers/cohortMember.service.ts @@ -32,7 +32,6 @@ export class CohortMembersService { try { const cohortMembers = await this.cohortMembersRepository.find({ where: { - tenantId: tenantId, cohortMembershipId: cohortMembershipId, }, }); @@ -258,7 +257,6 @@ export class CohortMembersService { try { const cohortMember = await this.cohortMembersRepository.find({ where: { - tenantId: tenantId, cohortMembershipId: cohortMembershipId, }, }); diff --git a/src/cohortMembers/dto/cohortMembers-search.dto.ts b/src/cohortMembers/dto/cohortMembers-search.dto.ts index f5f207de..58025188 100644 --- a/src/cohortMembers/dto/cohortMembers-search.dto.ts +++ b/src/cohortMembers/dto/cohortMembers-search.dto.ts @@ -16,7 +16,7 @@ export class CohortMembersSearchDto { @ApiProperty({ type: Object, description: "Filters", - example: { cohortId: "", userId: "" }, // Adding example for Swagger + example: { cohortId: "", userId: "", role:"" }, // Adding example for Swagger }) @ApiPropertyOptional() filters: { cohortId?: string; userId?: string }; // Define cohortId and userId properties diff --git a/src/cohortMembers/dto/cohortMembers.dto.ts b/src/cohortMembers/dto/cohortMembers.dto.ts index 266e7f92..9abe39ad 100644 --- a/src/cohortMembers/dto/cohortMembers.dto.ts +++ b/src/cohortMembers/dto/cohortMembers.dto.ts @@ -1,5 +1,6 @@ import { Exclude, Expose } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { IsNotEmpty, IsUUID } from "class-validator"; export class CohortMembersDto { //generated fields @@ -11,6 +12,10 @@ export class CohortMembersDto { createdAt: string; @Expose() updatedAt: string; + @Expose() + createdBy: string; + @Expose() + updatedBy: string; //cohortId @ApiProperty({ @@ -19,6 +24,8 @@ export class CohortMembersDto { default: "", }) @Expose() + @IsNotEmpty() + @IsUUID(undefined, { message: 'Cohort Id must be a valid UUID' }) cohortId: string; //userId @@ -28,35 +35,10 @@ export class CohortMembersDto { default: "", }) @Expose() + @IsNotEmpty() + @IsUUID(undefined, { message: 'User Id must be a valid UUID' }) userId: string; - //role - @ApiProperty({ - type: String, - description: "The role of the cohort members", - default: "", - }) - @Expose() - role: string; - - //createdBy - @ApiPropertyOptional({ - type: String, - description: "The createdBy of the cohort members", - default: "", - }) - @Expose() - createdBy: string; - - //updatedBy - @ApiPropertyOptional({ - type: String, - description: "The updatedBy of the cohort members", - default: "", - }) - @Expose() - updatedBy: string; - constructor(obj: any) { Object.assign(this, obj); } diff --git a/src/cohortMembers/entities/cohort-member.entity.ts b/src/cohortMembers/entities/cohort-member.entity.ts index 7e2006e9..d3ba1759 100644 --- a/src/cohortMembers/entities/cohort-member.entity.ts +++ b/src/cohortMembers/entities/cohort-member.entity.ts @@ -13,12 +13,6 @@ export class CohortMembers { @PrimaryGeneratedColumn("uuid") cohortMembershipId: string; - @Column({ type: "varchar", length: 255 }) - role: string; - - @Column({ type: "uuid" }) - tenantId: string; - @Column({ type: "uuid", nullable: true }) cohortId: string | null; diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index 7f440440..80cd1904 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -38,14 +38,14 @@ export class AssignRoleController { return response.status(result.statusCode).json(result); } - @Get("/:id") + @Get("/:userId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Role Detail." }) @ApiHeader({ name: "tenantid" }) @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({strategy: "excludeAll",}) public async getRole( - @Param("id") userId: string, + @Param("userId") userId: string, @Req() request: Request, @Res() response: Response ) { diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index d1c83172..5bb98199 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -1,4 +1,4 @@ -import {Expose } from "class-transformer"; +import {Expose, Type } from "class-transformer"; import { MaxLength, IsNotEmpty, @@ -7,10 +7,41 @@ import { IsNumber, IsArray, IsUUID, + ValidateNested, + IsOptional, } from "class-validator"; import { User } from "../entities/user-entity"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +export class tenantRoleMappingDto{ + @ApiProperty({ + type: String, + description: "Tenant Id", + }) + @Expose() + @IsUUID(undefined, { message: 'Tenant Id must be a valid UUID' }) + @IsNotEmpty() + tenantId: string; + + @ApiPropertyOptional({ + type: String, + description: "The cohort id of the user", + }) + @Expose() + @IsUUID(undefined, { message: 'Cohort Id must be a valid UUID' }) + @IsNotEmpty() + cohortId: string; + + @ApiPropertyOptional({ + type: String, + description: "User Role", + }) + @IsOptional() + @Expose() + @IsUUID(undefined, { message: 'Role Id must be a valid UUID' }) + roleId: string; +} + export class UserCreateDto { @Expose() @@ -21,22 +52,10 @@ export class UserCreateDto { @IsNotEmpty() username: string; - // @ApiProperty({ - // type: String, - // description: "The name of the user", - // }) @ApiProperty({ type: () => String }) @Expose() name: string; - @ApiProperty({ - type: String, - description: "The role of the user", - }) - @Expose() - @IsNotEmpty() - role: string; - @ApiPropertyOptional({ type: String, description: "The date of Birth of the user", @@ -108,14 +127,6 @@ export class UserCreateDto { @Expose() updatedBy: string; - @ApiPropertyOptional({ - type: String, - description: "The cohort id of the user", - }) - @Expose() - @IsNotEmpty() - cohortId: string; - //fieldValues @ApiProperty({ type: String, @@ -125,17 +136,17 @@ export class UserCreateDto { fieldValues: string; @ApiProperty({ - type: String, - description: "Tenant Id", - default: [], + type: [tenantRoleMappingDto], + description: 'List of user attendance details', }) - @Expose() - @IsArray() - @IsUUID(undefined, { each: true }) - @IsNotEmpty({ each: true }) - tenantId: string; + @ValidateNested({ each: true }) + @Type(() => tenantRoleMappingDto) + tenantCohortRoleMapping: tenantRoleMappingDto[]; constructor(partial: Partial) { Object.assign(this, partial); } } + + + diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts index aea16248..1f108b1b 100644 --- a/src/user/entities/user-entity.ts +++ b/src/user/entities/user-entity.ts @@ -12,9 +12,6 @@ export class User { @Column() name: string; - @Column() - role: string; - @Column({ type: "date", nullable: true }) dob: Date; @@ -48,9 +45,6 @@ export class User { @Column({ nullable: true }) updatedBy: string; - @Column({ type: "uuid" }) - tenantId: string; - @Column({ default: "active" }) status: string; userRoleMappings: User; diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index be296bb5..60049873 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -64,15 +64,20 @@ export class UserController { @Param("userId") userId: string, @Query("fieldvalue") fieldvalue: string | null = null ) { - // const tenantId = headers["tenantid"]; Can be Used In future + const tenantId = headers["tenantid"]; + if(!tenantId){ + return response.status(400).json({ "statusCode": 400, error: "Please provide a tenantId." }); + } // Context and ContextType can be taken from .env later let userData = { context: "USERS", + tenantId: tenantId, userId: userId, fieldValue: fieldvalue } let result; result = await this.userAdapter.buildUserAdapter().getUsersDetailsById(userData, response); + return response.status(result.statusCode).json(result); } @@ -92,6 +97,7 @@ export class UserController { @Body() userCreateDto: UserCreateDto, @Res() response: Response ) { + // console.log(userCreateDto); const result = await this.userAdapter.buildUserAdapter().createUser(request, userCreateDto); return response.status(result.statusCode).json(result); } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 03d83d8c..8d38a697 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -11,10 +11,14 @@ import { Field } from "./entities/field-entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; +import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; +import { Cohort } from "src/cohort/entities/cohort.entity"; +import { Role } from "src/rbac/role/entities/role.entity"; + @Module({ imports: [ - TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers,UserTenantMapping,Tenants]), + TypeOrmModule.forFeature([User, FieldValues, Field, CohortMembers,UserTenantMapping,Tenants,UserRoleMapping,Cohort,Role]), HttpModule, HasuraModule, PostgresModule, From cfebee91297a883ebb1503b5da738b2a0b7886a3 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 14 May 2024 17:04:49 +0530 Subject: [PATCH 327/408] remove commented code --- src/adapters/hasura/cohortMembers.adapter.ts | 58 ------------------- src/adapters/postgres/user-adapter.ts | 2 - .../dto/cohortMembers-search.dto.ts | 2 +- src/user/user.controller.ts | 1 - 4 files changed, 1 insertion(+), 62 deletions(-) diff --git a/src/adapters/hasura/cohortMembers.adapter.ts b/src/adapters/hasura/cohortMembers.adapter.ts index 4b388c8c..bc38c2d9 100644 --- a/src/adapters/hasura/cohortMembers.adapter.ts +++ b/src/adapters/hasura/cohortMembers.adapter.ts @@ -83,64 +83,6 @@ export class HasuraCohortMembersService cohortMembersUpdateDto: CohortMembersUpdateDto, response: any ) { - // var axios = require("axios"); - - // let query = ""; - // Object.keys(cohortMembersDto).forEach((e) => { - // if (cohortMembersDto[e] && cohortMembersDto[e] != "") { - // if (Array.isArray(cohortMembersDto[e])) { - // query += `${e}: "${JSON.stringify(cohortMembersDto[e])}", `; - // } else { - // query += `${e}: "${cohortMembersDto[e]}", `; - // } - // } - // }); - - // var data = { - // query: ` - // mutation UpdateCohortMembers($cohortMembershipId:uuid!) { - // update_CohortMembers_by_pk( - // pk_columns: { - // cohortMembershipId: $cohortMembershipId - // }, - // _set: { - // ${query} - // } - // ) { - // cohortMembershipId - // } - // } - // `, - // variables: { - // cohortMembershipId: cohortMembershipId, - // }, - // }; - - // var config = { - // method: "post", - // url: process.env.REGISTRYHASURA, - // headers: { - // "x-hasura-admin-secret": process.env.REGISTRYHASURAADMINSECRET, - // "Content-Type": "application/json", - // }, - // data: data, - // }; - - // const response = await axios(config); - - // if (response?.data?.errors) { - // return new ErrorResponse({ - // errorCode: response?.data?.errors[0]?.extensions?.code, - // errorMessage: response?.data?.errors[0]?.message, - // }); - // } else { - // let result = response.data.data; - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } } public async mappedResponse(result: any) { diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 06c01ac6..b4130911 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -22,7 +22,6 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; -import { log } from 'console'; @Injectable() export class PostgresUserService { @@ -140,7 +139,6 @@ export class PostgresUserService { const customFields = await this.findCustomFields(userData) result.userData = userDetails; - console.log(); const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { diff --git a/src/cohortMembers/dto/cohortMembers-search.dto.ts b/src/cohortMembers/dto/cohortMembers-search.dto.ts index 58025188..bf6250af 100644 --- a/src/cohortMembers/dto/cohortMembers-search.dto.ts +++ b/src/cohortMembers/dto/cohortMembers-search.dto.ts @@ -19,7 +19,7 @@ export class CohortMembersSearchDto { example: { cohortId: "", userId: "", role:"" }, // Adding example for Swagger }) @ApiPropertyOptional() - filters: { cohortId?: string; userId?: string }; // Define cohortId and userId properties + filters: { cohortId?: string; userId?: string; role?: string }; // Define cohortId and userId properties constructor(partial: Partial) { Object.assign(this, partial); diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 60049873..3d1acf11 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -97,7 +97,6 @@ export class UserController { @Body() userCreateDto: UserCreateDto, @Res() response: Response ) { - // console.log(userCreateDto); const result = await this.userAdapter.buildUserAdapter().createUser(request, userCreateDto); return response.status(result.statusCode).json(result); } From 295de9c61578cd51a5887775741dbc8d012713a0 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 15 May 2024 16:21:52 +0530 Subject: [PATCH 328/408] Task:PS-408 Attendance:Added sort functionality to data from attendance/list API --- src/adapters/postgres/attendance-adapter.ts | 172 +++++++++++++----- src/attendance/dto/attendance-search.dto.ts | 190 +++++++++++--------- 2 files changed, 236 insertions(+), 126 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 054f3028..71be8c8a 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -35,7 +35,7 @@ export class PostgresAttendanceService { async searchAttendance(tenantId: string, request: any, attendanceSearchDto: AttendanceSearchDto) { try { - let { limit, page, filters, facets } = attendanceSearchDto; + let { limit, page, filters, facets, sort } = attendanceSearchDto; // Set default limit to 0 if not provided if (!limit) { limit = 20; @@ -59,21 +59,17 @@ export class PostgresAttendanceService { if (key === "attendanceDate") { // For attendanceDate, consider NULL values as well whereClause[key] = In([value, null]); + } else { + whereClause[key] = value; } - whereClause[key] = value; - } - - else if (filters.fromDate && filters.toDate) { - - + } else if (key === 'fromDate' && filters.toDate) { // Convert fromDate and toDate strings to Date objects - const fromDate = new Date(filters.fromDate); + const fromDate = new Date(value); const toDate = new Date(filters.toDate); // Construct the whereClause with the date range using Between whereClause["attendanceDate"] = Between(fromDate, toDate); - } - else { + } else { // If filter key is invalid, return a BadRequest response return new ErrorResponseTypeOrm({ statusCode: HttpStatus.BAD_REQUEST, @@ -81,17 +77,44 @@ export class PostgresAttendanceService { }); } } - } - // Fetch data from the database - const attendanceList = await this.attendanceRepository.find({ - where: whereClause - }); + let attendanceList; + + if (!facets) { + let orderOption: any = {}; + if (sort && Array.isArray(sort) && sort.length === 2) { + const [column, order] = sort; + if (attendanceKeys.includes(column)) { + orderOption[column] = order.toUpperCase();; + } else { + // If sort key is invalid, return a BadRequest response + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `${column} Invalid sort key`, + }); + } + } - const paginatedAttendanceList = attendanceList.slice(offset, offset + (limit)); + attendanceList = await this.attendanceRepository.find({ + where: whereClause, + order: orderOption, // Apply sorting option + }); + const paginatedAttendanceList = attendanceList.slice(offset, offset + (limit)); + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: 'Ok.', + data: { + attendanceList: paginatedAttendanceList + }, + }); + } if (facets && facets.length > 0) { + attendanceList = await this.attendanceRepository.find({ + where: whereClause // Apply sorting option + }); + let facetFields = []; // Check for invalid facets for (const facet of facets) { @@ -105,22 +128,18 @@ export class PostgresAttendanceService { facetFields.push({ name: facet, field: facet }); } - - - - // Process the data to calculate counts based on facets - const tree = await this.facetedSearch({ data: attendanceList, facets: facetFields }); - let result = {}; // Process the data to calculate counts based on facets for (const facet of facetFields) { const { field } = facet; - const tree = await this.facetedSearch({ data: attendanceList, facets: [facet] }); + const tree = await this.facetedSearch({ data: attendanceList, facets: [facet], sort }); + + if (tree instanceof ErrorResponseTypeOrm) { + return tree + } result[field] = tree[field]; } - - // Return success response with counts return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -130,18 +149,7 @@ export class PostgresAttendanceService { }, }); } - else { - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: { - attendanceList: paginatedAttendanceList - }, - }); - - } } catch (error) { if (error.code === "22P02") { // Handle invalid input value error @@ -159,8 +167,18 @@ export class PostgresAttendanceService { } - async facetedSearch({ data, facets }) { - const tree = []; + async facetedSearch({ data, facets, sort }) { + const tree = {}; + const attendanceKeys = new Set(); + + // Populate attendanceKeys with distinct attendance values + data.forEach(item => { + const attendanceValue = item.attendance; + if (attendanceValue) { + attendanceKeys.add(attendanceValue); + } + }); + // Iterate over facets for (const facet of facets) { const { field } = facet; @@ -186,8 +204,7 @@ export class PostgresAttendanceService { } } - // Calculate percentage for each contextId - // Calculate percentage for each contextId + // Calculate percentage for each value for (const value in tree[field]) { const counts = tree[field][value]; const totalCount = Object.values(counts).reduce((acc: number, curr: unknown) => acc + (curr as number), 0); @@ -195,15 +212,87 @@ export class PostgresAttendanceService { for (const key in counts) { const count = counts[key]; const percentage = (count / Number(totalCount)) * 100; // Convert totalCount to a number - // counts[key + "_count"] = count; counts[key + "_percentage"] = percentage.toFixed(2); // Round percentage to two decimal places } } + // Assign default values for sorting + for (const value in tree[field]) { + for (const attendanceValue of attendanceKeys) { + const percentageKey = `${attendanceValue}_percentage`; + if (!tree[field][value].hasOwnProperty(percentageKey)) { + tree[field][value][percentageKey] = "0.00"; // Set default value internally + } + } + } + + // Validate sort keys + if (sort) { + const [sortField, sortOrder] = sort; + if (!attendanceKeys.has(sortField.replace("_percentage", "")) && sortField !== 'present_percentage' && sortField !== 'absent_percentage') { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Invalid sort[0]: ${sortField}`, + }); + } + + // Sort the tree based on the provided sort parameter + tree[field] = await this.sortTree(tree[field], sortField, sortOrder); + } + } + + // Remove default values from the response + for (const field in tree) { + for (const value in tree[field]) { + for (const attendanceValue of attendanceKeys) { + const percentageKey = `${attendanceValue}_percentage`; + if (tree[field][value][percentageKey] === "0.00") { + delete tree[field][value][percentageKey]; // Remove default value from response + } + } + } } + return tree; } + // Helper function to sort the tree based on the provided sortField and sortOrder + async sortTree(tree, sortField, sortOrder) { + const sortedTree = {}; + + // Convert the object keys (values of the sortField) into an array + const keys = Object.keys(tree); + + // Sort the keys based on the sortField and sortOrder + keys.sort((a, b) => { + const valueA = parseFloat(tree[a][sortField] || "0.00"); // Convert string to float + const valueB = parseFloat(tree[b][sortField] || "0.00"); // Convert string to float + + if (sortOrder === 'asc') { + return valueA - valueB; + } else { + return valueB - valueA; + } + }); + + // Populate the sortedTree with sorted data + keys.forEach(key => { + sortedTree[key] = tree[key]; + }); + + return sortedTree; + } + + + + + + + + + + + async attendanceReport(attendanceStatsDto: AttendanceStatsDto) { @@ -444,7 +533,6 @@ export class PostgresAttendanceService { try { const Isvalid = await this.validateUserForCohort(attendanceDto.userId, attendanceDto.contextId) - if (!Isvalid) { return new ErrorResponseTypeOrm({ diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index 2fc18850..46be7c00 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -1,13 +1,13 @@ - import { ApiAcceptedResponse, ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; - import { IsArray, IsNotEmpty, IsNumber, IsOptional, IsString, IsUUID, Matches, Validate, ValidateIf, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface, isNotEmpty } from "class-validator"; - import { isBefore, isSameDay } from "date-fns"; - import { UserDto } from "src/user/dto/user.dto"; - import { AttendanceDto } from "./attendance.dto"; - import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; - import { Type } from "class-transformer"; +import { ApiAcceptedResponse, ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { ArrayMaxSize, ArrayMinSize, IsArray, IsEnum, IsNotEmpty, IsNumber, IsOptional, IsString, IsUUID, Matches, Validate, ValidateIf, ValidateNested, ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface, isNotEmpty } from "class-validator"; +import { isBefore, isSameDay } from "date-fns"; +import { UserDto } from "src/user/dto/user.dto"; +import { AttendanceDto } from "./attendance.dto"; +import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; +import { Type } from "class-transformer"; - @ValidatorConstraint({ name: 'isNotAfterFromDate', async: false }) +@ValidatorConstraint({ name: 'isNotAfterFromDate', async: false }) export class IsFromDateBeforeToDateConstraint implements ValidatorConstraintInterface { validate(fromDate: Date, args: ValidationArguments) { const toDate = args.object[args.constraints[0]]; @@ -20,102 +20,124 @@ export class IsFromDateBeforeToDateConstraint implements ValidatorConstraintInte } } - export class AttendanceFiltersDto { - @ApiPropertyOptional({default:"yyyy-mm-dd"}) - @IsOptional() - @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) - @Validate(IsFromDateBeforeToDateConstraint, ['toDate']) - fromDate?: Date; - @ApiPropertyOptional({default:"yyyy-mm-dd"}) - @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) - @IsOptional() - toDate?: Date; +enum SortDirection { + ASC = 'asc', + DESC = 'desc', +} - @ApiPropertyOptional() - @IsUUID() - @IsOptional() - contextId ?:string +export class AttendanceFiltersDto { + @ApiPropertyOptional({ default: "yyyy-mm-dd" }) + @IsOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @Validate(IsFromDateBeforeToDateConstraint, ['toDate']) + fromDate?: Date; - @ApiPropertyOptional() - scope ?: string + @ApiPropertyOptional({ default: "yyyy-mm-dd" }) + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + @IsOptional() + toDate?: Date; - @ApiPropertyOptional({ - type: String, - description: "The date of the attendance in format yyyy-mm-dd", - default:"yyyy-mm-dd" - }) - @IsOptional() - @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) - attendanceDate ?:Date + @ApiPropertyOptional() + @IsUUID() + @IsOptional() + contextId?: string + @ApiPropertyOptional() + scope?: string - @ApiPropertyOptional() - @IsUUID() - @IsOptional() - userId?: string + @ApiPropertyOptional({ + type: String, + description: "The date of the attendance in format yyyy-mm-dd", + default: "yyyy-mm-dd" + }) + @IsOptional() + @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Please provide a valid date in the format yyyy-mm-dd' }) + attendanceDate?: Date - // @ApiPropertyOptional() + @ApiPropertyOptional() + @IsUUID() + @IsOptional() + userId?: string - [key: string]: any; // Allows additional dynamic keys - } + // @ApiPropertyOptional() - @ValidatorConstraint({ name: "validDateRange", async: false }) - export class ValidDateRangeConstraint implements ValidatorConstraintInterface { - validate(value: any, args: ValidationArguments) { - const { toDate, fromDate } = value; - // If either fromDate or toDate is not provided, validation passes - if (!fromDate || !toDate) { - return true; - } + [key: string]: any; // Allows additional dynamic keys +} - return isBefore(new Date(fromDate), new Date(toDate)) || isSameDay(new Date(fromDate), new Date(toDate)); - } +@ValidatorConstraint({ name: "validDateRange", async: false }) +export class ValidDateRangeConstraint implements ValidatorConstraintInterface { + validate(value: any, args: ValidationArguments) { + const { toDate, fromDate } = value; - defaultMessage(args: ValidationArguments) { - return "Invalid date range. 'toDate' must be after or equal to 'fromDate'."; + // If either fromDate or toDate is not provided, validation passes + if (!fromDate || !toDate) { + return true; } - } - - - export class AttendanceSearchDto { - @ApiPropertyOptional({ - type: Number, - description: "Limit", - }) - @IsOptional() - @IsNotEmpty() - @IsNumber({}, { message: 'Limit must be a number' }) - limit: number; + return isBefore(new Date(fromDate), new Date(toDate)) || isSameDay(new Date(fromDate), new Date(toDate)); + } - @ApiProperty({ - type: Number, - description: "number", - }) - page: number; + defaultMessage(args: ValidationArguments) { + return "Invalid date range. 'toDate' must be after or equal to 'fromDate'."; + } +} - @ApiPropertyOptional({ - type: AttendanceFiltersDto, - description: "Filters", - }) - @ValidateNested({ each: true }) - @Type(() => AttendanceFiltersDto) - // @Validate(ValidDateRangeConstraint, { message: "Invalid date range." }) - filters: AttendanceFiltersDto - @ApiPropertyOptional({ - description: "Facets", - example: [ "contextId","userId","scope"] - }) - facets?: string[]; +export class AttendanceSearchDto { + @ApiPropertyOptional({ + type: Number, + description: "Limit", + }) + @IsOptional() + @IsNotEmpty() + @IsNumber({}, { message: 'Limit must be a number' }) + limit: number; + + @ApiProperty({ + type: Number, + description: "number", + }) + page: number; + + @ApiPropertyOptional({ + type: AttendanceFiltersDto, + description: "Filters", + }) + @ValidateNested({ each: true }) + @Type(() => AttendanceFiltersDto) + // @Validate(ValidDateRangeConstraint, { message: "Invalid date range." }) + filters: AttendanceFiltersDto + + + @ApiPropertyOptional({ + description: "Facets", + example: ["contextId", "userId", "scope"] + }) + facets?: string[]; + + @ApiPropertyOptional({ + description: "Sort", + example: ["attendanceDate", "ascending"] + }) + @IsArray() + @IsOptional() + @ArrayMinSize(2, { message: 'Sort array must contain exactly two elements' }) + @ArrayMaxSize(2, { message: 'Sort array must contain exactly two elements' }) + sort: [string, string]; + + @ValidateIf((o) => o.sort !== undefined) + @IsEnum(SortDirection, { each: true, message: 'Sort[1] must be either asc or desc' }) + get sortDirection(): string | undefined { + return this.sort ? this.sort[1] : undefined; + } - constructor(partial: Partial) { - Object.assign(this, partial); - } + constructor(partial: Partial) { + Object.assign(this, partial); } +} From db8406dcbcaca0cc330cb393a6f453aa3f23f33c Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 15 May 2024 17:17:24 +0530 Subject: [PATCH 329/408] Task PS-378 FieldValues: Support to store multiple selected values from frontend --- src/adapters/hasura/user.adapter.ts | 154 +++++++++++++------------- src/adapters/postgres/user-adapter.ts | 31 +++--- src/user/dto/user-create.dto.ts | 32 +++++- src/user/user.controller.ts | 2 +- 4 files changed, 123 insertions(+), 96 deletions(-) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 63f17a0e..ad77d4d1 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -314,47 +314,47 @@ export class HasuraUserService implements IServicelocator { errorMessage: response.data.errors[0].message, }); } else { - const result = response.data.data.insert_Users_one; - - let fieldCreate = true; - let fieldError = null; - //create fields values - let userId = result?.userId; - let field_value_array = userCreateDto.fieldValues?.split("|"); - - if (field_value_array?.length > 0) { - let field_values = []; - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - field_values.push({ - value: fieldValues[1] ? fieldValues[1] : "", - itemId: userId, - fieldId: fieldValues[0] ? fieldValues[0] : "", - createdBy: userCreateDto?.createdBy, - updatedBy: userCreateDto?.updatedBy, - }); - } - - const response_field_values = - await this.fieldsService.createFieldValuesBulk(field_values); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError = response_field_values?.data; - } - } - - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "Ok.", - data: result, - }); - } else { - return new ErrorResponse({ - errorCode: fieldError?.errors[0]?.extensions?.code, - errorMessage: fieldError?.errors[0]?.message, - }); - } + // const result = response.data.data.insert_Users_one; + + // let fieldCreate = true; + // let fieldError = null; + // //create fields values + // let userId = result?.userId; + // let field_value_array = userCreateDto.fieldValues?.split("|"); + + // if (field_value_array?.length > 0) { + // let field_values = []; + // for (let i = 0; i < field_value_array.length; i++) { + // let fieldValues = field_value_array[i].split(":"); + // field_values.push({ + // value: fieldValues[1] ? fieldValues[1] : "", + // itemId: userId, + // fieldId: fieldValues[0] ? fieldValues[0] : "", + // createdBy: userCreateDto?.createdBy, + // updatedBy: userCreateDto?.updatedBy, + // }); + // } + + // const response_field_values = + // await this.fieldsService.createFieldValuesBulk(field_values); + // if (response_field_values?.data?.errors) { + // fieldCreate = false; + // fieldError = response_field_values?.data; + // } + // } + + // if (fieldCreate) { + // return new SuccessResponse({ + // statusCode: 200, + // message: "Ok.", + // data: result, + // }); + // } else { + // return new ErrorResponse({ + // errorCode: fieldError?.errors[0]?.extensions?.code, + // errorMessage: fieldError?.errors[0]?.message, + // }); + // } } }catch (e) { console.error(e); @@ -421,42 +421,42 @@ export class HasuraUserService implements IServicelocator { errorMessage: response?.data?.errors[0]?.message, }); } else { - let result = response.data.update_Users_by_pk; - let fieldCreate = true; - let fieldError = []; - //update fields values - let field_value_array = userUpdateDto.fieldValues?.split("|"); - if (field_value_array?.length > 0) { - for (let i = 0; i < field_value_array.length; i++) { - let fieldValues = field_value_array[i].split(":"); - //update values - let fieldValuesUpdate = new FieldValuesDto({ - value: fieldValues[1] ? fieldValues[1] : "", - }); - - const response_field_values = - await this.fieldsService.updateFieldValues( - fieldValues[0] ? fieldValues[0] : "", - fieldValuesUpdate - ); - if (response_field_values?.data?.errors) { - fieldCreate = false; - fieldError.push(response_field_values?.data); - } - } - } - if (fieldCreate) { - return new SuccessResponse({ - statusCode: 200, - message: "User updated successfully ", - data: result, - }); - } else { - return new ErrorResponse({ - errorCode: "filed value update error", - errorMessage: JSON.stringify(fieldError), - }); - } + // let result = response.data.update_Users_by_pk; + // let fieldCreate = true; + // let fieldError = []; + // //update fields values + // let field_value_array = userUpdateDto.fieldValues?.split("|"); + // if (field_value_array?.length > 0) { + // for (let i = 0; i < field_value_array.length; i++) { + // let fieldValues = field_value_array[i].split(":"); + // //update values + // let fieldValuesUpdate = new FieldValuesDto({ + // value: fieldValues[1] ? fieldValues[1] : "", + // }); + + // const response_field_values = + // await this.fieldsService.updateFieldValues( + // fieldValues[0] ? fieldValues[0] : "", + // fieldValuesUpdate + // ); + // if (response_field_values?.data?.errors) { + // fieldCreate = false; + // fieldError.push(response_field_values?.data); + // } + // } + // } + // if (fieldCreate) { + // return new SuccessResponse({ + // statusCode: 200, + // message: "User updated successfully ", + // data: result, + // }); + // } else { + // return new ErrorResponse({ + // errorCode: "filed value update error", + // errorMessage: JSON.stringify(fieldError), + // }); + // } } } diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index b4130911..62a72ffd 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -426,9 +426,9 @@ export class PostgresUserService { //Check duplicate field entry if (userCreateDto.fieldValues) { - let field_value_array = userCreateDto.fieldValues.split("|"); - const validateField = await this.validateFieldValues(field_value_array); - + let field_values = userCreateDto.fieldValues; + const validateField = await this.validateFieldValues(field_values); + if (validateField == false) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.CONFLICT, @@ -436,6 +436,7 @@ export class PostgresUserService { }); } } + // check and validate all fields let validateBodyFields = await this.validateBodyFields(userCreateDto) @@ -473,14 +474,14 @@ export class PostgresUserService { let fieldData = {}; if (userCreateDto.fieldValues) { - let field_value_array = userCreateDto.fieldValues.split("|"); - if (result && field_value_array?.length > 0) { + + if (result && userCreateDto.fieldValues?.length > 0) { let userId = result?.userId; - for (let i = 0; i < field_value_array?.length; i++) { - let fieldValues = field_value_array[i].split(":"); + for (let fieldValues of userCreateDto.fieldValues) { + fieldData = { - fieldId: fieldValues[0], - value: fieldValues[1] + fieldId: fieldValues['fieldId'], + value: fieldValues['value'] } let result = await this.updateCustomFields(userId, fieldData); if (!result) { @@ -492,6 +493,7 @@ export class PostgresUserService { } } } + return new SuccessResponse({ statusCode: 200, message: "User has been created successfully.", @@ -762,16 +764,17 @@ export class PostgresUserService { } } - public async validateFieldValues(field_value_array: string[]) { - let encounteredKeys = [] - for (const fieldValue of field_value_array) { - const [fieldId] = fieldValue.split(":").map(value => value.trim()); + public async validateFieldValues(field_values) { + + let encounteredKeys = [] + for (const fieldValue of field_values) { + const fieldId = fieldValue['fieldId']; + // const [fieldId] = fieldValue.split(":").map(value => value.trim()); if (encounteredKeys.includes(fieldId)) { return false } encounteredKeys.push(fieldId); - }; } diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 5bb98199..917dc08b 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -42,8 +42,31 @@ export class tenantRoleMappingDto{ roleId: string; } -export class UserCreateDto { +export class fieldValuesDto{ + @ApiPropertyOptional({ + type: String, + description: "Field Id", + }) + @Expose() + @IsUUID(undefined, { message: 'Field Id must be a valid UUID' }) + fieldId: string; + + // @ApiPropertyOptional({ + // type: String, + // description: "Field type", + // }) + // @Expose() + // fieldType: string; + + @ApiPropertyOptional({ + type: String, + description: "Field values", + }) + @Expose() + value: string; +} +export class UserCreateDto { @Expose() userId: string; @@ -129,11 +152,12 @@ export class UserCreateDto { //fieldValues @ApiProperty({ - type: String, + type: [fieldValuesDto], description: "The fieldValues Object", }) - @Expose() - fieldValues: string; + @ValidateNested({ each: true }) + @Type(() => fieldValuesDto) + fieldValues: fieldValuesDto[]; @ApiProperty({ type: [tenantRoleMappingDto], diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 3d1acf11..a8d992ad 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -41,7 +41,7 @@ import { Response } from "express"; import { isUUID } from "class-validator"; import { SuccessResponse } from "src/success-response"; @ApiTags("User") -@UseGuards(JwtAuthGuard) +// @UseGuards(JwtAuthGuard) @Controller("users") export class UserController { constructor( From 07b65dcef4f3912123337b6643ae98ff63f8154a Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 15 May 2024 17:18:45 +0530 Subject: [PATCH 330/408] Task PS-408Attendance: Chore [Fixed "toDate" and "fromDate" filter] --- src/adapters/postgres/attendance-adapter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/postgres/attendance-adapter.ts b/src/adapters/postgres/attendance-adapter.ts index 71be8c8a..7d246fcd 100644 --- a/src/adapters/postgres/attendance-adapter.ts +++ b/src/adapters/postgres/attendance-adapter.ts @@ -62,9 +62,9 @@ export class PostgresAttendanceService { } else { whereClause[key] = value; } - } else if (key === 'fromDate' && filters.toDate) { + } else if (filters.fromDate && filters.toDate) { // Convert fromDate and toDate strings to Date objects - const fromDate = new Date(value); + const fromDate = new Date(filters.fromDate); const toDate = new Date(filters.toDate); // Construct the whereClause with the date range using Between From 3291ed1a6e105fdd552d8fbc3306d57e8bfe1565 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 15 May 2024 17:22:00 +0530 Subject: [PATCH 331/408] add --- src/adapters/hasura/user.adapter.ts | 235 ---------------------------- src/user/dto/user-create.dto.ts | 7 - 2 files changed, 242 deletions(-) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index ad77d4d1..1c626c07 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -31,117 +31,6 @@ export class HasuraUserService implements IServicelocator { } public async getUsersDetailsById(userData: Record, response:any) {} public async getUsersDetailsByCohortId(userData: Record, response:any) {} - // public async getUser( - // userData?:Record, - // res?: any, - // tenantId?: string, - // userId?: string, - // accessRole?: string, - // request?: any, - // ) { - // try { - // const decoded: any = jwt_decode(request.headers.authorization); - // const userRoles = - // decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; - - // const data = { - // query: `query GetUser($userId: uuid!, $tenantId: uuid!, $context: String!, $contextId: uuid!, $access : String!) { - // Users(where: {tenantId: {_eq: $tenantId}, userId: {_eq: $userId}}) { - // username - // userId - // name - // email - // district - // state - // address - // pincode - // mobile - // dob - // role - // tenantId - // updatedAt - // updatedBy - // createdBy - // createdAt - // fields: UsersFieldsTenants(where: {_or: [{contextId: {_is_null: true}}, {contextId: {_eq: $contextId}}], context: {_eq: $context}, _and: {_or: [{access: {_is_null: true}}, {access: {_eq: $access}}]}}) { - // tenantId - // fieldId - // assetId - // context - // contextId - // groupId - // name - // label - // defaultValue - // type - // note - // description - // state - // required - // ordering - // metadata - // access - // onlyUseInSubform - // updatedAt - // updatedBy - // createdAt - // createdBy - // fieldValues: FieldValues(where: {itemId: {_eq: $contextId}}) { - // value - // itemId - // fieldId - // fieldValuesId - // updatedBy - // updatedAt - // createdBy - // createdAt - // } - // } - // } - // }`, - // variables: { - // userId: userId, - // tenantId: tenantId, - // context: "Users", - // contextId: userId, - // access: accessRole, - // }, - // }; - - // const config = { - // method: "post", - // url: process.env.REGISTRYHASURA, - // headers: { - // Authorization: request.headers.authorization, - // "x-hasura-role": getUserRole(userRoles), - // "Content-Type": "application/json", - // }, - // data: data, - // }; - - // const response = await this.axios(config); - - // if (response?.data?.errors) { - // return res.status(400).send({ - // errorCode: response?.data?.errors[0]?.extensions?.code, - // errorMessage: response?.data?.errors[0]?.message, - // }); - // } else { - // const result = response.data.data.Users; - // return res.status(200).send({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } - // } catch (e) { - // console.error(e); - // return new ErrorResponse({ - // errorCode: "400", - // errorMessage: e, - // }); - // } - // } public async checkAndAddUser(request: any, userDto: UserCreateDto) { // try { @@ -217,53 +106,6 @@ export class HasuraUserService implements IServicelocator { } public async createUser(request: any, userCreateDto: UserCreateDto) { - // It is considered that if user is not present in keycloak it is not present in database as well - // try { - // const decoded: any = jwt_decode(request.headers.authorization); - // const userRoles = - // decoded["https://hasura.io/jwt/claims"]["x-hasura-allowed-roles"]; - - // const userId = - // decoded["https://hasura.io/jwt/claims"]["x-hasura-user-id"]; - // userCreateDto.createdBy = userId; - // userCreateDto.updatedBy = userId; - - // userCreateDto.username = userCreateDto.username.toLocaleLowerCase(); - - // const userSchema = new UserCreateDto(userCreateDto); - - // let errKeycloak = ""; - // let resKeycloak = ""; - - // // if (altUserRoles.includes("systemAdmin")) { - - // const keycloakResponse = await getKeycloakAdminToken(); - // const token = keycloakResponse.data.access_token; - - // resKeycloak = await createUserInKeyCloak(userSchema, token).catch( - // (error) => { - // errKeycloak = error.response?.data.errorMessage; - - // return new ErrorResponse({ - // errorCode: "500", - // errorMessage: "Someting went wrong", - // }); - // } - // ); - // // } else { - // // return new ErrorResponse({ - // // errorCode: "401", - // // errorMessage: "Unauthorized", - // // }); - // // } - - // // Add userId created in keycloak as user Id of ALT user - // userCreateDto.userId = resKeycloak; - // return await this.createUserInDatabase(request, userCreateDto); - // } catch (e) { - // console.error(e); - // return e; - // } } async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { @@ -314,47 +156,6 @@ export class HasuraUserService implements IServicelocator { errorMessage: response.data.errors[0].message, }); } else { - // const result = response.data.data.insert_Users_one; - - // let fieldCreate = true; - // let fieldError = null; - // //create fields values - // let userId = result?.userId; - // let field_value_array = userCreateDto.fieldValues?.split("|"); - - // if (field_value_array?.length > 0) { - // let field_values = []; - // for (let i = 0; i < field_value_array.length; i++) { - // let fieldValues = field_value_array[i].split(":"); - // field_values.push({ - // value: fieldValues[1] ? fieldValues[1] : "", - // itemId: userId, - // fieldId: fieldValues[0] ? fieldValues[0] : "", - // createdBy: userCreateDto?.createdBy, - // updatedBy: userCreateDto?.updatedBy, - // }); - // } - - // const response_field_values = - // await this.fieldsService.createFieldValuesBulk(field_values); - // if (response_field_values?.data?.errors) { - // fieldCreate = false; - // fieldError = response_field_values?.data; - // } - // } - - // if (fieldCreate) { - // return new SuccessResponse({ - // statusCode: 200, - // message: "Ok.", - // data: result, - // }); - // } else { - // return new ErrorResponse({ - // errorCode: fieldError?.errors[0]?.extensions?.code, - // errorMessage: fieldError?.errors[0]?.message, - // }); - // } } }catch (e) { console.error(e); @@ -421,42 +222,6 @@ export class HasuraUserService implements IServicelocator { errorMessage: response?.data?.errors[0]?.message, }); } else { - // let result = response.data.update_Users_by_pk; - // let fieldCreate = true; - // let fieldError = []; - // //update fields values - // let field_value_array = userUpdateDto.fieldValues?.split("|"); - // if (field_value_array?.length > 0) { - // for (let i = 0; i < field_value_array.length; i++) { - // let fieldValues = field_value_array[i].split(":"); - // //update values - // let fieldValuesUpdate = new FieldValuesDto({ - // value: fieldValues[1] ? fieldValues[1] : "", - // }); - - // const response_field_values = - // await this.fieldsService.updateFieldValues( - // fieldValues[0] ? fieldValues[0] : "", - // fieldValuesUpdate - // ); - // if (response_field_values?.data?.errors) { - // fieldCreate = false; - // fieldError.push(response_field_values?.data); - // } - // } - // } - // if (fieldCreate) { - // return new SuccessResponse({ - // statusCode: 200, - // message: "User updated successfully ", - // data: result, - // }); - // } else { - // return new ErrorResponse({ - // errorCode: "filed value update error", - // errorMessage: JSON.stringify(fieldError), - // }); - // } } } diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 917dc08b..9df99836 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -51,13 +51,6 @@ export class fieldValuesDto{ @IsUUID(undefined, { message: 'Field Id must be a valid UUID' }) fieldId: string; - // @ApiPropertyOptional({ - // type: String, - // description: "Field type", - // }) - // @Expose() - // fieldType: string; - @ApiPropertyOptional({ type: String, description: "Field values", From 106b62b6ffae070a5d0092cd895e6fcbde384b58 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 15 May 2024 17:23:07 +0530 Subject: [PATCH 332/408] add --- src/user/user.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index a8d992ad..3d1acf11 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -41,7 +41,7 @@ import { Response } from "express"; import { isUUID } from "class-validator"; import { SuccessResponse } from "src/success-response"; @ApiTags("User") -// @UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard) @Controller("users") export class UserController { constructor( From c1d4e8c8d52a69b7223f8e8519b1b896dc4e88fa Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 15 May 2024 17:27:15 +0530 Subject: [PATCH 333/408] Fix[swagger fix] --- src/attendance/dto/attendance-search.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attendance/dto/attendance-search.dto.ts b/src/attendance/dto/attendance-search.dto.ts index 46be7c00..8f4de7f8 100644 --- a/src/attendance/dto/attendance-search.dto.ts +++ b/src/attendance/dto/attendance-search.dto.ts @@ -121,7 +121,7 @@ export class AttendanceSearchDto { @ApiPropertyOptional({ description: "Sort", - example: ["attendanceDate", "ascending"] + example: ["attendanceDate", "asc"] }) @IsArray() @IsOptional() From 1e7d27fca594436a17473aecd70571f7964a5dec Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Wed, 15 May 2024 17:29:09 +0530 Subject: [PATCH 334/408] Task:PS-372 User: Delete user API- delete user from keycloak,user & related tables --- src/adapters/hasura/user.adapter.ts | 3 ++ src/adapters/postgres/user-adapter.ts | 60 +++++++++++++++++++++++++++ src/adapters/userservicelocator.ts | 2 + src/user/user.controller.ts | 24 +++++++++++ 4 files changed, 89 insertions(+) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 63f17a0e..ace77332 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -941,4 +941,7 @@ export class HasuraUserService implements IServicelocator { return e; } } + + public async deleteUserById(userId){} + } \ No newline at end of file diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index b4130911..f8a56061 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -775,6 +775,66 @@ export class PostgresUserService { }; } + public async deleteUserById(userId){ + const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; + // Validate userId format + if (!isUUID(userId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter a valid UUID for userId", + }); + } + + try { + // Check if user exists in usersRepository + const user = await this.usersRepository.findOne({ where :{userId:userId}}); + if (!user) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User not found in user table.", + }); + } + + + // Delete from User table + const userResult = await this.usersRepository.delete(userId); + + // Delete from CohortMembers table + const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); + + // Delete from UserTenantMapping table + const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); + + // Delete from UserRoleMapping table + const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); + + // Delete from FieldValues table where ItemId matches userId + const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); + + const keycloakResponse = await getKeycloakAdminToken(); + const token = keycloakResponse.data.access_token; + + await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { + headers: { + 'Authorization': `Bearer ${token}` + }}); + + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "User and related entries deleted Successfully.", + data: { + user: userResult + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + } diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index 3832723a..d25066da 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -23,4 +23,6 @@ export interface IServicelocator { userSearchDto: UserSearchDto ); resetUserPassword(request: any, username: string, newPassword: string); + deleteUserById(userId); + } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 3d1acf11..714c6612 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -14,6 +14,7 @@ import { UsePipes, ValidationPipe, HttpStatus, + Delete, } from "@nestjs/common"; import { Request } from "@nestjs/common"; @@ -161,4 +162,27 @@ export class UserController { .buildUserAdapter() .resetUserPassword(request, reqBody.username, reqBody.newPassword); } + + //delete + @Delete("/:userId") + + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "User deleted successfully" }) + @ApiNotFoundResponse({ description: "Data not found" }) + @SerializeOptions({ + strategy: "excludeAll", + }) + + public async deleteUserById( + @Headers() headers, + @Param("userId") userId: string, + @Req() request: Request, + @Res() response: Response + ) { + + const result = await this.userAdapter + .buildUserAdapter() + .deleteUserById(userId); + return response.status(result.statusCode).json(result); + } } From 08a2b5c08217b54f61c3be60899edbf0413bf3e2 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Wed, 15 May 2024 17:52:22 +0530 Subject: [PATCH 335/408] Resolve all comments --- src/adapters/userservicelocator.ts | 2 +- src/user/user.controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index d25066da..b91584ed 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -23,6 +23,6 @@ export interface IServicelocator { userSearchDto: UserSearchDto ); resetUserPassword(request: any, username: string, newPassword: string); - deleteUserById(userId); + deleteUserById(userId: string): Promise; } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 714c6612..d2806b4f 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -167,7 +167,7 @@ export class UserController { @Delete("/:userId") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "User deleted successfully" }) + @ApiOkResponse({ description: "User deleted successfully" }) @ApiNotFoundResponse({ description: "Data not found" }) @SerializeOptions({ strategy: "excludeAll", From 29e3112ef716a458fec6fccd3c4ef7fd487659a2 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 16 May 2024 10:04:24 +0530 Subject: [PATCH 336/408] comment changes --- src/adapters/postgres/cohortMembers-adapter.ts | 12 +++++++----- src/adapters/postgres/user-adapter.ts | 2 -- src/user/dto/user-create.dto.ts | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index 2f3b1fd7..da7ef909 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -331,8 +331,6 @@ export class PostgresCohortMembersService { let whereCase = ``; let optionsCase = ``; let isRoleCondition = 0; - console.log("WHERE ",where) - console.log("LENGTH ",where.length); if (where.length > 0) { whereCase = `where `; where.forEach((value,index) => { @@ -355,12 +353,16 @@ export class PostgresCohortMembersService { } if(isRoleCondition == 0) { - query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + query = `SELECT U."userId", U.username, U.name, R.name AS role, U.district, U.state,U.mobile FROM public."CohortMembers" CM INNER JOIN public."Users" U - ON CM."userId" = U."userId" ${whereCase} ${optionsCase}`; + ON CM."userId" = U."userId" + INNER JOIN public."UserRolesMapping" UR + ON UR."userId" = U."userId" + INNER JOIN public."Roles" R + ON R."roleId" = UR."roleId" ${whereCase} ${optionsCase}`; } else { - query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + query = `SELECT U."userId", U.username, U.name, R.name AS role, U.district, U.state,U.mobile FROM public."CohortMembers" CM INNER JOIN public."Users" U ON CM."userId" = U."userId" INNER JOIN public."UserRolesMapping" UR diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 62a72ffd..7ffd600b 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -765,8 +765,6 @@ export class PostgresUserService { } public async validateFieldValues(field_values) { - - let encounteredKeys = [] for (const fieldValue of field_values) { const fieldId = fieldValue['fieldId']; diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index 9df99836..b3d8eadd 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -42,7 +42,7 @@ export class tenantRoleMappingDto{ roleId: string; } -export class fieldValuesDto{ +export class FieldValuesDto{ @ApiPropertyOptional({ type: String, description: "Field Id", @@ -144,13 +144,13 @@ export class UserCreateDto { updatedBy: string; //fieldValues - @ApiProperty({ - type: [fieldValuesDto], + @ApiPropertyOptional({ + type: [FieldValuesDto], description: "The fieldValues Object", }) @ValidateNested({ each: true }) - @Type(() => fieldValuesDto) - fieldValues: fieldValuesDto[]; + @Type(() => FieldValuesDto) + fieldValues: FieldValuesDto[]; @ApiProperty({ type: [tenantRoleMappingDto], From 6562ff7985fcfe0b27f9a9bf47f733da4eea6b27 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 17 May 2024 18:53:03 +0530 Subject: [PATCH 337/408] PS-369: Added Check Valid Email API --- src/adapters/hasura/user.adapter.ts | 3 ++ src/adapters/postgres/user-adapter.ts | 60 +++++++++++++++++++-------- src/adapters/userservicelocator.ts | 1 + src/user/user.controller.ts | 14 ++++++- 4 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 9681ebb7..b9f03d99 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -26,6 +26,9 @@ export class HasuraUserService implements IServicelocator { private httpService: HttpService, private fieldsService: FieldsService ) {} + checkUser(body: any, response: any) { + throw new Error("Method not implemented."); + } public async findUserDetails(userID: any, username: String) { } diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index bee881b7..986ad26f 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -9,6 +9,7 @@ import { getKeycloakAdminToken, createUserInKeyCloak, checkIfUsernameExistsInKeycloak, + checkIfEmailExistsInKeycloak } from "../../common/utils/keycloak.adapter.util" import { ErrorResponse } from 'src/error-response'; import { SuccessResponse } from 'src/success-response'; @@ -89,7 +90,6 @@ export class PostgresUserService { skip: offset, take: parseInt(limit), }); - console.log(results); return results; } @@ -125,11 +125,13 @@ export class PostgresUserService { }); } const customFields = await this.findCustomFields(userData, userDetails.role) - result.userData = userDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { - const fieldValue = filledValuesMap.get(data.fieldId); + let fieldValue:any = filledValuesMap.get(data.fieldId); + if(data.type === 'checkbox'){ + fieldValue=fieldValue.split(',') + } const customField = { fieldId: data.fieldId, label: data.label, @@ -158,7 +160,7 @@ export class PostgresUserService { async getUsersDetailsByCohortId(userData: Record, response: any) { let apiId = 'api.users.getAllUsersDetails' try { - if (userData.fieldValue) { + if (userData?.fieldValue) { let getUserDetails = await this.findUserName(userData.cohortId, userData.contextType) let result = { userDetails: [], @@ -201,7 +203,6 @@ export class PostgresUserService { customField: [], } const fieldValues = await this.getFieldandFieldValues(data.userId) - userDetails.customField.push(fieldValues); result.userDetails.push(userDetails); @@ -214,7 +215,6 @@ export class PostgresUserService { }); } - } catch (e) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, @@ -306,7 +306,7 @@ export class PostgresUserService { const result = await this.updateCustomFields(userDto.userId, data); if (result) { if (!updatedData['customFields']) - updatedData['customFields'] = []; + updatedData['customFields'] = []; updatedData['customFields'].push(result); } } @@ -427,8 +427,6 @@ export class PostgresUserService { errors, }; } - - let result = await this.createUserInDatabase(request, userCreateDto, cohortId); let fieldData = {}; @@ -465,19 +463,47 @@ export class PostgresUserService { } } + async checkUser(body){ + let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(body); + if(checkUserinKeyCloakandDb){ + return new SuccessResponse({ + statusCode: 200, + message: "User Exists. Proceed with Sending Email ", + data: {data:true}, + }); + } + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: "Invalid Username Or Email", + data: {data:false}, + }); + } + // Can be Implemeneted after we know what are the unique entties async checkUserinKeyCloakandDb(userDto) { const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( - userDto.username, - token - ); - if (usernameExistsInKeycloak.data.length > 0) { - return usernameExistsInKeycloak; + if(userDto?.username){ + const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( + userDto?.username, + token + ); + if (usernameExistsInKeycloak?.data?.length > 0) { + return usernameExistsInKeycloak; + } + return false; + }else{ + const usernameExistsInKeycloak = await checkIfEmailExistsInKeycloak( + userDto?.email, + token + ); + if (usernameExistsInKeycloak.data.length > 0) { + return usernameExistsInKeycloak; + } + return false; } - return false; - } +} + async createUserInDatabase(request: any, userCreateDto: UserCreateDto, cohortId) { const user = new User() diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index 3832723a..1daceb8b 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -23,4 +23,5 @@ export interface IServicelocator { userSearchDto: UserSearchDto ); resetUserPassword(request: any, username: string, newPassword: string); + checkUser(body:any,response); } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index be296bb5..8ea023bc 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -41,7 +41,6 @@ import { Response } from "express"; import { isUUID } from "class-validator"; import { SuccessResponse } from "src/success-response"; @ApiTags("User") -@UseGuards(JwtAuthGuard) @Controller("users") export class UserController { constructor( @@ -49,6 +48,7 @@ export class UserController { ) {} @Get('/:userId') + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detais Fetched Succcessfully" }) @ApiNotFoundResponse({ description: "User Not Found" }) @@ -119,6 +119,7 @@ export class UserController { } @Post("/search") + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User list." }) @ApiBody({ type: UserSearchDto }) @@ -140,6 +141,7 @@ export class UserController { } @Post("/reset-password") + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Password reset successfully." }) @ApiForbiddenResponse({ description: "Forbidden" }) @@ -156,4 +158,14 @@ export class UserController { .buildUserAdapter() .resetUserPassword(request, reqBody.username, reqBody.newPassword); } + + @Post("/check") + async checkUser( + @Body() body, + @Res() response: Response + ) { + const result = await this.userAdapter.buildUserAdapter().checkUser(body,response) + return response.status(result.statusCode).json(result); + } + } From dc747de3f9de60c9483f4038045216ffa4d556b3 Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 17 May 2024 19:08:58 +0530 Subject: [PATCH 338/408] Valid Email Check --- src/adapters/postgres/user-adapter.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index dfa542d8..4b9d04d2 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -549,6 +549,21 @@ export class PostgresUserService { return true; } + async checkUser(body){ + let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(body); + if(checkUserinKeyCloakandDb){ + return new SuccessResponse({ + statusCode: 200, + message: "User Exists. Proceed with Sending Email ", + data: {data:true}, + }); + } + return new SuccessResponse({ + statusCode: HttpStatus.BAD_REQUEST, + message: "Invalid Username Or Email", + data: {data:false}, + }); + } // Can be Implemeneted after we know what are the unique entties async checkUserinKeyCloakandDb(userDto) { From 739eb9df1c2b2c654713b2dc4b367f90a8331384 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 20 May 2024 23:31:46 +0530 Subject: [PATCH 339/408] Cohort Module bug --- src/adapters/postgres/cohort-adapter.ts | 95 +++++++++++++++++------- src/cohort/cohort.controller.ts | 4 +- src/cohort/cohort.module.ts | 3 +- src/cohort/dto/cohort-search.dto.ts | 98 +++++++------------------ 4 files changed, 100 insertions(+), 100 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 54a7aa4e..1f43097b 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -18,6 +18,7 @@ import { FieldValues } from "../../fields/entities/fields-values.entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { isUUID } from "class-validator"; +import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; @@ -34,6 +35,8 @@ export class PostgresCohortService { private fieldValuesRepository: Repository, @InjectRepository(Fields) private fieldsRepository: Repository, + @InjectRepository(UserTenantMapping) + private UserTenantMappingRepository: Repository, private fieldsService: PostgresFieldsService, ) { } @@ -77,7 +80,6 @@ export class PostgresCohortService { public async getCohortsDetails(cohortId: string) { try { - console.log(cohortId); if (!isUUID(cohortId)) { return new ErrorResponseTypeOrm({ @@ -191,19 +193,19 @@ export class PostgresCohortService { ]); return result; } - public async validateFieldValues(field_value_array:string[]) { - let encounteredKeys = [] - for (const fieldValue of field_value_array) { - const [fieldId] = fieldValue.split(":").map(value => value.trim()); + public async validateFieldValues(field_value_array: string[]) { + let encounteredKeys = [] + for (const fieldValue of field_value_array) { + const [fieldId] = fieldValue.split(":").map(value => value.trim()); + + if (encounteredKeys.includes(fieldId)) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.CONFLICT, + errorMessage: `Duplicate fieldId '${fieldId}' found in fieldValues.`, + }); + } + encounteredKeys.push(fieldId); - if (encounteredKeys.includes(fieldId)) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: `Duplicate fieldId '${fieldId}' found in fieldValues.`, - }); - } - encounteredKeys.push(fieldId); - }; } @@ -233,9 +235,9 @@ export class PostgresCohortService { const updateData = { status: true }; const cohortId = existData[0].cohortId; await this.cohortRepository.update(cohortId, updateData); - const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; - }else{ + } else { return new SuccessResponse({ statusCode: HttpStatus.CONFLICT, message: "Cohort name already exist for this parent.", @@ -255,7 +257,7 @@ export class PostgresCohortService { const updateData = { status: true }; const cohortId = existData[0].cohortId; await this.cohortRepository.update(cohortId, updateData); - const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { return new SuccessResponse({ @@ -266,7 +268,7 @@ export class PostgresCohortService { } } } - + let cohortId = response?.cohortId; if (field_value_array.length > 0) { @@ -351,7 +353,7 @@ export class PostgresCohortService { const existData = await this.cohortRepository.find({ where: { name: cohortUpdateDto.name, parentId: cohortUpdateDto.parentId } }) - + if (existData.length == 0) { response = await this.cohortRepository.update(cohortId, updateData); } else { @@ -359,9 +361,9 @@ export class PostgresCohortService { const updateData = { status: true }; const cohortId = existData[0].cohortId; await this.cohortRepository.update(cohortId, updateData); - const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; - }else{ + } else { return new SuccessResponse({ statusCode: HttpStatus.CONFLICT, message: "Cohort name already exist for this parent please choose another name.", @@ -373,7 +375,7 @@ export class PostgresCohortService { const existData = await this.cohortRepository.find({ where: { name: cohortUpdateDto.name } }) - + if (existData.length == 0) { response = await this.cohortRepository.update(cohortId, updateData); } else { @@ -381,7 +383,7 @@ export class PostgresCohortService { const updateData = { status: true }; const cohortId = existData[0].cohortId; await this.cohortRepository.update(cohortId, updateData); - const cohortData = await this.cohortRepository.find({where: { cohortId: cohortId }}) + const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { return new SuccessResponse({ @@ -418,8 +420,6 @@ export class PostgresCohortService { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; - // console.log(fieldValueDto); - await this.fieldsService.createFieldValues(request, fieldValueDto); } } @@ -461,7 +461,10 @@ export class PostgresCohortService { let { limit, page, filters } = cohortSearchDto; let offset = 0; - if (page > 1) { + + if (limit == 0 || page == 0) { + limit = 20; + } else { offset = (limit) * (page - 1); } @@ -483,7 +486,7 @@ export class PostgresCohortService { }); } - const allowedKeys = ["userId", "cohortId", "programId", "parentId", "name", "type", "status", "createdBy", "updatedBy"]; + const allowedKeys = ["userId", "cohortId", "name"]; const whereClause = {}; if (filters && Object.keys(filters).length > 0) { @@ -494,11 +497,34 @@ export class PostgresCohortService { errorMessage: `${key} Invalid key`, }); } else { + if (value === '') { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `Blank value for key '${key}'. Please provide a valid value.`, + }); + } whereClause[key] = value; } }); } + if (whereClause['userId']) { + if (!isUUID(whereClause['userId'])) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: 'Invalid User ID format. It must be a valid UUID.', + }); + } + } + + if (whereClause['cohortId']) { + if (!isUUID(whereClause['cohortId'])) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: 'Invalid Cohort ID format. It must be a valid UUID.', + }); + } + } let results = { cohortDetails: [], @@ -513,6 +539,19 @@ export class PostgresCohortService { errorMessage: "When filtering by userId, do not include additional fields.", }); } + + let userTenantMapExist = await this.UserTenantMappingRepository.find({ + where:{ + tenantId:tenantId, + userId:whereClause['userId'] + } + }) + if(userTenantMapExist.length == 0){ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User is not map for this tenant.", + }); + } const [cohortData] = await this.cohortMembersRepository.findAndCount({ where: whereClause, skip: offset, @@ -523,13 +562,13 @@ export class PostgresCohortService { let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); results.cohortDetails.push(cohortDetails); } - } else { const [cohortData] = await this.cohortRepository.findAndCount({ where: whereClause, skip: offset, take: limit, }); + for (let data of cohortData) { let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); results.cohortDetails.push(cohortDetails); @@ -539,7 +578,7 @@ export class PostgresCohortService { if (results.cohortDetails.length > 0) { return new SuccessResponse({ statusCode: HttpStatus.OK, - message: 'Cohort detais fetched succcessfully', + message: 'Cohort details fetched successfully', data: results, }); } else { diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index cf10de35..49f3ac3d 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -129,7 +129,6 @@ export class CohortController { @ApiOkResponse({ description: "Cohort list" }) @ApiBadRequestResponse({ description: "Bad request." }) @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) - // @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe()) @SerializeOptions({ strategy: "excludeAll", @@ -144,6 +143,9 @@ export class CohortController { @Res() response: Response ) { let tenantid = headers["tenantid"]; + if(tenantid === ''){ + return response.status(400).json({"statusCode": 400, "errorMessage": "TenantId required."}); + } const result = await this.cohortAdapter.buildCohortAdapter().searchCohort( tenantid, request, diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index c4e9e15b..e8dddc71 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -11,10 +11,11 @@ import { FieldValues } from "../fields/entities/fields-values.entity"; import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { PostgresModule } from "src/adapters/postgres/potsgres-module"; import { PostgresCohortService } from "src/adapters/postgres/cohort-adapter"; +import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; @Module({ imports: [ - TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers]), + TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers, UserTenantMapping]), HttpModule, HasuraModule, PostgresModule diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index a083ba88..50ac3e11 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -1,8 +1,28 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsBoolean, IsNumber, IsNumberString, IsObject, IsOptional, IsString } from "class-validator"; +import { IsBoolean, IsNotEmpty, IsNumber, IsNumberString, IsObject, IsOptional, IsString, IsUUID, ValidationArguments, ValidationOptions, registerDecorator } from "class-validator"; import { CohortDto } from "./cohort.dto"; import { Expose } from "class-transformer"; +// Custom decorator to check if the object is not empty +function IsNotEmptyObject(validationOptions?: ValidationOptions) { + return function (object: Object, propertyName: string) { + registerDecorator({ + name: 'isNotEmptyObject', + target: object.constructor, + propertyName: propertyName, + options: validationOptions, + validator: { + validate(value: any, args: ValidationArguments) { + return value && Object.keys(value).length > 0; + }, + defaultMessage(args: ValidationArguments) { + return `${args.property} should not be an empty object`; + }, + }, + }); + }; +} + export class setFilters { //userIdBy @ApiProperty({ @@ -12,10 +32,11 @@ export class setFilters { }) @Expose() @IsOptional() - @IsString() + @IsUUID() + @IsNotEmpty() userId?: string; - //userIdBy + //cohortIdBy @ApiProperty({ type: String, description: "The cohort is createdBy", @@ -23,31 +44,10 @@ export class setFilters { }) @Expose() @IsOptional() - @IsString() + @IsUUID() + @IsNotEmpty() cohortId?: string; - //programId - @ApiPropertyOptional({ - type: String, - description: "The programId of the cohort", - default: "", - }) - @Expose() - @IsOptional() - @IsString() - programId?: string; - - //parentId - @ApiPropertyOptional({ - type: String, - description: "The parentId of the cohort", - default: "", - }) - @Expose() - @IsOptional() - @IsString() - parentId?: string; - //name @ApiProperty({ type: String, @@ -57,51 +57,8 @@ export class setFilters { @Expose() @IsOptional() @IsString() + @IsNotEmpty() name?: string; - - //type - @ApiProperty({ - type: String, - description: "The type of the cohort", - default: "", - }) - @Expose() - @IsOptional() - @IsString() - type?: string; - - //status - @ApiPropertyOptional({ - type: Boolean, - description: "The status of the cohort", - default: true, - }) - @Expose() - @IsOptional() - @IsBoolean() - status?: boolean; - - //createdBy - @ApiProperty({ - type: String, - description: "The cohort is createdBy", - default: "", - }) - @Expose() - @IsOptional() - @IsString() - createdBy?: string; - - //updatedBy - @ApiProperty({ - type: String, - description: "The cohort is updatedBy", - default: "", - }) - @Expose() - @IsOptional() - @IsString() - updatedBy?: string; } export class CohortSearchDto { @@ -124,6 +81,7 @@ export class CohortSearchDto { description: "Filters", }) @IsObject() + @IsNotEmptyObject({ message: 'Filters should not be an empty object' }) filters: setFilters; constructor(partial: Partial) { From 348b421d4615358c8a9ccfbda8e66142521260b8 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 20 May 2024 23:46:49 +0530 Subject: [PATCH 340/408] add --- src/adapters/postgres/cohort-adapter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 1f43097b..e09c5dec 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -549,7 +549,7 @@ export class PostgresCohortService { if(userTenantMapExist.length == 0){ return new ErrorResponseTypeOrm({ statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User is not map for this tenant.", + errorMessage: "User is not mapped for this tenant.", }); } const [cohortData] = await this.cohortMembersRepository.findAndCount({ From 0fe18df360f46b1c825d6dbf40e854704a493f7e Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 20 May 2024 23:57:22 +0530 Subject: [PATCH 341/408] Uncomment JWT token --- src/cohort/cohort.controller.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index 49f3ac3d..adf6a715 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -1,7 +1,6 @@ import { ApiTags, ApiBody, - ApiForbiddenResponse, ApiCreatedResponse, ApiBasicAuth, ApiConsumes, @@ -29,7 +28,6 @@ import { UseGuards, ValidationPipe, UsePipes, - Query, BadRequestException, } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; @@ -41,13 +39,11 @@ import { Response, response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortUpdateDto } from "./dto/cohort-update.dto"; - import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; -import { QueryParamsDto } from "./dto/query-params.dto"; @ApiTags("Cohort") @Controller("cohorts") -// @UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard) export class CohortController { constructor(private readonly cohortAdapter: CohortAdapter) { } From 4199070bd6641e0d82b94beec6595cdbf9652ce6 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 21 May 2024 09:43:45 +0530 Subject: [PATCH 342/408] spelling mistakes --- src/cohort/cohort.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index adf6a715..f3aa96b6 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -50,7 +50,7 @@ export class CohortController { //Get Cohort Details @Get("/:cohortId") @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "Cohort detais Fetched Succcessfully" }) + @ApiOkResponse({ description: "Cohort details Fetched Successfully" }) @ApiNotFoundResponse({ description: "Cohort Not Found" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) @ApiBadRequestResponse({ description: "Bad Request" }) From fe93942421fa40b0183cc086d2d88b13f7a9492c Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 21 May 2024 14:18:01 +0530 Subject: [PATCH 343/408] PS-582 Fix: Fixed Bug of Get User API. REmoved Arraty in case of Checkbox and DropDown. --- src/adapters/postgres/user-adapter.ts | 47 +++++++++++++-------------- src/adapters/userservicelocator.ts | 2 +- src/user/user.controller.ts | 3 +- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 4b9d04d2..3b81b8e1 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -23,6 +23,7 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; +import { CourseController } from 'src/course/course.controller'; @Injectable() export class PostgresUserService { @@ -100,36 +101,36 @@ export class PostgresUserService { return results; } - async getUsersDetailsById(userData: Record, response: any) { + async getUsersDetailsById(userData: any, response: any) { try { if (!isUUID(userData.userId)) { return new SuccessResponse({ statusCode: HttpStatus.BAD_REQUEST, - message: 'Please Enter Valid User ID', + message: 'Please Enter Valid UUID', }); } const result = { userData: { } }; + let filledValues:any; let customFieldsArray = []; - - const [filledValues, userDetails, userRole] = await Promise.all([ - this.findFilledValues(userData.userId), + if(userData?.fieldValue){ + filledValues = await this.findFilledValues(userData.userId) + } + let [userDetails, userRole] = await Promise.all([ this.findUserDetails(userData.userId), this.findUserRoles(userData.userId,userData.tenantId) ]); - if(userRole){ userDetails['role'] = userRole.title; } - if (!userDetails) { return new SuccessResponse({ statusCode: HttpStatus.NOT_FOUND, message: 'User Not Found', }); - } + } if (!userData.fieldValue) { return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -138,15 +139,14 @@ export class PostgresUserService { }); } const customFields = await this.findCustomFields(userData) - result.userData = userDetails; - const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { let fieldValue:any = filledValuesMap.get(data.fieldId); - if(data.type === 'checkbox'){ - fieldValue=fieldValue.split(',') - } + // if(data.type === 'checkbox' && fieldValue){ + // console.log("Hi",fieldValue); + // fieldValue=fieldValue.split(',') + // } const customField = { fieldId: data.fieldId, label: data.label, @@ -158,15 +158,11 @@ export class PostgresUserService { }; customFieldsArray.push(customField); } - - result.userData['customFields'] = customFieldsArray; - - return new SuccessResponse({ statusCode: HttpStatus.OK, - message: 'User detais Fetched Succcessfully.', + message: 'User details Fetched Successfully.', data: result, }); @@ -279,10 +275,11 @@ export class PostgresUserService { tenantId:tenantId } }) - - let role - - role = await this.roleRepository.findOne({ + if(!getRole) { + return false; + } + let role; + role = await this.roleRepository.findOne({ where:{ roleId:getRole.roleId, }, @@ -301,12 +298,12 @@ export class PostgresUserService { where: whereClause, select: ["userId", "username", "name", "district", "state", "mobile"] }) - + if(!userDetails){ + return false; + } const tenentDetails = await this.allUsersTenent(userDetails.userId) - userDetails['tenantData'] = tenentDetails; return userDetails; - } async allUsersTenent(userId: string) { const query = ` diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index a37ce3b1..03da13bb 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -11,7 +11,7 @@ export interface IServicelocator { // accessRole?: string, // request?: any, // ); - getUsersDetailsById(userData: Record, response:any); + getUsersDetailsById(userData: any, response:any); getUsersDetailsByCohortId(userData: Record, response:any); updateUser(userDto?: any,response?: any); createUser(request: any, userDto: UserCreateDto); diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 0fee1128..046af4e0 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -69,12 +69,13 @@ export class UserController { if(!tenantId){ return response.status(400).json({ "statusCode": 400, error: "Please provide a tenantId." }); } + const fieldValueBoolean = fieldvalue === 'true'; // Context and ContextType can be taken from .env later let userData = { context: "USERS", tenantId: tenantId, userId: userId, - fieldValue: fieldvalue + fieldValue: fieldValueBoolean } let result; result = await this.userAdapter.buildUserAdapter().getUsersDetailsById(userData, response); From 5ee08a816327be8b9cf5142a81039eaf33e9397f Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 21 May 2024 14:52:26 +0530 Subject: [PATCH 344/408] PS-582 Fix: Added Type Safety. --- src/adapters/hasura/user.adapter.ts | 3 ++- src/adapters/postgres/user-adapter.ts | 3 ++- src/adapters/userservicelocator.ts | 4 ++-- src/user/user.controller.ts | 11 ++++++++++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 8481438f..0f31aa23 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -7,6 +7,7 @@ import jwt_decode from "jwt-decode"; import { UserSearchDto } from "src/user/dto/user-search.dto"; import { ErrorResponse } from "src/error-response"; import { FieldsService } from "./services/fields.service"; +import { UserData } from "src/user/user.controller"; // import { UserUpdateDto } from "src/user/dto/user-update.dto"; import { getUserRole, @@ -32,7 +33,7 @@ export class HasuraUserService implements IServicelocator { public async findUserDetails(userID: any, username: String) { } - public async getUsersDetailsById(userData: Record, response:any) {} + public async getUsersDetailsById(userData: UserData, response:any) {} public async getUsersDetailsByCohortId(userData: Record, response:any) {} public async checkAndAddUser(request: any, userDto: UserCreateDto) { diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 3b81b8e1..63536e5d 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -24,6 +24,7 @@ import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; import { CourseController } from 'src/course/course.controller'; +import { UserData } from 'src/user/user.controller'; @Injectable() export class PostgresUserService { @@ -101,7 +102,7 @@ export class PostgresUserService { return results; } - async getUsersDetailsById(userData: any, response: any) { + async getUsersDetailsById(userData: UserData, response: any) { try { if (!isUUID(userData.userId)) { return new SuccessResponse({ diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index 03da13bb..f777cfcd 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -1,6 +1,6 @@ import { UserCreateDto } from "src/user/dto/user-create.dto"; import { UserSearchDto } from "src/user/dto/user-search.dto"; -import { UserDto } from "src/user/dto/user.dto"; +import { UserData } from "src/user/user.controller"; export interface IServicelocator { // getUser( @@ -11,7 +11,7 @@ export interface IServicelocator { // accessRole?: string, // request?: any, // ); - getUsersDetailsById(userData: any, response:any); + getUsersDetailsById(userData: UserData, response:any); getUsersDetailsByCohortId(userData: Record, response:any); updateUser(userDto?: any,response?: any); createUser(request: any, userDto: UserCreateDto); diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 046af4e0..cf51807a 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -41,6 +41,15 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { Response } from "express"; import { isUUID } from "class-validator"; import { SuccessResponse } from "src/success-response"; + + +export interface UserData { + context: string; + tenantId: string; + userId: string; + fieldValue: boolean; +} + @ApiTags("User") @Controller("users") export class UserController { @@ -71,7 +80,7 @@ export class UserController { } const fieldValueBoolean = fieldvalue === 'true'; // Context and ContextType can be taken from .env later - let userData = { + let userData:UserData = { context: "USERS", tenantId: tenantId, userId: userId, From 7fe5054e7e1d824d9b4f529f2d521dc2f9d62ffa Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 21 May 2024 14:55:30 +0530 Subject: [PATCH 345/408] add --- src/adapters/postgres/user-adapter.ts | 193 ++++++++++++++------------ src/user/entities/user-entity.ts | 23 ++- src/utils/mask-data.ts | 56 ++++++++ 3 files changed, 174 insertions(+), 98 deletions(-) create mode 100644 src/utils/mask-data.ts diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 4b9d04d2..35a100fd 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -23,10 +23,11 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; +import { maskMobileNumber, maskEmail, maskDateOfBirth } from "src/utils/mask-data"; @Injectable() export class PostgresUserService { - axios = require("axios"); + axios = require("axios");maskEmail constructor( // private axiosInstance: AxiosInstance, @@ -117,10 +118,10 @@ export class PostgresUserService { const [filledValues, userDetails, userRole] = await Promise.all([ this.findFilledValues(userData.userId), this.findUserDetails(userData.userId), - this.findUserRoles(userData.userId,userData.tenantId) + this.findUserRoles(userData.userId, userData.tenantId) ]); - if(userRole){ + if (userRole) { userDetails['role'] = userRole.title; } @@ -129,23 +130,23 @@ export class PostgresUserService { statusCode: HttpStatus.NOT_FOUND, message: 'User Not Found', }); - } + } if (!userData.fieldValue) { return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', data: userDetails, }); - } + } const customFields = await this.findCustomFields(userData) - + result.userData = userDetails; - + const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { - let fieldValue:any = filledValuesMap.get(data.fieldId); - if(data.type === 'checkbox'){ - fieldValue=fieldValue.split(',') + let fieldValue: any = filledValuesMap.get(data.fieldId); + if (data.type === 'checkbox') { + fieldValue = fieldValue.split(',') } const customField = { fieldId: data.fieldId, @@ -160,9 +161,9 @@ export class PostgresUserService { } - + result.userData['customFields'] = customFieldsArray; - + return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -271,23 +272,23 @@ export class PostgresUserService { return result } - async findUserRoles(userId:string, tenantId:string) { - + async findUserRoles(userId: string, tenantId: string) { + const getRole = await this.userRoleMappingRepository.findOne({ - where:{ - userId:userId, - tenantId:tenantId + where: { + userId: userId, + tenantId: tenantId } }) - + let role - role = await this.roleRepository.findOne({ - where:{ - roleId:getRole.roleId, - }, - select: ["title"] - }) + role = await this.roleRepository.findOne({ + where: { + roleId: getRole.roleId, + }, + select: ["title"] + }) return role } @@ -430,7 +431,7 @@ export class PostgresUserService { if (userCreateDto.fieldValues) { let field_values = userCreateDto.fieldValues; const validateField = await this.validateFieldValues(field_values); - + if (validateField == false) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.CONFLICT, @@ -439,7 +440,7 @@ export class PostgresUserService { } } - + // check and validate all fields let validateBodyFields = await this.validateBodyFields(userCreateDto) @@ -495,7 +496,7 @@ export class PostgresUserService { } } } - + return new SuccessResponse({ statusCode: 200, message: "User has been created successfully.", @@ -549,19 +550,19 @@ export class PostgresUserService { return true; } - async checkUser(body){ + async checkUser(body) { let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(body); - if(checkUserinKeyCloakandDb){ + if (checkUserinKeyCloakandDb) { return new SuccessResponse({ statusCode: 200, message: "User Exists. Proceed with Sending Email ", - data: {data:true}, + data: { data: true }, }); } return new SuccessResponse({ statusCode: HttpStatus.BAD_REQUEST, message: "Invalid Username Or Email", - data: {data:false}, + data: { data: false }, }); } @@ -569,7 +570,7 @@ export class PostgresUserService { async checkUserinKeyCloakandDb(userDto) { const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - if(userDto?.username){ + if (userDto?.username) { const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( userDto?.username, token @@ -578,7 +579,7 @@ export class PostgresUserService { return usernameExistsInKeycloak; } return false; - }else{ + } else { const usernameExistsInKeycloak = await checkIfEmailExistsInKeycloak( userDto?.email, token @@ -588,27 +589,34 @@ export class PostgresUserService { } return false; } -} - + } + async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { const user = new User() user.username = userCreateDto?.username user.name = userCreateDto?.name user.email = userCreateDto?.email - user.mobile = Number(userCreateDto?.mobile) || null, + user.mobile = userCreateDto?.mobile, + user.dob = userCreateDto?.dob, user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, - user.state = userCreateDto?.state, - user.district = userCreateDto?.district, - user.address = userCreateDto?.address, - user.pincode = userCreateDto?.pincode + user.state = userCreateDto?.state, + user.district = userCreateDto?.district, + user.address = userCreateDto?.address, + user.pincode = userCreateDto?.pincode + if (userCreateDto?.email) { + user.email = maskEmail(user.email) + } + if (userCreateDto?.mobile) { + user.mobile = maskMobileNumber(user.mobile) + } if (userCreateDto?.dob) { - user.dob = new Date(userCreateDto.dob); + user.dob = maskDateOfBirth(user.dob); } - + let result = await this.usersRepository.save(user); if (result) { @@ -805,65 +813,68 @@ export class PostgresUserService { }; } - public async deleteUserById(userId){ + public async deleteUserById(userId) { const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; - // Validate userId format - if (!isUUID(userId)) { + // Validate userId format + if (!isUUID(userId)) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter a valid UUID for userId", + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter a valid UUID for userId", }); - } - - try { - // Check if user exists in usersRepository - const user = await this.usersRepository.findOne({ where :{userId:userId}}); - if (!user) { + } + + try { + // Check if user exists in usersRepository + const user = await this.usersRepository.findOne({ where: { userId: userId } }); + if (!user) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User not found in user table.", + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User not found in user table.", }); - } - - - // Delete from User table - const userResult = await this.usersRepository.delete(userId); - - // Delete from CohortMembers table - const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); - - // Delete from UserTenantMapping table - const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); - - // Delete from UserRoleMapping table - const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); - + } + + + // Delete from User table + const userResult = await this.usersRepository.delete(userId); + + // Delete from CohortMembers table + const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); + + // Delete from UserTenantMapping table + const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); + + // Delete from UserRoleMapping table + const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); + // Delete from FieldValues table where ItemId matches userId - const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); - + const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); + const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - - await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { + + await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { headers: { - 'Authorization': `Bearer ${token}` - }}); - - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "User and related entries deleted Successfully.", - data: { - user: userResult - }, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } + 'Authorization': `Bearer ${token}` + } + }); + + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "User and related entries deleted Successfully.", + data: { + user: userResult + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } + } + + } diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts index 1f108b1b..b45c7fa0 100644 --- a/src/user/entities/user-entity.ts +++ b/src/user/entities/user-entity.ts @@ -12,12 +12,6 @@ export class User { @Column() name: string; - @Column({ type: "date", nullable: true }) - dob: Date; - - @Column({ nullable: true }) - email: string; - @Column({ nullable: true }) district: string; @@ -37,7 +31,22 @@ export class User { updatedAt: Date; @Column() - mobile: number; + mobile: string; + + @Column() + encryptedMobile: string; + + @Column({ nullable: true }) + dob: string; + + @Column() + encryptedDob: string; + + @Column({ nullable: true }) + email: string; + + @Column() + encryptedEmail: string; @Column({ nullable: true }) createdBy: string; diff --git a/src/utils/mask-data.ts b/src/utils/mask-data.ts new file mode 100644 index 00000000..c99e0a7e --- /dev/null +++ b/src/utils/mask-data.ts @@ -0,0 +1,56 @@ +import { Injectable } from '@nestjs/common'; +import { createCipheriv, createDecipheriv } from 'crypto'; + +@Injectable() +export class EncryptionService { + private readonly secretKey = Buffer.from(process.env.SECRET_KEY, 'base64'); + + encrypt(data: string): string { + const cipher = createCipheriv('aes-256-ecb', this.secretKey, null); + const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]).toString('base64'); + return encrypted; + } + + decrypt(encryptedData: string): string { + const decipher = createDecipheriv('aes-256-ecb', this.secretKey, null); + const decrypted = Buffer.concat([decipher.update(Buffer.from(encryptedData, 'base64')), decipher.final()]).toString('utf8'); + return decrypted; + } +} + +export function maskMobileNumber(mobileNumber: any): string { + const mobileNumberStr = String(mobileNumber); + if (mobileNumberStr.length !== 10) { + throw new Error('Mobile number must be 10 digits long'); + } + const prefix = mobileNumberStr.substring(0, 2); + const suffix = mobileNumberStr.substring(8, 10); + return `${prefix}******${suffix}`; +} + +export function maskEmail(email: string): string { + if (typeof email !== 'string' || !email.includes('@')) { + throw new Error('Invalid email address'); + } + const [localPart, domain] = email.split('@'); + if (localPart.length < 2) { + throw new Error('Invalid email address'); + } + const maskedLocalPart = localPart[0] + '*'.repeat(localPart.length - 2) + localPart[localPart.length - 1]; + return `${maskedLocalPart}@${domain}`; +} + + +export function isValidDateFormat(date: string): boolean { + const regex = /^\d{4}-\d{2}-\d{2}$/; + return regex.test(date); +} + +export function maskDateOfBirth(dob: string): string { + if (!isValidDateFormat(dob)) { + throw new Error('Invalid date of birth format. Expected format: YYYY-MM-DD'); + } + return `****${dob.substring(4)}`; +} + + From 7b71b9ebf8a052613b067bf644e2cc51b446b84d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 21 May 2024 14:57:32 +0530 Subject: [PATCH 346/408] add --- src/adapters/postgres/user-adapter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 35a100fd..c648ece3 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -23,7 +23,7 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; -import { maskMobileNumber, maskEmail, maskDateOfBirth } from "src/utils/mask-data"; +import { maskMobileNumber, maskEmail, maskDateOfBirth, EncryptionService } from "src/utils/mask-data"; @Injectable() export class PostgresUserService { @@ -609,6 +609,7 @@ export class PostgresUserService { if (userCreateDto?.email) { user.email = maskEmail(user.email) + user.email = EncryptionService. } if (userCreateDto?.mobile) { user.mobile = maskMobileNumber(user.mobile) From e06022a139f4fefefe799a8e843196cc7b348b6b Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 22 May 2024 11:17:25 +0530 Subject: [PATCH 347/408] add --- src/adapters/postgres/user-adapter.ts | 12 +++++++----- src/utils/mask-data.ts | 15 +++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index c648ece3..488f461d 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -23,7 +23,7 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; -import { maskMobileNumber, maskEmail, maskDateOfBirth, EncryptionService } from "src/utils/mask-data"; +import { maskMobileNumber, maskEmail, maskDateOfBirth, encrypt } from "src/utils/mask-data"; @Injectable() export class PostgresUserService { @@ -145,9 +145,9 @@ export class PostgresUserService { const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { let fieldValue: any = filledValuesMap.get(data.fieldId); - if (data.type === 'checkbox') { - fieldValue = fieldValue.split(',') - } + // if (data.type === 'checkbox') { + // fieldValue = fieldValue.split(',') + // } const customField = { fieldId: data.fieldId, label: data.label, @@ -609,13 +609,15 @@ export class PostgresUserService { if (userCreateDto?.email) { user.email = maskEmail(user.email) - user.email = EncryptionService. + user.encryptedEmail = encrypt(user.email) } if (userCreateDto?.mobile) { user.mobile = maskMobileNumber(user.mobile) + user.encryptedMobile = encrypt(user.mobile) } if (userCreateDto?.dob) { user.dob = maskDateOfBirth(user.dob); + user.encryptedDob = encrypt(user.dob) } let result = await this.usersRepository.save(user); diff --git a/src/utils/mask-data.ts b/src/utils/mask-data.ts index c99e0a7e..6f95a92f 100644 --- a/src/utils/mask-data.ts +++ b/src/utils/mask-data.ts @@ -1,22 +1,21 @@ import { Injectable } from '@nestjs/common'; import { createCipheriv, createDecipheriv } from 'crypto'; -@Injectable() -export class EncryptionService { - private readonly secretKey = Buffer.from(process.env.SECRET_KEY, 'base64'); - encrypt(data: string): string { - const cipher = createCipheriv('aes-256-ecb', this.secretKey, null); +const secretKey = Buffer.from(process.env.SECRET_KEY, 'base64'); + +export function encrypt(data: string): string { + const cipher = createCipheriv('aes-256-ecb', secretKey, null); const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]).toString('base64'); return encrypted; } - decrypt(encryptedData: string): string { - const decipher = createDecipheriv('aes-256-ecb', this.secretKey, null); + export function decrypt(encryptedData: string): string { + const decipher = createDecipheriv('aes-256-ecb', secretKey, null); const decrypted = Buffer.concat([decipher.update(Buffer.from(encryptedData, 'base64')), decipher.final()]).toString('utf8'); return decrypted; } -} + export function maskMobileNumber(mobileNumber: any): string { const mobileNumberStr = String(mobileNumber); From 146eb913dc88a6495241f06ddbc37480dcb151e5 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 23 May 2024 12:07:37 +0530 Subject: [PATCH 348/408] search api changes --- src/adapters/postgres/cohort-adapter.ts | 55 +++++++++++-------------- src/cohort/dto/cohort-search.dto.ts | 21 ---------- 2 files changed, 25 insertions(+), 51 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index e09c5dec..61662afe 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -461,15 +461,15 @@ export class PostgresCohortService { let { limit, page, filters } = cohortSearchDto; let offset = 0; - - if (limit == 0 || page == 0) { - limit = 20; - } else { + if (limit > 0 && page > 0) { offset = (limit) * (page - 1); } + limit = 200; + const emptyValueKeys = {}; + let emptyKeysString = ''; - const MAX_LIMIT = 20; - const PAGE_LIMIT = 100000; + const MAX_LIMIT = 200; + const PAGE_LIMIT = 10000000; // Validate the limit parameter if (limit > MAX_LIMIT) { @@ -498,32 +498,27 @@ export class PostgresCohortService { }); } else { if (value === '') { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `Blank value for key '${key}'. Please provide a valid value.`, - }); + emptyValueKeys[key] = value; + emptyKeysString += (emptyKeysString ? ', ' : '') + key; + } else { + whereClause[key] = value; } - whereClause[key] = value; } }); } - if (whereClause['userId']) { - if (!isUUID(whereClause['userId'])) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: 'Invalid User ID format. It must be a valid UUID.', - }); - } + if (whereClause['userId'] && !isUUID(whereClause['userId'])) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: 'Invalid User ID format. It must be a valid UUID.', + }); } - if (whereClause['cohortId']) { - if (!isUUID(whereClause['cohortId'])) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: 'Invalid Cohort ID format. It must be a valid UUID.', - }); - } + if (whereClause['cohortId'] && !isUUID(whereClause['cohortId'])) { + throw new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: 'Invalid Cohort ID format. It must be a valid UUID.', + }); } let results = { @@ -541,12 +536,12 @@ export class PostgresCohortService { } let userTenantMapExist = await this.UserTenantMappingRepository.find({ - where:{ - tenantId:tenantId, - userId:whereClause['userId'] + where: { + tenantId: tenantId, + userId: whereClause['userId'] } }) - if(userTenantMapExist.length == 0){ + if (userTenantMapExist.length == 0) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.NOT_FOUND, errorMessage: "User is not mapped for this tenant.", @@ -568,7 +563,7 @@ export class PostgresCohortService { skip: offset, take: limit, }); - + for (let data of cohortData) { let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); results.cohortDetails.push(cohortDetails); diff --git a/src/cohort/dto/cohort-search.dto.ts b/src/cohort/dto/cohort-search.dto.ts index 50ac3e11..f6be8bc2 100644 --- a/src/cohort/dto/cohort-search.dto.ts +++ b/src/cohort/dto/cohort-search.dto.ts @@ -3,26 +3,6 @@ import { IsBoolean, IsNotEmpty, IsNumber, IsNumberString, IsObject, IsOptional, import { CohortDto } from "./cohort.dto"; import { Expose } from "class-transformer"; -// Custom decorator to check if the object is not empty -function IsNotEmptyObject(validationOptions?: ValidationOptions) { - return function (object: Object, propertyName: string) { - registerDecorator({ - name: 'isNotEmptyObject', - target: object.constructor, - propertyName: propertyName, - options: validationOptions, - validator: { - validate(value: any, args: ValidationArguments) { - return value && Object.keys(value).length > 0; - }, - defaultMessage(args: ValidationArguments) { - return `${args.property} should not be an empty object`; - }, - }, - }); - }; -} - export class setFilters { //userIdBy @ApiProperty({ @@ -81,7 +61,6 @@ export class CohortSearchDto { description: "Filters", }) @IsObject() - @IsNotEmptyObject({ message: 'Filters should not be an empty object' }) filters: setFilters; constructor(partial: Partial) { From 0351ca7304d426526cf6909a6f20ad90a7270610 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 23 May 2024 20:49:24 +0530 Subject: [PATCH 349/408] Role base field show --- src/adapters/postgres/user-adapter.ts | 21 +++++++++++++-------- src/user/user.controller.ts | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 63536e5d..5e429d16 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -116,13 +116,17 @@ export class PostgresUserService { }; let filledValues:any; let customFieldsArray = []; - if(userData?.fieldValue){ - filledValues = await this.findFilledValues(userData.userId) - } + let [userDetails, userRole] = await Promise.all([ this.findUserDetails(userData.userId), this.findUserRoles(userData.userId,userData.tenantId) ]); + + const roleInUpper = (userRole.title).toUpperCase(); + if(userData?.fieldValue){ + filledValues = await this.findFilledValues(userData.userId,roleInUpper) + } + if(userRole){ userDetails['role'] = userRole.title; } @@ -139,7 +143,7 @@ export class PostgresUserService { data: userDetails, }); } - const customFields = await this.findCustomFields(userData) + const customFields = await this.findCustomFields(userData,roleInUpper) result.userData = userDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { @@ -316,24 +320,25 @@ export class PostgresUserService { const result = await this.usersRepository.query(query, [userId]); return result; } - async findCustomFields(userData) { + async findCustomFields(userData, role) { let customFields = await this.fieldsRepository.find({ where: { context: userData.context, + contextType: role, } }) return customFields; } - async findFilledValues(userId: string) { + async findFilledValues(userId: string, role: string) { let query = `SELECT U."userId",FV."fieldId",FV."value", F."fieldAttributes" FROM public."Users" U LEFT JOIN public."FieldValues" FV ON U."userId" = FV."itemId" LEFT JOIN public."Fields" F ON F."fieldId" = FV."fieldId" - where U."userId" =$1`; + where U."userId" =$1 AND F."contextType" = $2`; - let result = await this.usersRepository.query(query, [userId]); + let result = await this.usersRepository.query(query, [userId,role]); return result; } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index cf51807a..7808f46f 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -60,7 +60,7 @@ export class UserController { @Get('/:userId') @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") - @ApiOkResponse({ description: "User detais Fetched Succcessfully" }) + @ApiOkResponse({ description: "User details Fetched Successfully" }) @ApiNotFoundResponse({ description: "User Not Found" }) @ApiInternalServerErrorResponse({description:"Internal Server Error" }) @ApiBadRequestResponse({description:"Bad Request"}) From fb86099506523a6e1457d78ade5ee509d861d9d4 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Mon, 27 May 2024 13:54:46 +0530 Subject: [PATCH 350/408] Task #219973: feat : global exception filter for microservice --- src/common/filters/exception.filter.ts | 27 ++++++++++++++++++++++++++ src/main.ts | 4 +++- src/user/user.controller.ts | 16 +++++++-------- 3 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 src/common/filters/exception.filter.ts diff --git a/src/common/filters/exception.filter.ts b/src/common/filters/exception.filter.ts new file mode 100644 index 00000000..f9817cd7 --- /dev/null +++ b/src/common/filters/exception.filter.ts @@ -0,0 +1,27 @@ +import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; +import { Response, Request } from 'express'; +import APIResponse from '../responses/response'; + +@Catch() +export class AllExceptionsFilter implements ExceptionFilter { + constructor(private readonly apiId?: string) { } + + catch(exception: unknown, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const status = exception instanceof HttpException ? exception.getStatus() : 500; + const exceptionResponse = exception instanceof HttpException ? exception.getResponse() : null; + const errorMessage = + exception instanceof HttpException + ? (exceptionResponse as any).message || exception.message + : 'Internal server error'; + const detailedErrorMessage = `${errorMessage}`; + APIResponse.error( + response, + this.apiId, + detailedErrorMessage, + exception instanceof HttpException ? exception.name : 'InternalServerError', // error + status.toString() + ); + } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 994a3676..55974cfd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -35,6 +35,8 @@ import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger"; import { RequestMethod } from "@nestjs/common"; import { join } from "path"; import express = require("express"); +import { AllExceptionsFilter } from "./common/filters/exception.filter"; + async function bootstrap() { const app = await NestFactory.create(AppModule); app.use( @@ -54,10 +56,10 @@ async function bootstrap() { { type: "apiKey", name: "Authorization", in: "header" }, "access-token" ) - .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup("api/swagger-docs", app, document); + app.useGlobalFilters(new AllExceptionsFilter()) app.enableCors(); await app.listen(3000); } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 7808f46f..675bfb40 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -13,11 +13,11 @@ import { Query, UsePipes, ValidationPipe, - HttpStatus, Delete, + ParseUUIDPipe, + UseFilters, } from "@nestjs/common"; -import { Request } from "@nestjs/common"; import { ApiTags, ApiBody, @@ -38,11 +38,9 @@ import { UserAdapter } from "./useradapter"; import { UserCreateDto } from "./dto/user-create.dto"; import { UserUpdateDTO } from "./dto/user-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; -import { Response } from "express"; -import { isUUID } from "class-validator"; -import { SuccessResponse } from "src/success-response"; - - +import { Request, Response } from "express"; +import { AllExceptionsFilter } from "src/common/filters/exception.filter"; +import { Reflector } from "@nestjs/core"; export interface UserData { context: string; tenantId: string; @@ -55,8 +53,10 @@ export interface UserData { export class UserController { constructor( private userAdapter: UserAdapter, + private reflector: Reflector, ) {} + @UseFilters(new AllExceptionsFilter('get.user.byid')) @Get('/:userId') @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @@ -71,7 +71,7 @@ export class UserController { @Headers() headers, @Req() request: Request, @Res() response: Response, - @Param("userId") userId: string, + @Param('userId', ParseUUIDPipe) userId: string, @Query("fieldvalue") fieldvalue: string | null = null ) { const tenantId = headers["tenantid"]; From ebe95e726b0a867618e317f58ec6fbeb514f0017 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 27 May 2024 18:22:17 +0530 Subject: [PATCH 351/408] User Profile: Set and show order for field values --- src/adapters/postgres/user-adapter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 5e429d16..23af55ac 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -155,6 +155,7 @@ export class PostgresUserService { const customField = { fieldId: data.fieldId, label: data.label, + order: data.ordering, value: fieldValue || '', isRequired: data.fieldAttributes ? data.fieldAttributes['isRequired'] : '', isEditable: data.fieldAttributes ? data.fieldAttributes['isEditable'] : '', From 41e28fe279722fb7cc1e27cad7c8553ab8c1865f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 27 May 2024 19:39:36 +0530 Subject: [PATCH 352/408] set message for blank data --- src/adapters/postgres/cohortMembers-adapter.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index da7ef909..740334cf 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -233,7 +233,13 @@ export class PostgresCohortMembersService { "true", options ); - + + if(results['userDetails'].length == 0){ + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "No data found.", + }); + } return new SuccessResponse({ statusCode: HttpStatus.OK, message: "Ok.", From 417fe69c9b5e189a809048488912d62c48491610 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Mon, 27 May 2024 22:43:06 +0530 Subject: [PATCH 353/408] add --- src/adapters/cohortMembersservicelocator.ts | 6 +- src/adapters/hasura/cohortMembers.adapter.ts | 4 +- .../postgres/cohortMembers-adapter.ts | 156 +++++++++--------- src/cohortMembers/cohortMembers.controller.ts | 11 +- src/common/responses/response-interface.ts | 34 ++++ src/common/responses/response.ts | 64 +++++++ 6 files changed, 188 insertions(+), 87 deletions(-) create mode 100644 src/common/responses/response-interface.ts create mode 100644 src/common/responses/response.ts diff --git a/src/adapters/cohortMembersservicelocator.ts b/src/adapters/cohortMembersservicelocator.ts index d81c3b7d..476a405d 100644 --- a/src/adapters/cohortMembersservicelocator.ts +++ b/src/adapters/cohortMembersservicelocator.ts @@ -1,15 +1,15 @@ import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-search.dto"; import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; import { CohortMembersUpdateDto } from "src/cohortMembers/dto/cohortMember-update.dto"; - +import { Response } from "express"; export interface IServicelocatorcohortMembers { createCohortMembers( loginUser: any, cohortMembersDto: CohortMembersDto, response: any ); - getCohortMembers(cohortMemberId: string, fieldvalue); - searchCohortMembers(cohortMembersSearchDto: CohortMembersSearchDto); + getCohortMembers(cohortMemberId: string,tenantId:string, fieldvalue:string, response:Response); + searchCohortMembers(cohortMembersSearchDto: CohortMembersSearchDto, tenantId:string, response:Response); updateCohortMembers( cohortMembershipId: string, loginUser: any, diff --git a/src/adapters/hasura/cohortMembers.adapter.ts b/src/adapters/hasura/cohortMembers.adapter.ts index bc38c2d9..3c1fd56e 100644 --- a/src/adapters/hasura/cohortMembers.adapter.ts +++ b/src/adapters/hasura/cohortMembers.adapter.ts @@ -75,8 +75,8 @@ export class HasuraCohortMembersService } } - public async searchCohortMembers(cohortMembersSearchDto) {} - public async getCohortMembers(cohortMemberId, fieldvalue) {} + public async searchCohortMembers(cohortMembersSearchDto, tenantId, res) {} + public async getCohortMembers(cohortMemberId, tenantId, fieldvalue, res) {} public async updateCohortMembers( cohortMembershipId: string, request: any, diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index da7ef909..8e40a6c6 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -9,7 +9,7 @@ import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; import { CohortDto } from "src/cohort/dto/cohort.dto"; -import APIResponse from "src/utils/response"; + import { HttpStatus } from "@nestjs/common"; import response from "src/utils/response"; import { User } from "src/user/entities/user-entity"; @@ -19,6 +19,8 @@ import { Fields } from "src/fields/entities/fields.entity"; import { UUID } from "typeorm/driver/mongodb/bson.typings"; import { isUUID } from "class-validator"; import { Cohort } from "src/cohort/entities/cohort.entity"; +import APIResponse from "src/common/responses/response"; +import { Response } from "express"; @Injectable() export class PostgresCohortMembersService { constructor( @@ -32,13 +34,31 @@ export class PostgresCohortMembersService { private cohortRepository: Repository ) { } - async getCohortMembers(cohortId: any, fieldvalue: any) { + async getCohortMembers(cohortId: any, tenantId: any, fieldvalue: any, res: Response) { + const apiId = 'api.get.cohortMembers'; try { + const fieldvalues = fieldvalue.toLowerCase() + + if (!tenantId) { + APIResponse.error(res, apiId, "BAD_REQUEST", `TenantId required`, String(HttpStatus.BAD_REQUEST)); + } + if (!isUUID(cohortId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid (UUID)", - }); + APIResponse.error(res, apiId, "BAD_REQUEST", "Invalid input: CohortId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); + } + + if (!isUUID(tenantId)) { + APIResponse.error(res, apiId, "Bad Request", "Invalid input: TenantId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); + } + + const cohortTenantMap = await this.cohortRepository.find({ + where: { + cohortId: cohortId, + tenantId: tenantId + } + }) + if (!cohortTenantMap) { + APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort not found for the provided tenant.", String(HttpStatus.NOT_FOUND)); } const userDetails = await this.findcohortData(cohortId); if (userDetails === true) { @@ -49,25 +69,16 @@ export class PostgresCohortMembersService { let cohortDetails = await this.getUserDetails( cohortId, "cohortId", - fieldvalue + fieldvalues ); results.userDetails.push(cohortDetails); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: results, - }); + + APIResponse.success(res, apiId, results, String(HttpStatus.OK), "Cohort members details fetched successfully."); } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Cohort Member not exist", - }); + APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort Member not exist.", String(HttpStatus.NOT_FOUND)); } } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + APIResponse.error(res, apiId, "Internal Server Error", `Error is: ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } async getUserDetails(searchId: any, searchKey: any, fieldShowHide: any) { @@ -88,12 +99,12 @@ export class PostgresCohortMembersService { mobile: data?.mobile }; - if (fieldShowHide === "false") { - results.userDetails.push(userDetails); - } else { + if (fieldShowHide === "true") { const fieldValues = await this.getFieldandFieldValues(data.userId); userDetails['customField'] = fieldValues; results.userDetails.push(userDetails); + } else { + results.userDetails.push(userDetails); } } @@ -144,7 +155,7 @@ export class PostgresCohortMembersService { } else { whereCase = `where CM."userId" =$1`; } - let query = `SELECT U."userId", U.username, U.name, U.role, U.district, U.state,U.mobile FROM public."CohortMembers" CM + let query = `SELECT U."userId", U.username, U.name, U.district, U.state,U.mobile FROM public."CohortMembers" CM LEFT JOIN public."Users" U ON CM."userId" = U."userId" ${whereCase}`; @@ -153,9 +164,16 @@ export class PostgresCohortMembersService { } public async searchCohortMembers( - cohortMembersSearchDto: CohortMembersSearchDto + cohortMembersSearchDto: CohortMembersSearchDto, + tenantId: string, + res: Response ) { + const apiId = 'api.post.searchCohortMembers'; try { + if (!isUUID(tenantId)) { + APIResponse.error(res, apiId, "Bad Request", "Invalid input: TenantId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); + } + let { limit, page, filters } = cohortMembersSearchDto; let offset = 0; if (page > 1) { @@ -171,16 +189,10 @@ export class PostgresCohortMembersService { // Validate cohortId and userId format if (whereClause["cohortId"] && !isUUID(whereClause["cohortId"])) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter a valid UUID for cohortId", - }); + APIResponse.error(res, apiId, "Bad Request", "Invalid input: CohortId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); } if (whereClause["userId"] && !isUUID(whereClause["userId"])) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter a valid UUID for userId", - }); + APIResponse.error(res, apiId, "Bad Request", "Invalid input: UserId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); } // Check if cohortId exists if (whereClause["cohortId"]) { @@ -188,10 +200,7 @@ export class PostgresCohortMembersService { where: { cohortId: whereClause["cohortId"] }, }); if (!cohortExists) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Cohort Member with specified cohortId not found", - }); + APIResponse.error(res, apiId, "Not Found", "Invalid input: No member found for this cohortId.", String(HttpStatus.NOT_FOUND)); } } @@ -201,38 +210,35 @@ export class PostgresCohortMembersService { where: { userId: whereClause["userId"] }, }); if (!userExists) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Cohort Member with specified userId not found", - }); + APIResponse.error(res, apiId, "Not Found", "Invalid input: No member found for this userId and cohort combination.", String(HttpStatus.NOT_FOUND)); } } // console.log("USER DATA ",userData) let results = {}; - let where = []; - if (whereClause["cohortId"]) { - where.push(["cohortId", whereClause["cohortId"]]); - } - if (whereClause["userId"]) { - where.push(["userId", whereClause["userId"]]); - } - if (whereClause["role"]) { - where.push(["role", whereClause["role"]]); - } - let options = []; - if (limit) { - options.push(['limit',limit]); - } - if (offset) { - options.push(['offset',offset]); - } - - results = await this.getCohortMemberUserDetails( - where, - "true", - options - ); + let where = []; + if (whereClause["cohortId"]) { + where.push(["cohortId", whereClause["cohortId"]]); + } + if (whereClause["userId"]) { + where.push(["userId", whereClause["userId"]]); + } + if (whereClause["role"]) { + where.push(["role", whereClause["role"]]); + } + let options = []; + if (limit) { + options.push(['limit', limit]); + } + if (offset) { + options.push(['offset', offset]); + } + + results = await this.getCohortMemberUserDetails( + where, + "true", + options + ); return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -269,7 +275,7 @@ export class PostgresCohortMembersService { if (fieldShowHide === "false") { results.userDetails.push(userDetails); } else { - const fieldValues = await this.getFieldandFieldValues(data.userId); + const fieldValues = await this.getFieldandFieldValues(data.userId); userDetails['customField'] = fieldValues; results.userDetails.push(userDetails); } @@ -290,14 +296,14 @@ export class PostgresCohortMembersService { await this.validateEntity(this.cohortRepository, { cohortId: cohortMembers.cohortId }, `Cohort Id does not exist.`); await this.validateEntity(this.usersRepository, { userId: cohortMembers.userId }, `User Id does not exist.`); - + const existrole = await this.cohortMembersRepository.find({ - where:{ + where: { userId: cohortMembers.userId, cohortId: cohortMembers.cohortId } }) - if(existrole.length>0){ + if (existrole.length > 0) { throw new ErrorResponseTypeOrm({ statusCode: HttpStatus.CONFLICT, errorMessage: `This user '${cohortMembers.userId}' already assign for this cohort '${cohortMembers.cohortId}'.`, @@ -333,26 +339,26 @@ export class PostgresCohortMembersService { let isRoleCondition = 0; if (where.length > 0) { whereCase = `where `; - where.forEach((value,index) => { - if(value[0]=="role") { - isRoleCondition=1; + where.forEach((value, index) => { + if (value[0] == "role") { + isRoleCondition = 1; whereCase += `R."name"='${value[1]}' `; } else { whereCase += `CM."${value[0]}"='${value[1]}' `; } - if(index != (where.length-1)) { + if (index != (where.length - 1)) { whereCase += ` AND ` } }) } if (options.length > 0) { - options.forEach((value,index) => { + options.forEach((value, index) => { optionsCase = `${value[0]} ${value[1]} `; }) } - if(isRoleCondition == 0) { + if (isRoleCondition == 0) { query = `SELECT U."userId", U.username, U.name, R.name AS role, U.district, U.state,U.mobile FROM public."CohortMembers" CM INNER JOIN public."Users" U ON CM."userId" = U."userId" @@ -372,7 +378,7 @@ export class PostgresCohortMembersService { } let result = await this.usersRepository.query(query); return result; - + } async validateEntity(repository, whereCondition, errorMessage) { diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index 233a1b20..caba9508 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -96,13 +96,10 @@ export class CohortMembersController { @Res() response: Response, @Query("fieldvalue") fieldvalue: string | null = null ) { - let tenantid = headers["tenantid"]; - + const tenantId = headers["tenantid"]; const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() - .getCohortMembers(cohortId, fieldvalue); - - return response.status(result.statusCode).json(result); + .getCohortMembers(cohortId,tenantId, fieldvalue, response); } // search; @@ -124,11 +121,11 @@ export class CohortMembersController { @Res() response: Response, @Body() cohortMembersSearchDto: CohortMembersSearchDto ) { - let tenantid = headers["tenantid"]; + const tenantId = headers["tenantid"]; const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() - .searchCohortMembers(cohortMembersSearchDto); + .searchCohortMembers(cohortMembersSearchDto, tenantId, response); return response.status(result.statusCode).json(result); } diff --git a/src/common/responses/response-interface.ts b/src/common/responses/response-interface.ts new file mode 100644 index 00000000..1e5a8e74 --- /dev/null +++ b/src/common/responses/response-interface.ts @@ -0,0 +1,34 @@ +import { IsOptional } from "class-validator"; + +// structure for server responses +export interface ServerResponse { + // api id + id: string; + + // response param + params: Params; + + // response code + responseCode: string; + + //server result + result: any; + + // time stamp + ts: string; + + // api version + ver: string; + + headers?: any; + + response:any; +} + +export interface Params { + resmsgid: string; + err?: any; + status: string; + errmsg?: any; + successmessage?: string; +} diff --git a/src/common/responses/response.ts b/src/common/responses/response.ts new file mode 100644 index 00000000..d0470034 --- /dev/null +++ b/src/common/responses/response.ts @@ -0,0 +1,64 @@ +import { v4 } from 'uuid'; +import { Params } from './response-interface'; +import { Response } from 'express'; + +export default class APIResponse { + public static success( + response:Response, + id: string, + result: Type, + statusCode: string, + successmessage:string + ) { + try { + const params: Params = { + resmsgid: v4(), + status: 'successful', + err: null, + errmsg: null, + successmessage: successmessage + }; + + const resObj= { + id, + ver: '1.0', + ts: new Date().toISOString(), + params, + responseCode: statusCode, + result, + }; + return response.status(Number(statusCode)).json(resObj); + } catch (e) { + return e; + } + } + + public static error( + response: Response, + id: string, + errmsg: string, + error: string, + statusCode: string, + ) { + try { + const params: Params = { + resmsgid: v4(), + status: 'failed', + err: error, + errmsg: errmsg, + }; + + const resObj = { + id, + ver: '1.0', + ts: new Date().toISOString(), + params, + responseCode: statusCode, + result: { }, + }; + return response.status(Number(statusCode)).json(resObj); + } catch (e) { + return e; + } + } +} From 46e9a56cc0d50607e6160292133d800e0c8ccf7f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 28 May 2024 11:15:05 +0530 Subject: [PATCH 354/408] add --- src/adapters/postgres/user-adapter.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 5e429d16..6063b7b9 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -344,19 +344,26 @@ export class PostgresUserService { async updateUser(userDto, response) { try { + console.log("hiii1"); let updatedData = {}; + console.log("hiii2"); let errorMessage; + console.log("hiii3"); if (userDto.userData || Object.keys(userDto.userData).length > 0) { + console.log("hiii"); + await this.updateBasicUserDetails(userDto.userId, userDto.userData); updatedData['basicDetails'] = userDto.userData; } + console.log("hii"); + if (userDto?.customFields?.length > 0) { const getFieldsAttributesQuery = ` SELECT * FROM "public"."Fields" - WHERE "contextType"='STUDENT' AND "fieldAttributes"->>'isEditable' = $1 + WHERE "fieldAttributes"->>'isEditable' = $1 `; const getFieldsAttributesParams = ['true']; const getFieldsAttributes = await this.fieldsRepository.query(getFieldsAttributesQuery, getFieldsAttributesParams); @@ -365,7 +372,7 @@ export class PostgresUserService { for (let fieldDetails of getFieldsAttributes) { isEditableFieldId.push(fieldDetails.fieldId); } - + console.log("hi"); // let errorMessage = []; let unEditableIdes = []; for (let data of userDto.customFields) { @@ -408,6 +415,7 @@ export class PostgresUserService { return this.usersRepository.save(user); } + async updateCustomFields(itemId, data) { let result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); let newResult; From 44140b9bdc2ab295f71b04f27cc3ee2d182fe831 Mon Sep 17 00:00:00 2001 From: poojakarma Date: Tue, 28 May 2024 13:24:29 +0530 Subject: [PATCH 355/408] Changed role APIs responses --- src/adapters/postgres/rbac/role-adapter.ts | 312 ++++++++++----------- src/adapters/rbacservicelocator.ts | 10 +- src/common/responses/response-interface.ts | 34 +++ src/common/responses/response.ts | 64 +++++ src/main.ts | 2 +- src/rbac/role/role.controller.ts | 30 +- 6 files changed, 259 insertions(+), 193 deletions(-) create mode 100644 src/common/responses/response-interface.ts create mode 100644 src/common/responses/response.ts diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index f07fa4ed..4cb4dd2e 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -14,6 +14,8 @@ import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; import { Privilege } from "src/rbac/privilege/entities/privilege.entity"; import { isUUID } from "class-validator"; +import APIResponse from "src/common/responses/response"; +import { Response } from 'express'; @Injectable() export class PostgresRoleService { @@ -24,105 +26,88 @@ export class PostgresRoleService { private readonly userRoleMappingRepository: Repository, @InjectRepository(RolePrivilegeMapping) private readonly roleprivilegeMappingRepository: Repository - ) {} -public async createRole(request: any, createRolesDto: CreateRolesDto) { - - const tenant = await this.checkTenantID(createRolesDto.tenantId) - if (!tenant) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter valid tenantId", - }); - } - const roles = []; - const errors = [] - try { - - // Convert role name to lowercase - for (const roleDto of createRolesDto.roles) { - const tenantId = createRolesDto.tenantId; - const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); - - // Check if role name already exists - const existingRole = await this.roleRepository.findOne({ where: { code:code,tenantId:tenantId } }) - if (existingRole) { - errors.push({ - errorMessage: `Combination of this tenantId and the code '${code}' already exists.`, - }); - continue; - } + ) { } + public async createRole(request: any, createRolesDto: CreateRolesDto, response: Response) { + const apiId = 'api.create.role' + const tenant = await this.checkTenantID(createRolesDto.tenantId) + if (!tenant) { + APIResponse.error( + response, + apiId, + `Please enter valid tenantId`, + 'Invalid Tenant Id', + String(HttpStatus.BAD_REQUEST) + ) + } + const roles = []; + const errors = [] + try { - const newRoleDto = new RoleDto({ - ...roleDto, - code, - createdAt: new Date(), - updatedAt: new Date(), - createdBy: request.user.userId, // Assuming you have a user object in the request - updatedBy: request.user.userId, - tenantId, // Add the tenantId to the RoleDto - }); - // Convert roleDto to lowercase - // const response = await this.roleRepository.save(roleDto); - const roleEntity = this.roleRepository.create(newRoleDto); + // Convert role name to lowercase + for (const roleDto of createRolesDto.roles) { + const tenantId = createRolesDto.tenantId; + const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); - // Save the role entity to the database - const response = await this.roleRepository.save(roleEntity); - roles.push(new RolesResponseDto(response)); - } - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + // Check if role name already exists + const existingRole = await this.roleRepository.findOne({ where: { code: code, tenantId: tenantId } }) + if (existingRole) { + errors.push({ + errorMessage: `Combination of this tenantId and the code '${code}' already exists.`, + }); + continue; } - return { - statusCode: HttpStatus.OK, - successCount: roles.length, - errorCount: errors.length, - roles, - errors, - }; + const newRoleDto = new RoleDto({ + ...roleDto, + code, + createdAt: new Date(), + updatedAt: new Date(), + createdBy: request.user.userId, // Assuming you have a user object in the request + updatedBy: request.user.userId, + tenantId, // Add the tenantId to the RoleDto + }); + // Convert roleDto to lowercase + // const response = await this.roleRepository.save(roleDto); + const roleEntity = this.roleRepository.create(newRoleDto); + + // Save the role entity to the database + const response = await this.roleRepository.save(roleEntity); + roles.push(new RolesResponseDto(response)); + } + } catch (e) { + APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } + APIResponse.success(response, apiId, { successCount: roles.length, errorCount: errors.length, roles, errors }, + String(HttpStatus.OK), 'Role successfully Created') + } - public async getRole(roleId: string, request: any) { + public async getRole(roleId: string, request: any, response: Response) { + const apiId = 'api.get.role'; try { - const [results, totalCount] = await this.roleRepository.findAndCount({ + const [roles, totalCount] = await this.roleRepository.findAndCount({ where: { roleId }, }); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - totalCount, - data: results, - }); + APIResponse.success(response, apiId, { roles, totalCount }, String(HttpStatus.OK), 'Roles fetched successfully') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } - public async updateRole(roleId: string, request: any, roleDto: RoleDto) { + public async updateRole(roleId: string, request: any, roleDto: RoleDto, response: Response) { + const apiId = 'api.update.role'; try { - const response = await this.roleRepository.update(roleId, roleDto); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: { - rowCount: response.affected, - }, - }); + + const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); + roleDto.code = code; + const result = await this.roleRepository.update(roleId, roleDto); + APIResponse.success(response, apiId, { rowCount: result.affected, }, String(HttpStatus.OK), 'Roles Updated successful') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } - public async searchRole(roleSearchDto: RoleSearchDto) { + public async searchRole(roleSearchDto: RoleSearchDto, response: Response) { + const apiId = 'api.search.Role'; try { let { limit, page, filters } = roleSearchDto; @@ -141,93 +126,85 @@ public async createRole(request: any, createRolesDto: CreateRolesDto) { whereClause[key] = value; }); } - if (whereClause.userId && !whereClause.tenantId ) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter Tenenat id or Valid Filter", - }); + if (whereClause.userId && !whereClause.tenantId) { + APIResponse.error( + response, + apiId, + `Please Enter Tenenat id or Valid Filter`, + 'Invalid Tenant Id or Valid Filter', + String(HttpStatus.BAD_REQUEST) + ) } if (whereClause.field && !["Privilege"].includes(whereClause?.field)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Invalid field value.", - }); - } - if (whereClause.userId && whereClause.tenantId && whereClause.field==="Privilege") { - const userRoleMappingData = await this.findUserRoleData(whereClause.userId, whereClause.tenantId); - const roleIds = userRoleMappingData.map(data => data.roleid); - - const result = await this.findPrivilegeByRoleId(roleIds); - - const roles = userRoleMappingData.map(data => { + APIResponse.error( + response, + apiId, + `Please Enter valid field value.`, + 'Invalid field value.', + String(HttpStatus.BAD_REQUEST) + ) + } + if (whereClause.userId && whereClause.tenantId && whereClause.field === "Privilege") { + const userRoleMappingData = await this.findUserRoleData(whereClause.userId, whereClause.tenantId); + const roleIds = userRoleMappingData.map(data => data.roleid); + + const result = await this.findPrivilegeByRoleId(roleIds); + + const roles = userRoleMappingData.map(data => { const roleResult = result.find(privilegeData => privilegeData.roleid === data.roleid); return { roleId: data.roleid, title: data.title, code: data.code, privileges: roleResult ? roleResult : [] - }; - }); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Role For User with Privileges fetched successfully.", - data: roles, - }); - - }else if(whereClause.userId && whereClause.tenantId && !whereClause.field){ - const data = await this.findUserRoleData(whereClause.userId,whereClause.tenantId) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Role For User Id fetched successfully.", - data: data, + }; }); - } - else if (whereClause.tenantId && whereClause.field === "Privilege") { + APIResponse.success(response, apiId, roles, String(HttpStatus.OK), 'Role For User with Privileges fetched successfully.') + } else if (whereClause.userId && whereClause.tenantId && !whereClause.field) { + const data = await this.findUserRoleData(whereClause.userId, whereClause.tenantId) + APIResponse.success(response, apiId, data, String(HttpStatus.OK), 'Role For User Id fetched successfully.') + } + else if (whereClause.tenantId && whereClause.field === "Privilege") { const userRoleData = await this.findRoleData(whereClause.tenantId); const result = await this.findPrivilegeByRoleId(userRoleData.map(data => data.roleId)); const roles = userRoleData.map(data => { const roleResult = result.find(privilegeData => privilegeData.roleid === data.roleId); return { - roleId: data.roleId, - title: data.title, - code: data.code, - privileges: roleResult ? roleResult : [] + roleId: data.roleId, + title: data.title, + code: data.code, + privileges: roleResult ? roleResult : [] }; - }); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Role For Tenant with Privileges fetched successfully.", - data: roles, }); - } else if (whereClause.tenantId && !whereClause.field) { + APIResponse.success(response, apiId, roles, String(HttpStatus.OK), 'Role For Tenant with Privileges fetched successfully.') + } else if (whereClause.tenantId && !whereClause.field) { const data = await this.findRoleData(whereClause.tenantId); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Role For Tenant fetched successfully.", - data: data, - }); - }else { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: "Please Enter Valid Filter", - }); - }} catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + APIResponse.success(response, apiId, data, String(HttpStatus.OK), 'Role For Tenant fetched successfully.') + } else { + APIResponse.error( + response, + apiId, + `Please Enter Valid Filter`, + 'Invalid Filter', + String(HttpStatus.BAD_REQUEST) + ) + } + } catch (e) { + APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } - public async deleteRole(roleId: string) { + public async deleteRole(roleId: string, res: Response) { + const apiId = 'api.delete.role'; try { if (!isUUID(roleId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid (UUID)", - }); + APIResponse.error( + res, + apiId, + `Please Enter valid (UUID)`, + 'Invalid UUID', + String(HttpStatus.BAD_REQUEST) + ) } const roleToDelete = await this.roleRepository.findOne({ @@ -235,10 +212,13 @@ public async createRole(request: any, createRolesDto: CreateRolesDto) { }); if (!roleToDelete) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Role not found", - }); + APIResponse.error( + res, + apiId, + `Role not found`, + 'Not found', + String(HttpStatus.NOT_FOUND) + ) } // Delete the role const response = await this.roleRepository.delete(roleId); @@ -253,21 +233,13 @@ public async createRole(request: any, createRolesDto: CreateRolesDto) { await this.userRoleMappingRepository.delete({ roleId: roleId, }); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Role deleted successfully.", - data: { - rowCount: response.affected, - }, - }); + APIResponse.success(res, apiId, { rowCount: response.affected }, String(HttpStatus.OK), 'Role deleted successfully.') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: "Internal server error", // Access the error message - }); + APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } + + public async findRoleData(id: string) { const data = await this.roleRepository.find({ where: { @@ -278,14 +250,14 @@ public async createRole(request: any, createRolesDto: CreateRolesDto) { return data; } - public async findUserRoleData(userId: string,tenantId: string){ + public async findUserRoleData(userId: string, tenantId: string) { let userRoleData = await this.userRoleMappingRepository.createQueryBuilder('urp'). - innerJoin(Role,'r','r.roleId=urp.roleId'). - select(['urp.roleId as roleid','r.title as title','r.code as code']). - where("urp.userId= :userId",{userId}). - andWhere("urp.tenantId=:tenantId",{tenantId}) - .getRawMany() - return userRoleData; + innerJoin(Role, 'r', 'r.roleId=urp.roleId'). + select(['urp.roleId as roleid', 'r.title as title', 'r.code as code']). + where("urp.userId= :userId", { userId }). + andWhere("urp.tenantId=:tenantId", { tenantId }) + .getRawMany() + return userRoleData; } public async findPrivilegeByRoleId(roleIds: string[]) { @@ -301,7 +273,7 @@ public async createRole(request: any, createRolesDto: CreateRolesDto) { .where("rpm.roleId IN (:...roleIds)", { roleIds }) .getRawMany(); return privileges; -} + } public async checkTenantID(tenantId) { try { diff --git a/src/adapters/rbacservicelocator.ts b/src/adapters/rbacservicelocator.ts index 8f5c02fc..4860642d 100644 --- a/src/adapters/rbacservicelocator.ts +++ b/src/adapters/rbacservicelocator.ts @@ -1,13 +1,15 @@ import { RoleSearchDto } from "../rbac/role/dto/role-search.dto"; import { CreateRolesDto, RoleDto } from "../rbac/role/dto/role.dto"; +import { Response } from "express"; export interface IServicelocatorRbac { getRole( roleId?: string, request?: any, + response?: Response ); - updateRole(id?: string, request?: any, userDto?: any); - createRole(request: any, createRolesDto: CreateRolesDto); - searchRole(roleSearchDto: RoleSearchDto); - deleteRole(roleId); + updateRole(id?: string, request?: any, userDto?: any, response?: Response); + createRole(request: any, createRolesDto: CreateRolesDto, response?: Response); + searchRole(roleSearchDto: RoleSearchDto, response: Response); + deleteRole(roleId?: string, response?: Response); } diff --git a/src/common/responses/response-interface.ts b/src/common/responses/response-interface.ts new file mode 100644 index 00000000..86394aa1 --- /dev/null +++ b/src/common/responses/response-interface.ts @@ -0,0 +1,34 @@ +import { IsOptional } from "class-validator"; + +// structure for server responses +export interface ServerResponse { + // api id + id: string; + + // response param + params: Params; + + // response code + responseCode: string; + + //server result + result: any; + + // time stamp + ts: string; + + // api version + ver: string; + + headers?: any; + + response: any; +} + +export interface Params { + resmsgid: string; + err?: any; + status: string; + errmsg?: any; + successmessage?: string; +} diff --git a/src/common/responses/response.ts b/src/common/responses/response.ts new file mode 100644 index 00000000..cf50feef --- /dev/null +++ b/src/common/responses/response.ts @@ -0,0 +1,64 @@ +import { v4 } from 'uuid'; +import { Params } from './response-interface'; +import { Response } from 'express'; + +export default class APIResponse { + public static success( + response: Response, + id: string, + result: Type, + statusCode: string, + successmessage: string + ) { + try { + const params: Params = { + resmsgid: v4(), + status: 'successful', + err: null, + errmsg: null, + successmessage: successmessage + }; + + const resObj = { + id, + ver: '1.0', + ts: new Date().toISOString(), + params, + responseCode: statusCode, + result, + }; + return response.status(Number(statusCode)).json(resObj); + } catch (e) { + return e; + } + } + + public static error( + response: Response, + id: string, + errmsg: string, + error: string, + statusCode: string, + ) { + try { + const params: Params = { + resmsgid: v4(), + status: 'failed', + err: error, + errmsg: errmsg, + }; + + const resObj = { + id, + ver: '1.0', + ts: new Date().toISOString(), + params, + responseCode: statusCode, + result: {}, + }; + return response.status(Number(statusCode)).json(resObj); + } catch (e) { + return e; + } + } +} diff --git a/src/main.ts b/src/main.ts index 994a3676..7af92618 100644 --- a/src/main.ts +++ b/src/main.ts @@ -41,7 +41,7 @@ async function bootstrap() { process.env.IMAGEPATH, express.static(join(__dirname, "..", "uploads")) ); - app.setGlobalPrefix("api/v1", { + app.setGlobalPrefix("user/v1", { exclude: [{ path: "health", method: RequestMethod.GET }], }); diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index faf553cf..10444ca3 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -28,31 +28,29 @@ import { import { Request } from "@nestjs/common"; import { CreateRolesDto, RoleDto } from "./dto/role.dto"; import { RoleSearchDto } from "./dto/role-search.dto"; -import { Response, response } from "express"; +import { Response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { RoleAdapter } from "./roleadapter" - @ApiTags("rbac") @Controller("rbac/roles") @UseGuards(JwtAuthGuard) export class RoleController { - constructor(private readonly roleAdapter:RoleAdapter) { } + constructor(private readonly roleAdapter: RoleAdapter) { } //Get role - @Get("/:id") + @Get("read/:id") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Role Detail." }) @ApiHeader({ name: "tenantid" }) @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({strategy: "excludeAll",}) + @SerializeOptions({ strategy: "excludeAll", }) public async getRole( @Param("id") roleId: string, @Req() request: Request, @Res() response: Response ) { - const result = await this.roleAdapter.buildRbacAdapter().getRole(roleId, request); - return response.status(result.statusCode).json(result); + await this.roleAdapter.buildRbacAdapter().getRole(roleId, request, response); } //Create role @@ -68,12 +66,11 @@ export class RoleController { @Body() createRolesDto: CreateRolesDto, @Res() response: Response ) { - const result = await this.roleAdapter.buildRbacAdapter().createRole(request, createRolesDto); - return response.status(result.statusCode).json(result); + await this.roleAdapter.buildRbacAdapter().createRole(request, createRolesDto, response); } //Update Role - @Put("/:id") + @Put("update/:id") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role updated successfully." }) @ApiBody({ type: RoleDto }) @@ -85,12 +82,11 @@ export class RoleController { @Body() roleDto: RoleDto, @Res() response: Response ) { - const result = await this.roleAdapter.buildRbacAdapter().updateRole(roleId, request, roleDto); - return response.status(result.statusCode).json(result); + await this.roleAdapter.buildRbacAdapter().updateRole(roleId, request, roleDto, response) } // search Role - @Post("/list-roles") + @Post("list/roles") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role List." }) @ApiBody({ type: RoleSearchDto }) @@ -105,12 +101,11 @@ export class RoleController { @Res() response: Response ) { // let tenantid = headers["tenantid"]; - const result = await this.roleAdapter.buildRbacAdapter().searchRole(roleSearchDto); - return response.status(result.statusCode).json(result); + await this.roleAdapter.buildRbacAdapter().searchRole(roleSearchDto, response); } //delete role - @Delete("/:roleId") + @Delete("delete/:roleId") @ApiBasicAuth("access-token") @ApiHeader({ name: "tenantid" }) @ApiOkResponse({ description: "Role deleted successfully." }) @@ -120,7 +115,6 @@ export class RoleController { @Param("roleId") roleId: string, @Res() response: Response ) { - const result = await this.roleAdapter.buildRbacAdapter().deleteRole(roleId); - return response.status(result.statusCode).json(result); + await this.roleAdapter.buildRbacAdapter().deleteRole(roleId, response); } } From 2ccfe8022c928a0ca1ea07f5765fe82b32caf377 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 28 May 2024 16:33:03 +0530 Subject: [PATCH 356/408] Field Vaue: Required field value in array format --- src/adapters/postgres/user-adapter.ts | 216 +++++++++++++++----------- 1 file changed, 125 insertions(+), 91 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 23af55ac..e5f86bf9 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -110,48 +110,67 @@ export class PostgresUserService { message: 'Please Enter Valid UUID', }); } + const checkExistUser = await this.usersRepository.find({ + where: { + userId: userData.userId + } + }) + + if (checkExistUser.length == 0) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: `User Id '${userData.userId}' does not exist.`, + }); + } + const result = { userData: { } }; - let filledValues:any; + let filledValues: any; let customFieldsArray = []; let [userDetails, userRole] = await Promise.all([ this.findUserDetails(userData.userId), - this.findUserRoles(userData.userId,userData.tenantId) + this.findUserRoles(userData.userId, userData.tenantId) ]); const roleInUpper = (userRole.title).toUpperCase(); - if(userData?.fieldValue){ - filledValues = await this.findFilledValues(userData.userId,roleInUpper) + + if (userData?.fieldValue) { + filledValues = await this.findFilledValues(userData.userId, roleInUpper) } - if(userRole){ + if (userRole) { userDetails['role'] = userRole.title; } + if (!userDetails) { return new SuccessResponse({ statusCode: HttpStatus.NOT_FOUND, message: 'User Not Found', }); - } + } if (!userData.fieldValue) { return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', data: userDetails, }); - } - const customFields = await this.findCustomFields(userData,roleInUpper) + } + + const customFields = await this.findCustomFields(userData, roleInUpper) + result.userData = userDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); + for (let data of customFields) { - let fieldValue:any = filledValuesMap.get(data.fieldId); - // if(data.type === 'checkbox' && fieldValue){ - // console.log("Hi",fieldValue); - // fieldValue=fieldValue.split(',') - // } + let fieldValue: any = filledValuesMap.get(data.fieldId); + + if (fieldValue) { + fieldValue = fieldValue.split(',') + } + const customField = { fieldId: data.fieldId, label: data.label, @@ -164,7 +183,7 @@ export class PostgresUserService { }; customFieldsArray.push(customField); } - + result.userData['customFields'] = customFieldsArray; return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -273,24 +292,25 @@ export class PostgresUserService { return result } - async findUserRoles(userId:string, tenantId:string) { - + async findUserRoles(userId: string, tenantId: string) { + console.log(userId, tenantId); + const getRole = await this.userRoleMappingRepository.findOne({ - where:{ - userId:userId, - tenantId:tenantId + where: { + userId: userId, + tenantId: tenantId } }) - if(!getRole) { + if (!getRole) { return false; } let role; role = await this.roleRepository.findOne({ - where:{ - roleId:getRole.roleId, - }, - select: ["title"] - }) + where: { + roleId: getRole.roleId, + }, + select: ["title"] + }) return role } @@ -304,7 +324,7 @@ export class PostgresUserService { where: whereClause, select: ["userId", "username", "name", "district", "state", "mobile"] }) - if(!userDetails){ + if (!userDetails) { return false; } const tenentDetails = await this.allUsersTenent(userDetails.userId) @@ -328,6 +348,8 @@ export class PostgresUserService { contextType: role, } }) + console.log("customFields", customFields); + return customFields; } @@ -339,7 +361,7 @@ export class PostgresUserService { ON F."fieldId" = FV."fieldId" where U."userId" =$1 AND F."contextType" = $2`; - let result = await this.usersRepository.query(query, [userId,role]); + let result = await this.usersRepository.query(query, [userId, role]); return result; } @@ -347,7 +369,8 @@ export class PostgresUserService { try { let updatedData = {}; let errorMessage; - if (userDto.userData || Object.keys(userDto.userData).length > 0) { + + if (userDto.userData) { await this.updateBasicUserDetails(userDto.userId, userDto.userData); updatedData['basicDetails'] = userDto.userData; } @@ -357,7 +380,7 @@ export class PostgresUserService { const getFieldsAttributesQuery = ` SELECT * FROM "public"."Fields" - WHERE "contextType"='STUDENT' AND "fieldAttributes"->>'isEditable' = $1 + WHERE "fieldAttributes"->>'isEditable' = $1 `; const getFieldsAttributesParams = ['true']; const getFieldsAttributes = await this.fieldsRepository.query(getFieldsAttributesQuery, getFieldsAttributesParams); @@ -409,7 +432,17 @@ export class PostgresUserService { return this.usersRepository.save(user); } + async updateCustomFields(itemId, data) { + + if (Array.isArray(data.value) === true) { + let dataArray = []; + for (let value of data.value) { + dataArray.push(value.toLowerCase().replace(/ /g, '_')); + } + data.value = dataArray.join(', '); + } + let result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); let newResult; if (result.affected === 0) { @@ -434,7 +467,7 @@ export class PostgresUserService { if (userCreateDto.fieldValues) { let field_values = userCreateDto.fieldValues; const validateField = await this.validateFieldValues(field_values); - + if (validateField == false) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.CONFLICT, @@ -443,7 +476,7 @@ export class PostgresUserService { } } - + // check and validate all fields let validateBodyFields = await this.validateBodyFields(userCreateDto) @@ -499,7 +532,7 @@ export class PostgresUserService { } } } - + return new SuccessResponse({ statusCode: 200, message: "User has been created successfully.", @@ -553,19 +586,19 @@ export class PostgresUserService { return true; } - async checkUser(body){ + async checkUser(body) { let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(body); - if(checkUserinKeyCloakandDb){ + if (checkUserinKeyCloakandDb) { return new SuccessResponse({ statusCode: 200, message: "User Exists. Proceed with Sending Email ", - data: {data:true}, + data: { data: true }, }); } return new SuccessResponse({ statusCode: HttpStatus.BAD_REQUEST, message: "Invalid Username Or Email", - data: {data:false}, + data: { data: false }, }); } @@ -573,7 +606,7 @@ export class PostgresUserService { async checkUserinKeyCloakandDb(userDto) { const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - if(userDto?.username){ + if (userDto?.username) { const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( userDto?.username, token @@ -582,7 +615,7 @@ export class PostgresUserService { return usernameExistsInKeycloak; } return false; - }else{ + } else { const usernameExistsInKeycloak = await checkIfEmailExistsInKeycloak( userDto?.email, token @@ -592,8 +625,8 @@ export class PostgresUserService { } return false; } -} - + } + async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { const user = new User() @@ -601,7 +634,7 @@ export class PostgresUserService { user.name = userCreateDto?.name user.email = userCreateDto?.email user.mobile = Number(userCreateDto?.mobile) || null, - user.createdBy = userCreateDto?.createdBy + user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, user.state = userCreateDto?.state, @@ -612,7 +645,7 @@ export class PostgresUserService { if (userCreateDto?.dob) { user.dob = new Date(userCreateDto.dob); } - + let result = await this.usersRepository.save(user); if (result) { @@ -809,65 +842,66 @@ export class PostgresUserService { }; } - public async deleteUserById(userId){ + public async deleteUserById(userId) { const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; - // Validate userId format - if (!isUUID(userId)) { + // Validate userId format + if (!isUUID(userId)) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter a valid UUID for userId", + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter a valid UUID for userId", }); - } - - try { - // Check if user exists in usersRepository - const user = await this.usersRepository.findOne({ where :{userId:userId}}); - if (!user) { + } + + try { + // Check if user exists in usersRepository + const user = await this.usersRepository.findOne({ where: { userId: userId } }); + if (!user) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User not found in user table.", + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User not found in user table.", }); - } - - - // Delete from User table - const userResult = await this.usersRepository.delete(userId); - - // Delete from CohortMembers table - const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); - - // Delete from UserTenantMapping table - const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); - - // Delete from UserRoleMapping table - const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); - + } + + + // Delete from User table + const userResult = await this.usersRepository.delete(userId); + + // Delete from CohortMembers table + const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); + + // Delete from UserTenantMapping table + const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); + + // Delete from UserRoleMapping table + const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); + // Delete from FieldValues table where ItemId matches userId - const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); - + const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); + const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - - await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { + + await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { headers: { - 'Authorization': `Bearer ${token}` - }}); - - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "User and related entries deleted Successfully.", - data: { - user: userResult - }, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } + 'Authorization': `Bearer ${token}` + } + }); + + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "User and related entries deleted Successfully.", + data: { + user: userResult + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } + } } From 1d7e3eedf51b7f1a360ab81064e5281d93f0f692 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Tue, 28 May 2024 18:55:13 +0530 Subject: [PATCH 357/408] feat: modified responses of user --- src/adapters/postgres/user-adapter.ts | 281 +++++++++++++++----------- src/adapters/userservicelocator.ts | 7 +- src/common/utils/api-id.config.ts | 8 + src/user/user.controller.ts | 45 ++--- 4 files changed, 194 insertions(+), 147 deletions(-) create mode 100644 src/common/utils/api-id.config.ts diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 5e429d16..4f7cf5b4 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -25,6 +25,9 @@ import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; import { CourseController } from 'src/course/course.controller'; import { UserData } from 'src/user/user.controller'; +import APIResponse from 'src/common/responses/response'; +import { Response } from 'express'; +import { APIID } from 'src/common/utils/api-id.config'; @Injectable() export class PostgresUserService { @@ -51,28 +54,35 @@ export class PostgresUserService { @InjectRepository(Role) private roleRepository: Repository, ) { } + async searchUser(tenantId: string, request: any, response: any, userSearchDto: UserSearchDto) { + const apiId = APIID.USER_LIST; try { let findData = await this.findAllUserDetails(userSearchDto); if (!findData.length) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: 'Either Filter is wrong or No Data Found For the User', - }); + // return new SuccessResponse({ + // statusCode: HttpStatus.BAD_REQUEST, + // message: 'Either Filter is wrong or No Data Found For the User', + // }); + return APIResponse.error(response, apiId, "Bad request", `Either Filter is wrong or No Data Found For the User`, String(HttpStatus.BAD_REQUEST)); } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: findData, - }); + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: 'Ok.', + // data: findData, + // }); + return await APIResponse.success(response, apiId, findData, + String(HttpStatus.OK), 'User List fetched.') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + console.log(e,"eer"); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -103,12 +113,14 @@ export class PostgresUserService { } async getUsersDetailsById(userData: UserData, response: any) { + const apiId = APIID.USER_GET; try { if (!isUUID(userData.userId)) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: 'Please Enter Valid UUID', - }); + // new SuccessResponse({ + // statusCode: HttpStatus.BAD_REQUEST, + // message: 'Please Enter Valid UUID', + // }); + return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID`, String(HttpStatus.BAD_REQUEST)); } const result = { userData: { @@ -122,6 +134,8 @@ export class PostgresUserService { this.findUserRoles(userData.userId,userData.tenantId) ]); + console.log(userRole,"uerrple"); + const roleInUpper = (userRole.title).toUpperCase(); if(userData?.fieldValue){ filledValues = await this.findFilledValues(userData.userId,roleInUpper) @@ -131,17 +145,20 @@ export class PostgresUserService { userDetails['role'] = userRole.title; } if (!userDetails) { - return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'User Not Found', - }); + // return new SuccessResponse({ + // statusCode: HttpStatus.NOT_FOUND, + // message: 'User Not Found', + // }); + return APIResponse.error(response, apiId, "Not Found", `User Not Found`, String(HttpStatus.NOT_FOUND)); } if (!userData.fieldValue) { - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: userDetails, - }); + // new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: 'Ok.', + // data: userDetails, + // }); + return await APIResponse.success(response, apiId, {userData: userDetails}, + String(HttpStatus.OK), 'User details Fetched Successfully.') } const customFields = await this.findCustomFields(userData,roleInUpper) result.userData = userDetails; @@ -165,17 +182,20 @@ export class PostgresUserService { } result.userData['customFields'] = customFieldsArray; - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'User details Fetched Successfully.', - data: result, - }); - + // new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: 'User details Fetched Successfully.', + // data: result, + // }); + return await APIResponse.success(response, apiId, {...result}, + String(HttpStatus.OK), 'User details Fetched Successfully.') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + console.log("err",e) + // new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -342,7 +362,8 @@ export class PostgresUserService { return result; } - async updateUser(userDto, response) { + async updateUser(userDto, response: Response) { + const apiId = APIID.USER_UPDATE; try { let updatedData = {}; let errorMessage; @@ -384,17 +405,20 @@ export class PostgresUserService { errorMessage = `Uneditable fields: ${unEditableIdes.join(', ')}` } } - return ({ - statusCode: 200, - message: "User has been updated successfully.", - data: updatedData, - error: errorMessage - }); + // return ({ + // statusCode: 200, + // message: "User has been updated successfully.", + // data: updatedData, + // error: errorMessage + // }); + return await APIResponse.success(response, apiId, updatedData, + String(HttpStatus.OK), "User has been updated successfully.") } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -422,7 +446,8 @@ export class PostgresUserService { return result; } - async createUser(request: any, userCreateDto: UserCreateDto) { + async createUser(request: any, userCreateDto: UserCreateDto, response: Response) { + const apiId = APIID.USER_CREATE; // It is considered that if user is not present in keycloak it is not present in database as well try { const decoded: any = jwt_decode(request.headers.authorization); @@ -435,13 +460,13 @@ export class PostgresUserService { const validateField = await this.validateFieldValues(field_values); if (validateField == false) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: "Duplicate fieldId found in fieldValues.", - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.CONFLICT, + // errorMessage: "Duplicate fieldId found in fieldValues.", + // }); + return APIResponse.error(response, apiId, "Conflict", `Duplicate fieldId found in fieldValues.`, String(HttpStatus.CONFLICT)); } } - // check and validate all fields let validateBodyFields = await this.validateBodyFields(userCreateDto) @@ -456,21 +481,22 @@ export class PostgresUserService { const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) - let checkUserinDb = await this.checkUserinKeyCloakandDb(userCreateDto.username); + // let checkUserinDb = await this.checkUserinKeyCloakandDb(userCreateDto.username); if (checkUserinKeyCloakandDb) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.FORBIDDEN, - errorMessage: "User Already Exist", - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.FORBIDDEN, + // errorMessage: "User Already Exist", + // }); + return APIResponse.error(response, apiId, "Forbidden", `User Already Exist`, String(HttpStatus.FORBIDDEN)); } resKeycloak = await createUserInKeyCloak(userSchema, token).catch( (error) => { errKeycloak = error.response?.data.errorMessage; - - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: error, + // }); + return APIResponse.error(response, apiId, "Internal Server Error",`${errKeycloak}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } ); userCreateDto.userId = resKeycloak; @@ -490,29 +516,33 @@ export class PostgresUserService { } let result = await this.updateCustomFields(userId, fieldData); if (!result) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: `Error is ${result}`, - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: `Error is ${result}`, + // }); + return APIResponse.error(response, apiId, "Internal Server Error",`Error is ${result}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } } } - return new SuccessResponse({ - statusCode: 200, - message: "User has been created successfully.", - data: result, - }); + // return new SuccessResponse({ + // statusCode: 200, + // message: "User has been created successfully.", + // data: result, + // }); + APIResponse.success(response, apiId, {userData: result}, + String(HttpStatus.CREATED), "User has been created successfully.") } } catch (e) { if (e instanceof ErrorResponseTypeOrm) { return e; } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.toString(), // or any custom error message you want - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e.toString(), // or any custom error message you want + // }); + return APIResponse.error(response, apiId, "Internal Server Error",`Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } } @@ -684,8 +714,10 @@ export class PostgresUserService { public async resetUserPassword( request: any, username: string, - newPassword: string + newPassword: string, + response: Response ) { + const apiId = APIID.USER_RESET_PASSWORD; try { const userData: any = await this.findUserDetails(null, username); let userId; @@ -693,10 +725,11 @@ export class PostgresUserService { if (userData?.userId) { userId = userData?.userId; } else { - return new ErrorResponse({ - errorCode: `404`, - errorMessage: "User with given username not found", - }); + // return new ErrorResponse({ + // errorCode: `404`, + // errorMessage: "User with given username not found", + // }); + return APIResponse.error(response, apiId, "Not Found", `User with given username not found`, String(HttpStatus.NOT_FOUND)); } // const data = JSON.stringify({ @@ -717,28 +750,34 @@ export class PostgresUserService { userId ); } catch (e) { - return new ErrorResponse({ - errorCode: `${e.response.status}`, - errorMessage: e.response.data.error, - }); + // return new ErrorResponse({ + // errorCode: `${e.response.status}`, + // errorMessage: e.response.data.error, + // }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } if (apiResponse.statusCode === 204) { - return new SuccessResponse({ - statusCode: apiResponse.statusCode, - message: apiResponse.message, - data: apiResponse.data, - }); + // return new SuccessResponse({ + // statusCode: apiResponse.statusCode, + // message: apiResponse.message, + // data: apiResponse.data, + // }); + return await APIResponse.success(response, apiId, {}, + String(HttpStatus.NO_CONTENT), 'User Password Updated Successfully.') } else { - return new ErrorResponse({ - errorCode: "400", - errorMessage: apiResponse.errors, - }); + // return new ErrorResponse({ + // errorCode: "400", + // errorMessage: apiResponse.errors, + // }); + return APIResponse.error(response, apiId, "Bad Request", `Error : ${apiResponse?.errors}`, String(HttpStatus.BAD_REQUEST)); } } catch (e) { - return e; + // return e; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } + public async resetKeycloakPassword( request: any, token: string, @@ -808,24 +847,27 @@ export class PostgresUserService { }; } - public async deleteUserById(userId){ + public async deleteUserById(userId: string,response: Response){ + const apiId = APIID.USER_DELETE; const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; // Validate userId format if (!isUUID(userId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter a valid UUID for userId", - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.BAD_REQUEST, + // errorMessage: "Please enter a valid UUID for userId", + // }); + return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID for userId`, String(HttpStatus.BAD_REQUEST)); } try { // Check if user exists in usersRepository const user = await this.usersRepository.findOne({ where :{userId:userId}}); if (!user) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User not found in user table.", - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.NOT_FOUND, + // errorMessage: "User not found in user table.", + // }); + return APIResponse.error(response, apiId, "Not Found", `User not found in user table.`, String(HttpStatus.NOT_FOUND)); } @@ -853,24 +895,21 @@ export class PostgresUserService { }}); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "User and related entries deleted Successfully.", - data: { - user: userResult - }, - }); + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: "User and related entries deleted Successfully.", + // data: { + // user: userResult + // }, + // }); + return await APIResponse.success(response, apiId, userResult, + String(HttpStatus.OK), "User and related entries deleted Successfully.") } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } - } - - - - - diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index f777cfcd..aca47bb3 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -1,3 +1,4 @@ +import { Response } from "express"; import { UserCreateDto } from "src/user/dto/user-create.dto"; import { UserSearchDto } from "src/user/dto/user-search.dto"; import { UserData } from "src/user/user.controller"; @@ -14,7 +15,7 @@ export interface IServicelocator { getUsersDetailsById(userData: UserData, response:any); getUsersDetailsByCohortId(userData: Record, response:any); updateUser(userDto?: any,response?: any); - createUser(request: any, userDto: UserCreateDto); + createUser(request: any, userDto: UserCreateDto, response: Response); findUserDetails(userID:any,username:String) searchUser( tenantId: string, @@ -22,8 +23,8 @@ export interface IServicelocator { response: any, userSearchDto: UserSearchDto ); - resetUserPassword(request: any, username: string, newPassword: string); + resetUserPassword(request: any, username: string, newPassword: string, response: Response); checkUser(body:any,response); - deleteUserById(userId: string): Promise; + deleteUserById(userId: string, response: Response): Promise; } diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts new file mode 100644 index 00000000..5caf0de4 --- /dev/null +++ b/src/common/utils/api-id.config.ts @@ -0,0 +1,8 @@ +export const APIID = { + USER_GET: "api.user.get", + USER_CREATE: "api.user.create", + USER_UPDATE: "api.user.update", + USER_LIST: "api.user.list", + USER_RESET_PASSWORD: "api.user.resetPassword", + USER_DELETE: "api.user.delete" +} diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 675bfb40..2c7cf72e 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -40,7 +40,7 @@ import { UserUpdateDTO } from "./dto/user-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { Request, Response } from "express"; import { AllExceptionsFilter } from "src/common/filters/exception.filter"; -import { Reflector } from "@nestjs/core"; +import { APIID } from "src/common/utils/api-id.config"; export interface UserData { context: string; tenantId: string; @@ -49,15 +49,14 @@ export interface UserData { } @ApiTags("User") -@Controller("users") +@Controller() export class UserController { constructor( private userAdapter: UserAdapter, - private reflector: Reflector, ) {} - @UseFilters(new AllExceptionsFilter('get.user.byid')) - @Get('/:userId') + @UseFilters(new AllExceptionsFilter(APIID.USER_GET)) + @Get('read/:userId') @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User details Fetched Successfully" }) @@ -92,8 +91,8 @@ export class UserController { return response.status(result.statusCode).json(result); } - - @Post() + @UseFilters(new AllExceptionsFilter(APIID.USER_CREATE)) + @Post("/create") @UseGuards(JwtAuthGuard) @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @@ -108,11 +107,12 @@ export class UserController { @Body() userCreateDto: UserCreateDto, @Res() response: Response ) { - const result = await this.userAdapter.buildUserAdapter().createUser(request, userCreateDto); - return response.status(result.statusCode).json(result); + return await this.userAdapter.buildUserAdapter().createUser(request, userCreateDto, response); + } - @Patch("/:userid") + @UseFilters(new AllExceptionsFilter(APIID.USER_UPDATE)) + @Patch("update/:userid") @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiBody({ type: UserUpdateDTO }) @@ -130,11 +130,11 @@ export class UserController { ) { // userDto.tenantId = headers["tenantid"]; userUpdateDto.userId = userId; - const result = await this.userAdapter.buildUserAdapter().updateUser(userUpdateDto,response); - return response.status(result.statusCode).json(result); + return await this.userAdapter.buildUserAdapter().updateUser(userUpdateDto,response); } - @Post("/search") + @UseFilters(new AllExceptionsFilter(APIID.USER_LIST)) + @Post("/list") @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "User list." }) @@ -152,10 +152,10 @@ export class UserController { @Body() userSearchDto: UserSearchDto ) { const tenantId = headers["tenantid"]; - const result = await this.userAdapter.buildUserAdapter().searchUser(tenantId,request,response,userSearchDto); - return response.status(result.statusCode).json(result); + return await this.userAdapter.buildUserAdapter().searchUser(tenantId,request,response,userSearchDto); } + @UseFilters(new AllExceptionsFilter(APIID.USER_RESET_PASSWORD)) @Post("/reset-password") @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @@ -164,6 +164,7 @@ export class UserController { @ApiBody({ type: Object }) public async resetUserPassword( @Req() request: Request, + @Res() response: Response, @Body() reqBody: { username: string; @@ -172,9 +173,10 @@ export class UserController { ) { return await this.userAdapter .buildUserAdapter() - .resetUserPassword(request, reqBody.username, reqBody.newPassword); + .resetUserPassword(request, reqBody.username, reqBody.newPassword, response); } + // required for FTL @Post("/check") async checkUser( @Body() body, @@ -185,25 +187,22 @@ export class UserController { } //delete - @Delete("/:userId") - + @Delete("delete/:userId") + @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User deleted successfully" }) @ApiNotFoundResponse({ description: "Data not found" }) @SerializeOptions({ strategy: "excludeAll", }) - public async deleteUserById( @Headers() headers, @Param("userId") userId: string, @Req() request: Request, @Res() response: Response ) { - - const result = await this.userAdapter + return await this.userAdapter .buildUserAdapter() - .deleteUserById(userId); - return response.status(result.statusCode).json(result); + .deleteUserById(userId,response); } } From f1213cc60f074b1979be2d6d01f8e21ebbdc8b1d Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Tue, 28 May 2024 19:15:14 +0530 Subject: [PATCH 358/408] chore : removed console logs --- src/adapters/postgres/user-adapter.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index e2a55e47..8935378f 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -81,7 +81,6 @@ export class PostgresUserService { // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: e, // }); - console.log(e,"eer"); return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -146,9 +145,6 @@ export class PostgresUserService { this.findUserDetails(userData.userId), this.findUserRoles(userData.userId, userData.tenantId) ]); - - console.log(userRole,"uerrple"); - const roleInUpper = (userRole.title).toUpperCase(); if (userData?.fieldValue) { @@ -208,7 +204,6 @@ export class PostgresUserService { return await APIResponse.success(response, apiId, {...result}, String(HttpStatus.OK), 'User details Fetched Successfully.') } catch (e) { - console.log("err",e) // new ErrorResponseTypeOrm({ // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: e, @@ -311,7 +306,6 @@ export class PostgresUserService { } async findUserRoles(userId: string, tenantId: string) { - console.log(userId, tenantId); const getRole = await this.userRoleMappingRepository.findOne({ where: { @@ -366,9 +360,6 @@ export class PostgresUserService { contextType: role, } }) - console.log("customFields", customFields); - - return customFields; } async findFilledValues(userId: string, role: string) { From 44464b65702e6b5a394783c78b792ce0ede3ac20 Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Tue, 28 May 2024 19:25:21 +0530 Subject: [PATCH 359/408] PS-634:Task[Changes in respose iof Cohort API] --- src/adapters/cohortservicelocator.ts | 11 +- src/adapters/fieldsservicelocator.ts | 2 +- src/adapters/postgres/cohort-adapter.ts | 370 +++++++++++++----------- src/adapters/postgres/fields-adapter.ts | 78 +++-- src/cohort/cohort.controller.ts | 56 ++-- src/fields/fields.controller.ts | 7 +- 6 files changed, 285 insertions(+), 239 deletions(-) diff --git a/src/adapters/cohortservicelocator.ts b/src/adapters/cohortservicelocator.ts index 37fb0fcc..b15d0493 100644 --- a/src/adapters/cohortservicelocator.ts +++ b/src/adapters/cohortservicelocator.ts @@ -2,11 +2,12 @@ import { CohortCreateDto } from "src/cohort/dto/cohort-create.dto"; import { CohortUpdateDto } from "src/cohort/dto/cohort-update.dto"; import { CohortSearchDto } from "src/cohort/dto/cohort-search.dto"; import { CohortDto } from "src/cohort/dto/cohort.dto"; +import { Response } from "express"; export interface IServicelocatorcohort { - getCohortsDetails(cohortId: string); - createCohort(request: any, cohortDto: CohortCreateDto); - searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto); - updateCohort(cohortId: string, request: any, cohortUpdateDto: CohortUpdateDto); - updateCohortStatus(cohortId: string, request: any); + getCohortsDetails(cohortId: string,response); + createCohort(request: any, cohortDto: CohortCreateDto,response); + searchCohort(tenantid, request: any, cohortSearchDto: CohortSearchDto,response); + updateCohort(cohortId: string, request: any, cohortUpdateDto: CohortUpdateDto,response); + updateCohortStatus(cohortId: string, request: any,response); } diff --git a/src/adapters/fieldsservicelocator.ts b/src/adapters/fieldsservicelocator.ts index 300a3918..36fd9181 100644 --- a/src/adapters/fieldsservicelocator.ts +++ b/src/adapters/fieldsservicelocator.ts @@ -10,7 +10,7 @@ export interface IServicelocatorfields { searchFields(tenantid, request: any, fieldsSearchDto: FieldsSearchDto); // updateFields(fieldsId: string, request: any, fieldsDto: FieldsDto); //field values - createFieldValues(request: any, fieldValuesDto: FieldValuesDto); + createFieldValues(request: any, fieldValuesDto: FieldValuesDto,response); // getFieldValues(id, request); searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto); updateFieldValues(id: string, request: any, fieldValuesDto: FieldValuesDto); diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 61662afe..c52d23a1 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -19,8 +19,7 @@ import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { isUUID } from "class-validator"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; - - +import APIResponse from "src/common/responses/response"; @Injectable() export class PostgresCohortService { @@ -44,9 +43,9 @@ export class PostgresCohortService { tenantId: string, userId: string, request: any, - response: any + res: any ) { - const apiId = "api.concept.editminiScreeningAnswer"; + let apiId = 'api.get.getCohortList'; try { let findCohortId = await this.findCohortName(userId); let result = { @@ -65,50 +64,46 @@ export class PostgresCohortService { result.cohortData.push(cohortData); } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: result, - }); + return APIResponse.success(res, apiId, result,(HttpStatus.OK), "Cohort list fetched successfully"); + } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + } } - public async getCohortsDetails(cohortId: string) { + public async getCohortsDetails(cohortId: string, res) { + let apiId = 'api.get.getCohortDetails'; + try { if (!isUUID(cohortId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid (UUID)", - }); + return APIResponse.error( + res, + apiId, + `Please Enter valid (UUID)`, + 'Invalid cohortId', + (HttpStatus.BAD_REQUEST) + ) } const checkData = await this.checkAuthAndValidData(cohortId); if (checkData === true) { const result = await this.getCohortDataWithCustomfield(cohortId); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Cohort detais fetched succcessfully.", - data: result, - }); + return APIResponse.success(res, apiId, result,(HttpStatus.OK), "Cohort details fetched succcessfully."); + } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Cohort not found", - }); + return APIResponse.error( + res, + apiId, + `Cohort not found`, + 'Invalid cohortId', + (HttpStatus.NOT_FOUND) + ) } - } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`,(HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -197,25 +192,32 @@ export class PostgresCohortService { let encounteredKeys = [] for (const fieldValue of field_value_array) { const [fieldId] = fieldValue.split(":").map(value => value.trim()); - if (encounteredKeys.includes(fieldId)) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: `Duplicate fieldId '${fieldId}' found in fieldValues.`, - }); + return { valid: false, fieldId: fieldId }; } - encounteredKeys.push(fieldId); + encounteredKeys.push(fieldId) + } + return { valid: true, fieldId: "true" }; + }; + - }; - } + public async createCohort(request: any, cohortCreateDto: CohortCreateDto, res) { + let apiId = 'api.post.createCohort'; - public async createCohort(request: any, cohortCreateDto: CohortCreateDto) { try { let field_value_array = cohortCreateDto.fieldValues.split("|"); //Check duplicate field - await this.validateFieldValues(field_value_array); - + let valid = await this.validateFieldValues(field_value_array); + if (valid && valid?.valid === false) { + return APIResponse.error( + res, + apiId, + `Duplicate fieldId`, + `Duplicate fieldId '${valid.fieldId}' found in fieldValues.`, + (HttpStatus.CONFLICT) + ) + } const decoded: any = jwt_decode(request.headers.authorization); cohortCreateDto.createdBy = decoded?.sub cohortCreateDto.updatedBy = decoded?.sub @@ -227,7 +229,6 @@ export class PostgresCohortService { const existData = await this.cohortRepository.find({ where: { name: cohortCreateDto.name, parentId: cohortCreateDto.parentId } }) - if (existData.length == 0) { response = await this.cohortRepository.save(cohortCreateDto); } else { @@ -238,19 +239,20 @@ export class PostgresCohortService { const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { - return new SuccessResponse({ - statusCode: HttpStatus.CONFLICT, - message: "Cohort name already exist for this parent.", - data: existData, - }); + return APIResponse.error( + res, + apiId, + `Cohort already exist`, + `Cohort name already exist for this parent.`, + (HttpStatus.CONFLICT) + ) } } } else { const existData = await this.cohortRepository.find({ where: { name: cohortCreateDto.name } }) - - if (existData.length == 0) { + if (existData.length === 0) { response = await this.cohortRepository.save(cohortCreateDto); } else { if (existData[0].status == false) { @@ -260,11 +262,13 @@ export class PostgresCohortService { const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { - return new SuccessResponse({ - statusCode: HttpStatus.CONFLICT, - message: "Cohort name already exists.", - data: existData, - }); + return APIResponse.error( + res, + apiId, + `Cohort already exist`, + `Cohort name already exists.`, + (HttpStatus.CONFLICT) + ) } } } @@ -285,39 +289,40 @@ export class PostgresCohortService { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; - const fieldValue = await this.fieldsService.createFieldValues(request, fieldValueDto); + const fieldValue = await this.fieldsService.findAndSaveFieldValues(fieldValueDto); } } response = new ReturnResponseBody(response); - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Cohort Created Successfully.", - data: response, - }); + return APIResponse.success(res, apiId, response,(HttpStatus.CREATED), "Cohort Created Successfully."); + } catch (e) { - if (e instanceof ErrorResponseTypeOrm) { - return e; - } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.toString(), // or any custom error message you want - }); - } + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); } } public async updateCohort( cohortId: string, request: any, - cohortUpdateDto: CohortUpdateDto + cohortUpdateDto: CohortUpdateDto, + res ) { + let apiId = 'api.put.updateCohort'; try { let field_value_array = cohortUpdateDto.fieldValues.split("|"); - await this.validateFieldValues(field_value_array); + let valid = await this.validateFieldValues(field_value_array); + if (valid && valid?.valid === false) { + return APIResponse.error( + res, + apiId, + `Duplicate fieldId`, + `Duplicate fieldId '${valid.fieldId}' found in fieldValues.`, + (HttpStatus.CONFLICT) + ) + } const decoded: any = jwt_decode(request.headers.authorization); cohortUpdateDto.updatedBy = decoded?.sub @@ -326,10 +331,13 @@ export class PostgresCohortService { let response; if (!isUUID(cohortId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid (UUID)", - }); + return APIResponse.error( + res, + apiId, + `Invalid cohortId`, + `Please Enter valid cohortId(UUID)`, + (HttpStatus.CONFLICT) + ) } const checkData = await this.checkAuthAndValidData(cohortId); @@ -354,6 +362,8 @@ export class PostgresCohortService { where: { name: cohortUpdateDto.name, parentId: cohortUpdateDto.parentId } }) + + if (existData.length == 0) { response = await this.cohortRepository.update(cohortId, updateData); } else { @@ -364,11 +374,13 @@ export class PostgresCohortService { const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { - return new SuccessResponse({ - statusCode: HttpStatus.CONFLICT, - message: "Cohort name already exist for this parent please choose another name.", - data: existData, - }); + return APIResponse.error( + res, + apiId, + `Cohort name already exist`, + `Cohort name already exist for this parent please choose another name.`, + (HttpStatus.CONFLICT), + ) } } } else { @@ -386,11 +398,13 @@ export class PostgresCohortService { const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { - return new SuccessResponse({ - statusCode: HttpStatus.CONFLICT, - message: "Cohort name already exists please choose another name.", - data: existData, - }); + return APIResponse.error( + res, + apiId, + `Cohort name already exist`, + `Cohort name already exists please choose another name.`, + (HttpStatus.CONFLICT) + ) } } } @@ -402,6 +416,7 @@ export class PostgresCohortService { let fieldValues = field_value_array[i].split(":"); let fieldId = fieldValues[0] ? fieldValues[0].trim() : ""; try { + const fieldVauesRowId = await this.fieldsService.searchFieldValueId(cohortId, fieldId) const rowid = fieldVauesRowId.fieldValuesId; @@ -411,6 +426,7 @@ export class PostgresCohortService { }; await this.fieldsService.updateFieldValues(rowid, fieldValueUpdateDto); } catch { + let fieldValueDto: FieldValuesDto = { value: fieldValues[1] ? fieldValues[1].trim() : "", itemId: cohortId, @@ -420,42 +436,35 @@ export class PostgresCohortService { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; - await this.fieldsService.createFieldValues(request, fieldValueDto); + await this.fieldsService.findAndSaveFieldValues(fieldValueDto); } } } } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Cohort updated successfully.", - data: { - rowCount: response.affected, - } - }); + return APIResponse.success(res, apiId, response.affected,(HttpStatus.OK), "Cohort updated successfully."); + } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Cohort not found", - }); + return APIResponse.error( + res, + apiId, + `Cohort not found`, + `Cohort not found`, + (HttpStatus.NOT_FOUND) + ) } } catch (e) { - if (e instanceof ErrorResponseTypeOrm) { - return e; - } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.toString(), // or any custom error message you want - }); - } + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`,(HttpStatus.INTERNAL_SERVER_ERROR)); + } } public async searchCohort( tenantId: string, request: any, - cohortSearchDto: CohortSearchDto, + cohortSearchDto: CohortSearchDto, response ) { + let apiId = 'api.post.searchCohort'; try { let { limit, page, filters } = cohortSearchDto; @@ -464,7 +473,7 @@ export class PostgresCohortService { if (limit > 0 && page > 0) { offset = (limit) * (page - 1); } - limit = 200; + if (limit === 0) { limit = 200 } const emptyValueKeys = {}; let emptyKeysString = ''; @@ -473,17 +482,23 @@ export class PostgresCohortService { // Validate the limit parameter if (limit > MAX_LIMIT) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `Limit exceeds maximum allowed value of ${MAX_LIMIT}`, - }); + return APIResponse.error( + response, + apiId, + `Limit exceeded`, + `Limit exceeds maximum allowed value of ${MAX_LIMIT}`, + (HttpStatus.BAD_REQUEST) + ) } if (page > PAGE_LIMIT) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `Page limit exceeds maximum allowed value of ${PAGE_LIMIT}`, - }); + return APIResponse.error( + response, + apiId, + `Page Limit exceeded`, + `Page limit exceeds maximum allowed value of ${PAGE_LIMIT}`, + (HttpStatus.BAD_REQUEST) + ) } const allowedKeys = ["userId", "cohortId", "name"]; @@ -492,10 +507,13 @@ export class PostgresCohortService { if (filters && Object.keys(filters).length > 0) { Object.entries(filters).forEach(([key, value]) => { if (!allowedKeys.includes(key)) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `${key} Invalid key`, - }); + return APIResponse.error( + response, + apiId, + `Invalid key in filter`, + `${key} Invalid key`, + (HttpStatus.BAD_REQUEST) + ) } else { if (value === '') { emptyValueKeys[key] = value; @@ -508,17 +526,23 @@ export class PostgresCohortService { } if (whereClause['userId'] && !isUUID(whereClause['userId'])) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: 'Invalid User ID format. It must be a valid UUID.', - }); + return APIResponse.error( + response, + apiId, + `Invalid userId`, + `Invalid User ID format. It must be a valid UUID.`, + (HttpStatus.BAD_REQUEST) + ) } if (whereClause['cohortId'] && !isUUID(whereClause['cohortId'])) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: 'Invalid Cohort ID format. It must be a valid UUID.', - }); + return APIResponse.error( + response, + apiId, + `Invalid cohortId`, + `Invalid Cohort ID format. It must be a valid UUID.`, + (HttpStatus.BAD_REQUEST) + ) } let results = { @@ -529,10 +553,13 @@ export class PostgresCohortService { const additionalFields = Object.keys(whereClause).filter(key => key !== 'userId'); if (additionalFields.length > 0) { // Handle the case where userId is provided along with other fields - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "When filtering by userId, do not include additional fields.", - }); + return APIResponse.error( + response, + apiId, + `Invalid filters`, + 'When filtering by userId, do not include additional fields.', + (HttpStatus.BAD_REQUEST) + ) } let userTenantMapExist = await this.UserTenantMappingRepository.find({ @@ -542,10 +569,13 @@ export class PostgresCohortService { } }) if (userTenantMapExist.length == 0) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User is not mapped for this tenant.", - }); + return APIResponse.error( + response, + apiId, + `Invalid combination of userId and tenantId`, + 'User is not mapped for this tenant.', + (HttpStatus.BAD_REQUEST) + ) } const [cohortData] = await this.cohortMembersRepository.findAndCount({ where: whereClause, @@ -571,47 +601,44 @@ export class PostgresCohortService { } if (results.cohortDetails.length > 0) { - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Cohort details fetched successfully', - data: results, - }); + return APIResponse.success(response, apiId, results,(HttpStatus.OK), "Cohort details fetched successfully"); + } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "No data found.", - }); + return APIResponse.error( + response, + apiId, + `No data found.`, + 'No data found.', + (HttpStatus.NOT_FOUND) + ) } - } catch (e) { - if (e instanceof ErrorResponseTypeOrm) { - return e; - } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.toString(), // or any custom error message you want - }); - } + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); } } public async updateCohortStatus( cohortId: string, - request: any + request: any, + response ) { + let apiId = 'api.delete.updateCohortStatus'; try { const decoded: any = jwt_decode(request.headers.authorization); // const createdBy = decoded?.sub; const updatedBy = decoded?.sub if (!isUUID(cohortId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid (UUID)", - }); + return APIResponse.error( + response, + apiId, + `Invalid cohortId`, + 'Invalid Cohort Id format. It must be a valid UUID.', + (HttpStatus.BAD_REQUEST) + ) } const checkData = await this.checkAuthAndValidData(cohortId); @@ -620,8 +647,7 @@ export class PostgresCohortService { SET "status" = false, "updatedBy" = '${updatedBy}' WHERE "cohortId" = $1`; - await this.cohortRepository.query(query, [cohortId]); - + const affectedrows = await this.cohortRepository.query(query, [cohortId]); await this.cohortMembersRepository.delete( { cohortId: cohortId } ); @@ -630,21 +656,19 @@ export class PostgresCohortService { ); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Cohort Deleted Successfully.", - }); + return APIResponse.success(response, apiId, affectedrows[1], (HttpStatus.OK), "Cohort Deleted Successfully."); + } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User not found", - }); + return APIResponse.error( + response, + apiId, + `Invalid cohortId`, + 'Cohort not found', + (HttpStatus.BAD_REQUEST) + ) } } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); } } diff --git a/src/adapters/postgres/fields-adapter.ts b/src/adapters/postgres/fields-adapter.ts index f0808835..7888b41b 100644 --- a/src/adapters/postgres/fields-adapter.ts +++ b/src/adapters/postgres/fields-adapter.ts @@ -10,8 +10,8 @@ import { FieldValues } from "../../fields/entities/fields-values.entity"; import { InjectRepository } from "@nestjs/typeorm"; import { Repository } from "typeorm"; import { SuccessResponse } from "src/success-response"; -import APIResponse from "src/utils/response"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; +import APIResponse from "src/common/responses/response"; @Injectable() export class PostgresFieldsService { @@ -58,7 +58,7 @@ export class PostgresFieldsService { async searchFields(tenantId: string, request: any, fieldsSearchDto: FieldsSearchDto) { try { - const getConditionalData = APIResponse.search(fieldsSearchDto) + const getConditionalData = await this.search(fieldsSearchDto) const offset = getConditionalData.offset; const limit = getConditionalData.limit; const whereClause = getConditionalData.whereClause; @@ -101,33 +101,34 @@ export class PostgresFieldsService { return { mappedResponse, totalCount }; } - async createFieldValues(request: any, fieldValuesDto: FieldValuesDto) { + async createFieldValues(request: any, fieldValuesDto: FieldValuesDto,res) { + let apiId = 'api.post.createFieldValues'; + + try { - const checkFieldValueExist = await this.fieldsValuesRepository.find({ - where: { itemId: fieldValuesDto.itemId, fieldId: fieldValuesDto.fieldId }, - }); - - if (checkFieldValueExist.length == 0) { - - let result = await this.fieldsValuesRepository.save(fieldValuesDto); - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Ok.", - data: result, - }); - } + let result = await this.findAndSaveFieldValues(fieldValuesDto); + if(!result){ + APIResponse.error( + res, + apiId, + `Fields not found`, + `Fields not found`, + (HttpStatus.NOT_FOUND) + ) + + } + return APIResponse.success(res, apiId, result, (HttpStatus.CREATED), "Ok"); + } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + } } async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { try { - const getConditionalData = APIResponse.search(fieldValuesSearchDto) + const getConditionalData = await this.search(fieldValuesSearchDto) const offset = getConditionalData.offset; const limit = getConditionalData.limit; const whereClause = getConditionalData.whereClause; @@ -265,4 +266,39 @@ export class PostgresFieldsService { return fieldResponse; } + public async findAndSaveFieldValues(fieldValuesDto: FieldValuesDto){ + + const checkFieldValueExist = await this.fieldsValuesRepository.find({ + where: { itemId: fieldValuesDto.itemId, fieldId: fieldValuesDto.fieldId }, + }); + + if (checkFieldValueExist.length == 0) { + let result = await this.fieldsValuesRepository.save(fieldValuesDto); + return result + } + return false; + } + + + public async search(dtoFileName){ + let { limit, page, filters } = dtoFileName; + + let offset = 0; + if (page > 1) { + offset = parseInt(limit) * (page - 1); + } + + if (limit.trim() === '') { + limit = '0'; + } + + const whereClause = {}; + if (filters && Object.keys(filters).length > 0) { + Object.entries(filters).forEach(([key, value]) => { + whereClause[key] = value; + }); + } + return {offset,limit,whereClause}; + } + } diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index f3aa96b6..c17a168d 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -35,20 +35,20 @@ import { Request } from "@nestjs/common"; import { FileInterceptor } from "@nestjs/platform-express"; import { editFileName, imageFileFilter } from "./utils/file-upload.utils"; import { diskStorage } from "multer"; -import { Response, response } from "express"; +import { Response } from "express"; import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortUpdateDto } from "./dto/cohort-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; @ApiTags("Cohort") -@Controller("cohorts") +@Controller("cohort") @UseGuards(JwtAuthGuard) export class CohortController { constructor(private readonly cohortAdapter: CohortAdapter) { } - //Get Cohort Details - @Get("/:cohortId") + + @Get("/read/:cohortId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Cohort details Fetched Successfully" }) @ApiNotFoundResponse({ description: "Cohort Not Found" }) @@ -63,12 +63,12 @@ export class CohortController { @Res() response: Response ) { // const tenantId = headers["tenantid"]; Can be Used In future - const result = await this.cohortAdapter.buildCohortAdapter().getCohortsDetails(cohortId); - return response.status(result.statusCode).json(result); + return await this.cohortAdapter.buildCohortAdapter().getCohortsDetails(cohortId, response); + } - //create cohort - @Post() + + @Post("/create") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort has been created successfully." }) @@ -97,28 +97,21 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { - const expectedFields = ['programId', 'parentId', 'name', 'type', 'fieldValues' ]; - const unexpectedFields = Object.keys(cohortCreateDto).filter(field => !expectedFields.includes(field)); - if (unexpectedFields.length > 0) { - throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); - } - let tenantid = headers["tenantid"]; const payload = { image: image?.filename, tenantId: tenantid, }; Object.assign(cohortCreateDto, payload); - const result = await this.cohortAdapter.buildCohortAdapter().createCohort( + return await this.cohortAdapter.buildCohortAdapter().createCohort( request, - cohortCreateDto + cohortCreateDto, + response ); - return response.status(result.statusCode).json(result); } - // search @Post("/search") @ApiBasicAuth("access-token") @ApiBody({ type: CohortSearchDto }) @@ -139,19 +132,16 @@ export class CohortController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - if(tenantid === ''){ - return response.status(400).json({"statusCode": 400, "errorMessage": "TenantId required."}); - } - const result = await this.cohortAdapter.buildCohortAdapter().searchCohort( + return await this.cohortAdapter.buildCohortAdapter().searchCohort( tenantid, request, - cohortSearchDto + cohortSearchDto, + response ); - return response.status(result.statusCode).json(result); } //update - @Put("/:cohortId") + @Put("/update/:cohortId") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @UseInterceptors( @@ -175,22 +165,17 @@ export class CohortController { @UploadedFile() image, @Res() response: Response ) { - const expectedFields = ['cohortId','programId', 'parentId', 'name', 'type', 'fieldValues' ]; - const unexpectedFields = Object.keys(cohortUpdateDto).filter(field => !expectedFields.includes(field)); - if (unexpectedFields.length > 0) { - throw new BadRequestException(`Unexpected fields found: ${unexpectedFields.join(', ')}`); - } - const result = await this.cohortAdapter.buildCohortAdapter().updateCohort( + return await this.cohortAdapter.buildCohortAdapter().updateCohort( cohortId, request, - cohortUpdateDto + cohortUpdateDto, + response ); - return response.status(result.statusCode).json(result); } //delete cohort - @Delete("/:cohortId") + @Delete("/delete/:cohortId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Cohort has been deleted successfully." }) @ApiBadRequestResponse({ description: "Bad request." }) @@ -200,7 +185,6 @@ export class CohortController { @Req() request: Request, @Res() response: Response ) { - const result = await this.cohortAdapter.buildCohortAdapter().updateCohortStatus(cohortId, request); - return response.status(result.statusCode).json(result); + return await this.cohortAdapter.buildCohortAdapter().updateCohortStatus(cohortId, request, response); } } diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 06037aa8..02f8efa0 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -108,9 +108,10 @@ export class FieldsController { ) { const result = await this.fieldsAdapter.buildFieldsAdapter().createFieldValues( request, - fieldValuesDto - ); - return response.status(result.statusCode).json(result); + fieldValuesDto, + response + ); + return result; } //search fields values From c9b16370cc86249d8b6451517ecdb7f5d973696b Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 28 May 2024 19:36:56 +0530 Subject: [PATCH 360/408] add --- src/adapters/cohortMembersservicelocator.ts | 9 +- .../postgres/cohortMembers-adapter.ts | 180 ++++------- src/adapters/postgres/user-adapter.ts | 182 ++++++----- src/cohortMembers/cohortMember.service.ts | 295 ------------------ src/cohortMembers/cohortMembers.controller.ts | 29 +- src/cohortMembers/cohortMembers.module.ts | 4 +- src/cohortMembers/dto/cohortMembers.dto.ts | 2 +- 7 files changed, 161 insertions(+), 540 deletions(-) delete mode 100644 src/cohortMembers/cohortMember.service.ts diff --git a/src/adapters/cohortMembersservicelocator.ts b/src/adapters/cohortMembersservicelocator.ts index 476a405d..8b00a0f7 100644 --- a/src/adapters/cohortMembersservicelocator.ts +++ b/src/adapters/cohortMembersservicelocator.ts @@ -6,10 +6,11 @@ export interface IServicelocatorcohortMembers { createCohortMembers( loginUser: any, cohortMembersDto: CohortMembersDto, - response: any + response: any, + tenantId: string, ); - getCohortMembers(cohortMemberId: string,tenantId:string, fieldvalue:string, response:Response); - searchCohortMembers(cohortMembersSearchDto: CohortMembersSearchDto, tenantId:string, response:Response); + getCohortMembers(cohortMemberId: string, tenantId: string, fieldvalue: string, response: Response); + searchCohortMembers(cohortMembersSearchDto: CohortMembersSearchDto, tenantId: string, response: Response); updateCohortMembers( cohortMembershipId: string, loginUser: any, @@ -17,5 +18,5 @@ export interface IServicelocatorcohortMembers { response: any ); - deleteCohortMemberById(tenantid, cohortMembershipId, response, request); + deleteCohortMemberById(tenantid, cohortMembershipId, response); } diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index c66096a6..af8ecb2c 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -37,19 +37,16 @@ export class PostgresCohortMembersService { async getCohortMembers(cohortId: any, tenantId: any, fieldvalue: any, res: Response) { const apiId = 'api.get.cohortMembers'; try { - const fieldvalues = fieldvalue.toLowerCase() + const fieldvalues = fieldvalue?.toLowerCase() if (!tenantId) { - APIResponse.error(res, apiId, "BAD_REQUEST", `TenantId required`, String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(res, apiId, "Bad Request", `TenantId required`, HttpStatus.BAD_REQUEST; } if (!isUUID(cohortId)) { - APIResponse.error(res, apiId, "BAD_REQUEST", "Invalid input: CohortId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(res, apiId, "Bad Request", "Invalid input: CohortId must be a valid UUID.", HttpStatus.BAD_REQUEST; } - if (!isUUID(tenantId)) { - APIResponse.error(res, apiId, "Bad Request", "Invalid input: TenantId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); - } const cohortTenantMap = await this.cohortRepository.find({ where: { @@ -58,7 +55,7 @@ export class PostgresCohortMembersService { } }) if (!cohortTenantMap) { - APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort not found for the provided tenant.", String(HttpStatus.NOT_FOUND)); + return APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort not found for the provided tenant.", HttpStatus.NOT_FOUND; } const userDetails = await this.findcohortData(cohortId); if (userDetails === true) { @@ -73,12 +70,12 @@ export class PostgresCohortMembersService { ); results.userDetails.push(cohortDetails); - APIResponse.success(res, apiId, results, String(HttpStatus.OK), "Cohort members details fetched successfully."); + return APIResponse.success(res, apiId, results, HttpStatus.OK, "Cohort members details fetched successfully."); } else { - APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort Member not exist.", String(HttpStatus.NOT_FOUND)); + return APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort Member not exist.", HttpStatus.NOT_FOUND; } } catch (e) { - APIResponse.error(res, apiId, "Internal Server Error", `Error is: ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is: ${e}`, HttpStatus.INTERNAL_SERVER_ERROR; } } async getUserDetails(searchId: any, searchKey: any, fieldShowHide: any) { @@ -171,7 +168,7 @@ export class PostgresCohortMembersService { const apiId = 'api.post.searchCohortMembers'; try { if (!isUUID(tenantId)) { - APIResponse.error(res, apiId, "Bad Request", "Invalid input: TenantId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(res, apiId, "Bad Request", "Invalid input: TenantId must be a valid UUID.", HttpStatus.BAD_REQUEST; } let { limit, page, filters } = cohortMembersSearchDto; @@ -189,10 +186,10 @@ export class PostgresCohortMembersService { // Validate cohortId and userId format if (whereClause["cohortId"] && !isUUID(whereClause["cohortId"])) { - APIResponse.error(res, apiId, "Bad Request", "Invalid input: CohortId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(res, apiId, "Bad Request", "Invalid input: CohortId must be a valid UUID.", HttpStatus.BAD_REQUEST; } if (whereClause["userId"] && !isUUID(whereClause["userId"])) { - APIResponse.error(res, apiId, "Bad Request", "Invalid input: UserId must be a valid UUID.", String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(res, apiId, "Bad Request", "Invalid input: UserId must be a valid UUID.", HttpStatus.BAD_REQUEST; } // Check if cohortId exists if (whereClause["cohortId"]) { @@ -200,7 +197,7 @@ export class PostgresCohortMembersService { where: { cohortId: whereClause["cohortId"] }, }); if (!cohortExists) { - APIResponse.error(res, apiId, "Not Found", "Invalid input: No member found for this cohortId.", String(HttpStatus.NOT_FOUND)); + return APIResponse.error(res, apiId, "Not Found", "Invalid input: No member found for this cohortId.", HttpStatus.NOT_FOUND; } } @@ -210,13 +207,12 @@ export class PostgresCohortMembersService { where: { userId: whereClause["userId"] }, }); if (!userExists) { - APIResponse.error(res, apiId, "Not Found", "Invalid input: No member found for this userId and cohort combination.", String(HttpStatus.NOT_FOUND)); + return APIResponse.error(res, apiId, "Not Found", "Invalid input: No member found for this userId and cohort combination.", HttpStatus.NOT_FOUND; } } // console.log("USER DATA ",userData) let results = {}; -<<<<<<< HEAD let where = []; if (whereClause["cohortId"]) { where.push(["cohortId", whereClause["cohortId"]]); @@ -240,50 +236,19 @@ export class PostgresCohortMembersService { "true", options ); + const totalCount = results['userDetails'].length; + + + if (results['userDetails'].length == 0) { + return APIResponse.error(res, apiId, "Not Found", "Invalid input: No data found.", HttpStatus.NOT_FOUND; + } + + return APIResponse.success(res, apiId, { totalCount, results }, HttpStatus.OK, "Cohort members details fetched successfully."); + -======= - let where = []; - if (whereClause["cohortId"]) { - where.push(["cohortId", whereClause["cohortId"]]); - } - if (whereClause["userId"]) { - where.push(["userId", whereClause["userId"]]); - } - if (whereClause["role"]) { - where.push(["role", whereClause["role"]]); - } - let options = []; - if (limit) { - options.push(['limit',limit]); - } - if (offset) { - options.push(['offset',offset]); - } - - results = await this.getCohortMemberUserDetails( - where, - "true", - options - ); - - if(results['userDetails'].length == 0){ - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "No data found.", - }); - } ->>>>>>> d9cc1bbd10ce416d996565065010bc59c66260c2 - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - data: results, - }); } catch (e) { console.log(e) - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is: ${e}`, HttpStatus.INTERNAL_SERVER_ERROR; } } @@ -320,15 +285,31 @@ export class PostgresCohortMembersService { public async createCohortMembers( loginUser: any, cohortMembers: CohortMembersDto, - response: any + res: Response, + tenantId: string ) { - + const apiId = 'api.post.createCohortMembers'; try { cohortMembers.createdBy = loginUser; cohortMembers.updatedBy = loginUser; - await this.validateEntity(this.cohortRepository, { cohortId: cohortMembers.cohortId }, `Cohort Id does not exist.`); - await this.validateEntity(this.usersRepository, { userId: cohortMembers.userId }, `User Id does not exist.`); + const existCohort = await this.cohortRepository.find({ + where: { + cohortId: cohortMembers.cohortId + } + }) + if (existCohort.length == 0) { + return APIResponse.error(res, apiId, "Bad Request", "Invalid input: Cohort Id does not exist.", HttpStatus.BAD_REQUEST; + } + + const existUser = await this.usersRepository.find({ + where: { + userId: cohortMembers.userId, + } + }) + if (existUser.length == 0) { + return APIResponse.error(res, apiId, "Bad Request", "Invalid input: User Id does not exist.", HttpStatus.BAD_REQUEST; + } const existrole = await this.cohortMembersRepository.find({ where: { @@ -337,10 +318,7 @@ export class PostgresCohortMembersService { } }) if (existrole.length > 0) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: `This user '${cohortMembers.userId}' already assign for this cohort '${cohortMembers.cohortId}'.`, - }); + return APIResponse.error(res, apiId, "CONFLICT", `User '${cohortMembers.userId}' is already assigned to cohort '${cohortMembers.cohortId}'.`, HttpStatus.CONFLICT; } // Create a new CohortMembers entity and populate it with cohortMembers data @@ -348,20 +326,10 @@ export class PostgresCohortMembersService { cohortMembers ); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Cohort Member created successfully.", - data: savedCohortMember, - }); + return APIResponse.success(res, apiId, savedCohortMember, HttpStatus.OK, "Cohort member has been successfully assigned."); + } catch (e) { - if (e instanceof ErrorResponseTypeOrm) { - return e; - } else { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.toString(), // or any custom error message you want - }); - } + return APIResponse.error(res, apiId, "Internal Server Error", `Error is: ${e}`, HttpStatus.INTERNAL_SERVER_ERROR; } } @@ -414,72 +382,47 @@ export class PostgresCohortMembersService { } - async validateEntity(repository, whereCondition, errorMessage) { - const validation = await repository.find({ where: whereCondition }); - if (validation.length == 0) { - throw new ErrorResponseTypeOrm({ - statusCode: HttpStatus.CONFLICT, - errorMessage: errorMessage, - }); - } - } public async updateCohortMembers( cohortMembershipId: string, loginUser: any, cohortMembersUpdateDto: CohortMembersUpdateDto, - response: any + res: Response, ) { const apiId = "api.cohortMember.updateCohortMembers"; try { cohortMembersUpdateDto.updatedBy = loginUser; if (!isUUID(cohortMembershipId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter a valid UUID for cohortMemberId", - }); + return APIResponse.error(res, apiId, "Bad Request", "Invalid input: Please Enter a valid UUID for cohortMemberId.", HttpStatus.BAD_REQUEST; } - // Find the cohort member to update const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ where: { cohortMembershipId: cohortMembershipId }, }); - // If cohort member not found, return error if (!cohortMemberToUpdate) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Cohort member not found", - }); + return APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort member not found.", HttpStatus.NOT_FOUND; } - // Update cohort member with provided data Object.assign(cohortMemberToUpdate, cohortMembersUpdateDto); - // Save updated cohort member const updatedCohortMember = await this.cohortMembersRepository.save( cohortMemberToUpdate ); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Cohort Member Updated successfully.", - data: updatedCohortMember, - }); + return APIResponse.success(res, apiId, updatedCohortMember, HttpStatus.OK, "Cohort Member Updated successfully."); + } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is: ${e}`, HttpStatus.INTERNAL_SERVER_ERROR; } } public async deleteCohortMemberById( + tenantid: any, cohortMembershipId: any, - response: any, - request: any + res: any ) { const apiId = "api.cohortMember.deleteCohortMemberById"; @@ -491,25 +434,16 @@ export class PostgresCohortMembersService { }); if (!cohortMember || cohortMember.length === 0) { - return response.status(HttpStatus.NOT_FOUND).send({ - error: "Cohort member not found", - }); + return APIResponse.error(res, apiId, "Not Found", "Invalid input: Cohort member not found.", HttpStatus.NOT_FOUND; } const result = await this.cohortMembersRepository.delete( cohortMembershipId ); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Cohort Member deleted Successfully.", - data: result, - }); + return APIResponse.success(res, apiId, result, HttpStatus.OK, "Cohort Member deleted Successfully."); } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is: ${e}`, HttpStatus.INTERNAL_SERVER_ERROR; } } } diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 1fa5f4c0..d9b6857c 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -114,20 +114,20 @@ export class PostgresUserService { userData: { } }; - let filledValues:any; + let filledValues: any; let customFieldsArray = []; let [userDetails, userRole] = await Promise.all([ this.findUserDetails(userData.userId), - this.findUserRoles(userData.userId,userData.tenantId) + this.findUserRoles(userData.userId, userData.tenantId) ]); const roleInUpper = (userRole.title).toUpperCase(); - if(userData?.fieldValue){ - filledValues = await this.findFilledValues(userData.userId,roleInUpper) + if (userData?.fieldValue) { + filledValues = await this.findFilledValues(userData.userId, roleInUpper) } - if(userRole){ + if (userRole) { userDetails['role'] = userRole.title; } if (!userDetails) { @@ -135,19 +135,19 @@ export class PostgresUserService { statusCode: HttpStatus.NOT_FOUND, message: 'User Not Found', }); - } + } if (!userData.fieldValue) { return new SuccessResponse({ statusCode: HttpStatus.OK, message: 'Ok.', data: userDetails, }); - } - const customFields = await this.findCustomFields(userData,roleInUpper) + } + const customFields = await this.findCustomFields(userData, roleInUpper) result.userData = userDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); for (let data of customFields) { - let fieldValue:any = filledValuesMap.get(data.fieldId); + let fieldValue: any = filledValuesMap.get(data.fieldId); // if(data.type === 'checkbox' && fieldValue){ // console.log("Hi",fieldValue); // fieldValue=fieldValue.split(',') @@ -164,7 +164,7 @@ export class PostgresUserService { }; customFieldsArray.push(customField); } - + result.userData['customFields'] = customFieldsArray; return new SuccessResponse({ statusCode: HttpStatus.OK, @@ -273,24 +273,24 @@ export class PostgresUserService { return result } - async findUserRoles(userId:string, tenantId:string) { - + async findUserRoles(userId: string, tenantId: string) { + const getRole = await this.userRoleMappingRepository.findOne({ - where:{ - userId:userId, - tenantId:tenantId + where: { + userId: userId, + tenantId: tenantId } }) - if(!getRole) { + if (!getRole) { return false; } let role; role = await this.roleRepository.findOne({ - where:{ - roleId:getRole.roleId, - }, - select: ["title"] - }) + where: { + roleId: getRole.roleId, + }, + select: ["title"] + }) return role } @@ -304,7 +304,7 @@ export class PostgresUserService { where: whereClause, select: ["userId", "username", "name", "district", "state", "mobile"] }) - if(!userDetails){ + if (!userDetails) { return false; } const tenentDetails = await this.allUsersTenent(userDetails.userId) @@ -339,28 +339,21 @@ export class PostgresUserService { ON F."fieldId" = FV."fieldId" where U."userId" =$1 AND F."contextType" = $2`; - let result = await this.usersRepository.query(query, [userId,role]); + let result = await this.usersRepository.query(query, [userId, role]); return result; } async updateUser(userDto, response) { try { - console.log("hiii1"); let updatedData = {}; - console.log("hiii2"); let errorMessage; - console.log("hiii3"); if (userDto.userData || Object.keys(userDto.userData).length > 0) { - console.log("hiii"); - + await this.updateBasicUserDetails(userDto.userId, userDto.userData); updatedData['basicDetails'] = userDto.userData; } - console.log("hii"); - if (userDto?.customFields?.length > 0) { - const getFieldsAttributesQuery = ` SELECT * FROM "public"."Fields" @@ -373,7 +366,7 @@ export class PostgresUserService { for (let fieldDetails of getFieldsAttributes) { isEditableFieldId.push(fieldDetails.fieldId); } - console.log("hi"); + // let errorMessage = []; let unEditableIdes = []; for (let data of userDto.customFields) { @@ -442,7 +435,7 @@ export class PostgresUserService { if (userCreateDto.fieldValues) { let field_values = userCreateDto.fieldValues; const validateField = await this.validateFieldValues(field_values); - + if (validateField == false) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.CONFLICT, @@ -451,7 +444,7 @@ export class PostgresUserService { } } - + // check and validate all fields let validateBodyFields = await this.validateBodyFields(userCreateDto) @@ -507,7 +500,7 @@ export class PostgresUserService { } } } - + return new SuccessResponse({ statusCode: 200, message: "User has been created successfully.", @@ -561,19 +554,19 @@ export class PostgresUserService { return true; } - async checkUser(body){ + async checkUser(body) { let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(body); - if(checkUserinKeyCloakandDb){ + if (checkUserinKeyCloakandDb) { return new SuccessResponse({ statusCode: 200, message: "User Exists. Proceed with Sending Email ", - data: {data:true}, + data: { data: true }, }); } return new SuccessResponse({ statusCode: HttpStatus.BAD_REQUEST, message: "Invalid Username Or Email", - data: {data:false}, + data: { data: false }, }); } @@ -581,7 +574,7 @@ export class PostgresUserService { async checkUserinKeyCloakandDb(userDto) { const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - if(userDto?.username){ + if (userDto?.username) { const usernameExistsInKeycloak = await checkIfUsernameExistsInKeycloak( userDto?.username, token @@ -590,7 +583,7 @@ export class PostgresUserService { return usernameExistsInKeycloak; } return false; - }else{ + } else { const usernameExistsInKeycloak = await checkIfEmailExistsInKeycloak( userDto?.email, token @@ -600,8 +593,8 @@ export class PostgresUserService { } return false; } -} - + } + async createUserInDatabase(request: any, userCreateDto: UserCreateDto) { const user = new User() @@ -609,7 +602,7 @@ export class PostgresUserService { user.name = userCreateDto?.name user.email = userCreateDto?.email user.mobile = Number(userCreateDto?.mobile) || null, - user.createdBy = userCreateDto?.createdBy + user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, user.state = userCreateDto?.state, @@ -620,7 +613,7 @@ export class PostgresUserService { if (userCreateDto?.dob) { user.dob = new Date(userCreateDto.dob); } - + let result = await this.usersRepository.save(user); if (result) { @@ -817,65 +810,66 @@ export class PostgresUserService { }; } - public async deleteUserById(userId){ + public async deleteUserById(userId) { const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; - // Validate userId format - if (!isUUID(userId)) { + // Validate userId format + if (!isUUID(userId)) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter a valid UUID for userId", + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter a valid UUID for userId", }); - } - - try { - // Check if user exists in usersRepository - const user = await this.usersRepository.findOne({ where :{userId:userId}}); - if (!user) { + } + + try { + // Check if user exists in usersRepository + const user = await this.usersRepository.findOne({ where: { userId: userId } }); + if (!user) { return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User not found in user table.", + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User not found in user table.", }); - } - - - // Delete from User table - const userResult = await this.usersRepository.delete(userId); - - // Delete from CohortMembers table - const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); - - // Delete from UserTenantMapping table - const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); - - // Delete from UserRoleMapping table - const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); - + } + + + // Delete from User table + const userResult = await this.usersRepository.delete(userId); + + // Delete from CohortMembers table + const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); + + // Delete from UserTenantMapping table + const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); + + // Delete from UserRoleMapping table + const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); + // Delete from FieldValues table where ItemId matches userId - const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); - + const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); + const keycloakResponse = await getKeycloakAdminToken(); const token = keycloakResponse.data.access_token; - - await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { + + await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { headers: { - 'Authorization': `Bearer ${token}` - }}); - - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "User and related entries deleted Successfully.", - data: { - user: userResult - }, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); - } + 'Authorization': `Bearer ${token}` + } + }); + + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "User and related entries deleted Successfully.", + data: { + user: userResult + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); } + } } diff --git a/src/cohortMembers/cohortMember.service.ts b/src/cohortMembers/cohortMember.service.ts deleted file mode 100644 index ca92ca50..00000000 --- a/src/cohortMembers/cohortMember.service.ts +++ /dev/null @@ -1,295 +0,0 @@ -import { Injectable } from "@nestjs/common"; -import { HttpService } from "@nestjs/axios"; -import { SuccessResponse } from "src/success-response"; -import { ErrorResponse } from "src/error-response"; -const resolvePath = require("object-resolve-path"); -import { CohortMembersDto } from "src/cohortMembers/dto/cohortMembers.dto"; -import { CohortMembersSearchDto } from "src/cohortMembers/dto/cohortMembers-search.dto"; -import { CohortMembers } from "./entities/cohort-member.entity"; -import { InjectRepository } from "@nestjs/typeorm"; -import { IsNull, Not, Repository, getConnection, getRepository } from "typeorm"; -import { CohortDto } from "../cohort/dto/cohort.dto"; -import APIResponse from "src/utils/response"; -import { HttpStatus } from "@nestjs/common"; -import response from "src/utils/response"; -import { User } from "src/user/entities/user-entity"; -import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; - -@Injectable() -export class CohortMembersService { - constructor( - @InjectRepository(CohortMembers) - private cohortMembersRepository: Repository - ) {} - - public async getCohortMembers( - tenantId: string, - cohortMembershipId: any, - response: any, - request: any - ) { - const apiId = "api.cohortMember.getCohortMembers"; - try { - const cohortMembers = await this.cohortMembersRepository.find({ - where: { - cohortMembershipId: cohortMembershipId, - }, - }); - if (!cohortMembers || cohortMembers.length === 0) { - return response - .status(HttpStatus.NOT_FOUND) - .send( - APIResponse.error( - apiId, - `Cohort Member Id is wrong`, - `Cohort Member not found`, - "COHORT_Member_NOT_FOUND" - ) - ); - } - - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - cohortMembers, - "Cohort Member Retrieved Successfully" - ) - ); - } catch (error) { - return response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - "Something went wrong", - `Failure Retrieving Cohort Member. Error is: ${error}`, - "INTERNAL_SERVER_ERROR" - ) - ); - } - } - - public async searchCohortMembers( - tenantId: string, - request: any, - cohortMembersSearchDto: CohortMembersSearchDto, - response: any - ) { - const apiId = "api.cohortMember.searchCohortMembers"; - - try { - let { limit, page, filters } = cohortMembersSearchDto; - - let offset = 0; - if (page > 1) { - offset = limit * (page - 1); - } - - const whereClause = {}; - if (filters && Object.keys(filters).length > 0) { - Object.entries(filters).forEach(([key, value]) => { - whereClause[key] = value; - }); - } - - let findCohortId = await this.findCohortName(whereClause["userId"]); - - let result = { - cohortData: [], - }; - - for (let data of findCohortId) { - let cohortData = { - cohortId: data.cohortId, - name:data.name, - customField: [], - }; - - let filterDetails = { - where: data.cohortId, - take: limit, - skip: offset, - }; - - const getDetails = await this.getUserDetails(filterDetails); - console.log(getDetails); - cohortData.customField.push(getDetails); - - result.cohortData.push(cohortData); - } - - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - result, - "Cohort Member Retrieved Successfully" - ) - ); - } catch (error) { - return response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - "Something went wrong", - `Failure Retrieving Cohort Member. Error is: ${error}`, - "INTERNAL_SERVER_ERROR" - ) - ); - } - } - public async findCohortName(userId: any) { - let query = `SELECT c."name",c."cohortId" - FROM public."CohortMembers" AS cm - LEFT JOIN public."Cohort" AS c ON cm."cohortId" = c."cohortId" - WHERE cm."userId"=$1`; - let result = await this.cohortMembersRepository.query(query, [userId]); - return result; - } - - public async getUserDetails(filter) { - let query = `SELECT DISTINCT f."label", fv."value", f."type", f."fieldParams" - FROM public."CohortMembers" cm - LEFT JOIN ( - SELECT DISTINCT ON (fv."fieldId", fv."itemId") fv.* - FROM public."FieldValues" fv - ) fv ON fv."itemId" = cm."cohortId" - INNER JOIN public."Fields" f ON fv."fieldId" = f."fieldId" - WHERE cm."cohortId" = $1;`; - let result = await this.cohortMembersRepository.query(query, [ - filter.where, - ]); - return result; - } - public async createCohortMembers( - request: any, - cohortMembers: CohortMembersDto, - response: any - ) { - const apiId = "api.cohortMember.createCohortMembers"; - - try { - // Create a new CohortMembers entity and populate it with cohortMembers data - const savedCohortMember = await this.cohortMembersRepository.save( - cohortMembers - ); - - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - savedCohortMember, - "Cohort Member created Successfully" - ) - ); - } catch (error) { - return response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - "Something went wrong", - `Failure creating Cohort Member. Error is: ${error}`, - "INTERNAL_SERVER_ERROR" - ) - ); - } - } - - public async updateCohortMembers( - cohortMembershipId: string, - request: any, - cohortMembersUpdateDto: CohortMembersUpdateDto, - response: any - ) { - const apiId = "api.cohortMember.updateCohortMembers"; - - try { - const cohortMemberToUpdate = await this.cohortMembersRepository.findOne({ - where: { cohortMembershipId: cohortMembershipId }, - }); - - if (!cohortMemberToUpdate) { - throw new Error("Cohort member not found"); - } - Object.assign(cohortMemberToUpdate, cohortMembersUpdateDto); - - const updatedCohortMember = await this.cohortMembersRepository.save( - cohortMemberToUpdate - ); - - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - updatedCohortMember, - "Cohort Member updated Successfully" - ) - ); - } catch (error) { - return response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - "Something went wrong", - `Failure updating Cohort Member. Error is: ${error}`, - "INTERNAL_SERVER_ERROR" - ) - ); - } - } - - public async deleteCohortMemberById( - tenantId: string, - cohortMembershipId: any, - response: any, - request: any - ) { - const apiId = "api.cohortMember.deleteCohortMemberById"; - - try { - const cohortMember = await this.cohortMembersRepository.find({ - where: { - cohortMembershipId: cohortMembershipId, - }, - }); - - if (!cohortMember || cohortMember.length === 0) { - return response.status(HttpStatus.NOT_FOUND).send({ - error: "Cohort member not found", - }); - } - - const result = await this.cohortMembersRepository.delete( - cohortMembershipId - ); - return response - .status(HttpStatus.OK) - .send( - APIResponse.success( - apiId, - result, - "Cohort Member deleted Successfully" - ) - ); - } catch (error) { - return response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - "Something went wrong", - `Failure Retrieving Cohort Member. Error is: ${error}`, - "INTERNAL_SERVER_ERROR" - ) - ); - } - } -} \ No newline at end of file diff --git a/src/cohortMembers/cohortMembers.controller.ts b/src/cohortMembers/cohortMembers.controller.ts index caba9508..ea79131b 100644 --- a/src/cohortMembers/cohortMembers.controller.ts +++ b/src/cohortMembers/cohortMembers.controller.ts @@ -31,8 +31,6 @@ import { CohortMembersSearchDto } from "./dto/cohortMembers-search.dto"; import { Request } from "@nestjs/common"; import { CohortMembersDto } from "./dto/cohortMembers.dto"; import { CohortMembersAdapter } from "./cohortMembersadapter"; -import { CohortMembersService } from "./cohortMember.service"; -// import { Response } from "@nestjs/common"; import { CohortMembersUpdateDto } from "./dto/cohortMember-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { Response } from "express"; @@ -42,12 +40,11 @@ import { Response } from "express"; @UseGuards(JwtAuthGuard) export class CohortMembersController { constructor( - private readonly cohortMembersService: CohortMembersService, private readonly cohortMemberAdapter: CohortMembersAdapter - ) {} + ) { } //create cohort members - @Post() + @Post("/:create") @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @ApiCreatedResponse({ @@ -64,20 +61,15 @@ export class CohortMembersController { @Res() response: Response ) { const loginUser = request.user.userId; - let tenantid = headers["tenantid"]; - const payload = { - tenantId: tenantid, - }; - Object.assign(cohortMembersDto, payload); - + const tenantId = headers["tenantid"]; const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() - .createCohortMembers(loginUser, cohortMembersDto, response); + .createCohortMembers(loginUser, cohortMembersDto, response, tenantId); return response.status(result.statusCode).json(result); } //get cohort members - @Get("/:cohortId") + @Get("/get/:cohortId") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members detail" }) @ApiNotFoundResponse({ description: "Data not found" }) @@ -99,7 +91,7 @@ export class CohortMembersController { const tenantId = headers["tenantid"]; const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() - .getCohortMembers(cohortId,tenantId, fieldvalue, response); + .getCohortMembers(cohortId, tenantId, fieldvalue, response); } // search; @@ -126,11 +118,10 @@ export class CohortMembersController { const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() .searchCohortMembers(cohortMembersSearchDto, tenantId, response); - return response.status(result.statusCode).json(result); } //update - @Put("/:id") + @Put("/update/:id") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort Members has been updated successfully.", @@ -154,11 +145,10 @@ export class CohortMembersController { cohortMemberUpdateDto, response ); - return response.status(result.statusCode).json(result); } //delete - @Delete("/:id") + @Delete("/delete/:id") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Cohort member deleted successfully" }) @ApiNotFoundResponse({ description: "Data not found" }) @@ -178,7 +168,6 @@ export class CohortMembersController { const result = await this.cohortMemberAdapter .buildCohortMembersAdapter() - .deleteCohortMemberById(tenantid, cohortMembershipId, response, request); - return response.status(result.statusCode).json(result); + .deleteCohortMemberById(tenantid, cohortMembershipId, response); } } \ No newline at end of file diff --git a/src/cohortMembers/cohortMembers.module.ts b/src/cohortMembers/cohortMembers.module.ts index f49ab84c..3e175da0 100644 --- a/src/cohortMembers/cohortMembers.module.ts +++ b/src/cohortMembers/cohortMembers.module.ts @@ -5,7 +5,6 @@ import { CohortMembersAdapter } from "./cohortMembersadapter"; import { HasuraModule } from "src/adapters/hasura/hasura.module"; import { TypeOrmModule } from "@nestjs/typeorm"; import { CohortMembers } from "./entities/cohort-member.entity"; -import { CohortMembersService } from "./cohortMember.service"; import { PostgresModule } from "src/adapters/postgres/potsgres-module"; import { PostgresCohortMembersService } from "src/adapters/postgres/cohortMembers-adapter"; import { HasuraCohortMembersService } from "src/adapters/hasura/cohortMembers.adapter"; @@ -23,9 +22,8 @@ import { Cohort } from "src/cohort/entities/cohort.entity"; controllers: [CohortMembersController], providers: [ CohortMembersAdapter, - CohortMembersService, PostgresCohortMembersService, HasuraCohortMembersService, ], }) -export class CohortMembersModule {} \ No newline at end of file +export class CohortMembersModule { } \ No newline at end of file diff --git a/src/cohortMembers/dto/cohortMembers.dto.ts b/src/cohortMembers/dto/cohortMembers.dto.ts index 9abe39ad..9c481d42 100644 --- a/src/cohortMembers/dto/cohortMembers.dto.ts +++ b/src/cohortMembers/dto/cohortMembers.dto.ts @@ -1,6 +1,6 @@ import { Exclude, Expose } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsNotEmpty, IsUUID } from "class-validator"; +import { IsNotEmpty, IsString, IsUUID } from "class-validator"; export class CohortMembersDto { //generated fields From f7d116097937095a6c281d11d198235ae483063a Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Tue, 28 May 2024 20:17:23 +0530 Subject: [PATCH 361/408] PS-634:chore[Changes in response message ] --- src/adapters/postgres/cohort-adapter.ts | 70 ++++++++++++------------- src/fields/fields.controller.ts | 4 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index c52d23a1..59f15ad6 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -64,10 +64,10 @@ export class PostgresCohortService { result.cohortData.push(cohortData); } - return APIResponse.success(res, apiId, result,(HttpStatus.OK), "Cohort list fetched successfully"); + return APIResponse.success(res, apiId, result, (HttpStatus.OK), "Cohort list fetched successfully"); } catch (error) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`, (HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -90,7 +90,7 @@ export class PostgresCohortService { if (checkData === true) { const result = await this.getCohortDataWithCustomfield(cohortId); - return APIResponse.success(res, apiId, result,(HttpStatus.OK), "Cohort details fetched succcessfully."); + return APIResponse.success(res, apiId, result, (HttpStatus.OK), "Cohort details fetched succcessfully."); } else { return APIResponse.error( @@ -103,7 +103,7 @@ export class PostgresCohortService { } } catch (error) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`,(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`, (HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -213,8 +213,8 @@ export class PostgresCohortService { return APIResponse.error( res, apiId, - `Duplicate fieldId`, `Duplicate fieldId '${valid.fieldId}' found in fieldValues.`, + `Duplicate fieldId`, (HttpStatus.CONFLICT) ) } @@ -242,8 +242,8 @@ export class PostgresCohortService { return APIResponse.error( res, apiId, - `Cohort already exist`, `Cohort name already exist for this parent.`, + `Cohort already exists`, (HttpStatus.CONFLICT) ) } @@ -265,8 +265,8 @@ export class PostgresCohortService { return APIResponse.error( res, apiId, - `Cohort already exist`, - `Cohort name already exists.`, + `Cohort name already exists`, + `Duplicate Cohort name`, (HttpStatus.CONFLICT) ) } @@ -295,7 +295,7 @@ export class PostgresCohortService { response = new ReturnResponseBody(response); - return APIResponse.success(res, apiId, response,(HttpStatus.CREATED), "Cohort Created Successfully."); + return APIResponse.success(res, apiId, response, (HttpStatus.CREATED), "Cohort Created Successfully."); } catch (e) { @@ -318,8 +318,8 @@ export class PostgresCohortService { return APIResponse.error( res, apiId, + `Duplicate fieldId '${valid.fieldId}' found in fieldValues`, `Duplicate fieldId`, - `Duplicate fieldId '${valid.fieldId}' found in fieldValues.`, (HttpStatus.CONFLICT) ) } @@ -334,8 +334,8 @@ export class PostgresCohortService { return APIResponse.error( res, apiId, - `Invalid cohortId`, `Please Enter valid cohortId(UUID)`, + `Invalid cohortId`, (HttpStatus.CONFLICT) ) } @@ -374,11 +374,11 @@ export class PostgresCohortService { const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { - return APIResponse.error( + return APIResponse.error( res, apiId, - `Cohort name already exist`, - `Cohort name already exist for this parent please choose another name.`, + `Cohort name already exist for this parent please choose another name`, + `Duplicate cohort name`, (HttpStatus.CONFLICT), ) } @@ -398,11 +398,11 @@ export class PostgresCohortService { const cohortData = await this.cohortRepository.find({ where: { cohortId: cohortId } }) response = cohortData[0]; } else { - return APIResponse.error( + return APIResponse.error( res, apiId, - `Cohort name already exist`, - `Cohort name already exists please choose another name.`, + `Cohort name already exists please choose another name`, + `Duplicate cohort name`, (HttpStatus.CONFLICT) ) } @@ -442,7 +442,7 @@ export class PostgresCohortService { } } - return APIResponse.success(res, apiId, response.affected,(HttpStatus.OK), "Cohort updated successfully."); + return APIResponse.success(res, apiId, response.affected, (HttpStatus.OK), "Cohort updated successfully."); } else { return APIResponse.error( @@ -450,11 +450,11 @@ export class PostgresCohortService { apiId, `Cohort not found`, `Cohort not found`, - (HttpStatus.NOT_FOUND) + (HttpStatus.NOT_FOUND) ) } } catch (e) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`,(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -485,8 +485,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Limit exceeded`, `Limit exceeds maximum allowed value of ${MAX_LIMIT}`, + `Limit exceeded`, (HttpStatus.BAD_REQUEST) ) } @@ -495,8 +495,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Page Limit exceeded`, `Page limit exceeds maximum allowed value of ${PAGE_LIMIT}`, + `Page limit exceeded`, (HttpStatus.BAD_REQUEST) ) } @@ -510,8 +510,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Invalid key in filter`, `${key} Invalid key`, + `Invalid filter key`, (HttpStatus.BAD_REQUEST) ) } else { @@ -529,8 +529,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, + `Invalid User ID format. It must be a valid UUID`, `Invalid userId`, - `Invalid User ID format. It must be a valid UUID.`, (HttpStatus.BAD_REQUEST) ) } @@ -539,8 +539,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Invalid cohortId`, - `Invalid Cohort ID format. It must be a valid UUID.`, + `Invalid Cohort ID format. It must be a valid UUID`, + `Invalid cohortID`, (HttpStatus.BAD_REQUEST) ) } @@ -556,8 +556,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Invalid filters`, - 'When filtering by userId, do not include additional fields.', + `When filtering by userId, do not include additional fields`, + 'Invalid filters', (HttpStatus.BAD_REQUEST) ) } @@ -572,8 +572,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Invalid combination of userId and tenantId`, - 'User is not mapped for this tenant.', + `User is not mapped for this tenant`, + 'Invalid combination of userId and tenantId', (HttpStatus.BAD_REQUEST) ) } @@ -601,7 +601,7 @@ export class PostgresCohortService { } if (results.cohortDetails.length > 0) { - return APIResponse.success(response, apiId, results,(HttpStatus.OK), "Cohort details fetched successfully"); + return APIResponse.success(response, apiId, results, (HttpStatus.OK), "Cohort details fetched successfully"); } else { return APIResponse.error( @@ -635,8 +635,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Invalid cohortId`, - 'Invalid Cohort Id format. It must be a valid UUID.', + `Invalid Cohort Id format. It must be a valid UUID`, + 'Invalid cohortId', (HttpStatus.BAD_REQUEST) ) } @@ -662,8 +662,8 @@ export class PostgresCohortService { return APIResponse.error( response, apiId, - `Invalid cohortId`, - 'Cohort not found', + `Cohort not found`, + 'Invalid cohortId', (HttpStatus.BAD_REQUEST) ) } diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 02f8efa0..9e0a3594 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -106,12 +106,12 @@ export class FieldsController { @Body() fieldValuesDto: FieldValuesDto, @Res() response: Response ) { - const result = await this.fieldsAdapter.buildFieldsAdapter().createFieldValues( + return await this.fieldsAdapter.buildFieldsAdapter().createFieldValues( request, fieldValuesDto, response ); - return result; + } //search fields values From f4ce5082bf706b7acd86d9ba0ff1e4d76976d206 Mon Sep 17 00:00:00 2001 From: poojakarma Date: Tue, 28 May 2024 21:33:48 +0530 Subject: [PATCH 362/408] Changes reponses of Privilege --- .../postgres/rbac/privilege-adapter.ts | 238 +++++++++--------- src/adapters/postgres/rbac/role-adapter.ts | 91 +++---- src/adapters/postgres/user-adapter.ts | 153 +++++------ src/adapters/privilegeservicelocator.ts | 20 +- src/common/filters/exception.filter.ts | 2 +- src/common/responses/response-interface.ts | 13 +- src/common/responses/response.ts | 14 +- src/common/utils/api-id.config.ts | 11 +- src/rbac/privilege/privilege.controller.ts | 31 +-- src/rbac/role/role.controller.ts | 22 +- 10 files changed, 291 insertions(+), 304 deletions(-) diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index be37d61f..b3f6bb6e 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -12,7 +12,9 @@ import { import { isUUID } from "class-validator"; import { RolePrivilegeMapping } from "src/rbac/assign-privilege/entities/assign-privilege.entity"; import { Role } from "src/rbac/role/entities/role.entity"; - +import { Response } from "express"; +import APIResponse from "src/common/responses/response"; +import { APIID } from "src/common/utils/api-id.config"; @Injectable() export class PostgresPrivilegeService { constructor( @@ -22,14 +24,16 @@ export class PostgresPrivilegeService { private rolePrivilegeMappingRepository: Repository, @InjectRepository(Role) private roleRepository: Repository, - ) {} + ) { } public async createPrivilege( loggedinUser: any, - createPrivilegesDto: CreatePrivilegesDto + createPrivilegesDto: CreatePrivilegesDto, + response: Response ) { const privileges = []; const errors = []; + const apiId = APIID.PRIVILEGE_CREATE try { for (const privilegeDto of createPrivilegesDto.privileges) { const code = privilegeDto.code; @@ -53,19 +57,16 @@ export class PostgresPrivilegeService { privileges.push(new PrivilegeResponseDto(response)); } } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.message || "Internal server error", - }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } - - return { - statusCode: HttpStatus.OK, - successCount: privileges.length, - errorCount: errors.length, - privileges, - errors, - }; + return APIResponse.success(response, apiId, + { + successCount: privileges.length, + errorCount: errors.length, + privileges, + errors, + }, + HttpStatus.CREATED, 'Privileges successfully Created') } public async checkExistingPrivilege(code) { @@ -82,36 +83,36 @@ export class PostgresPrivilegeService { } } - public async getPrivilege(privilegeId: string, request: any) { + public async getPrivilege(privilegeId: string, request: any, response: Response) { + const apiId = APIID.PRIVILEGE_BYPRIVILEGEID try { if (!isUUID(privilegeId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid PrivilegeId (UUID)", - }); + return APIResponse.error( + response, + apiId, + `Please Enter valid PrivilegeId (UUID)`, + 'Invalid PrivilegeId (UUID)', + HttpStatus.BAD_REQUEST + ) } const privilege = await this.privilegeRepository.findOne({ where: { privilegeId }, }); if (!privilege) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Privilege not found", - }); + return APIResponse.error( + response, + apiId, + `Privilege not found`, + 'Not found', + HttpStatus.NOT_FOUND + ) } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok.", - // totalCount, - data: privilege, - }); + return APIResponse.success(response, apiId, privilege, + HttpStatus.OK, 'Privilege fetched successfully') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -157,41 +158,39 @@ export class PostgresPrivilegeService { // } // } - public async getAllPrivilege(request) { + public async getAllPrivilege(request, response: Response) { try { - const [result, count] = await this.privilegeRepository.findAndCount(); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok", - totalCount: count, - data: result, - }); + const [privileges, totalCount] = await this.privilegeRepository.findAndCount(); + return APIResponse.success(response, APIID.ROLE_GET, { privileges, totalCount }, HttpStatus.OK, 'privileges fetched successfully') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: "Internal server error", - }); + return APIResponse.error(response, APIID.PRIVILEGE_BYROLEID, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } - public async deletePrivilege(privilegeId: string) { + public async deletePrivilege(privilegeId: string, res: Response) { + const apiId = APIID.PRIVILEGE_DELETE try { if (!isUUID(privilegeId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid (UUID)", - }); + return APIResponse.error( + res, + apiId, + `Please Enter valid (UUID)`, + 'Invalid (UUID)', + HttpStatus.BAD_REQUEST + ) } const privilegeToDelete = await this.privilegeRepository.findOne({ where: { privilegeId: privilegeId }, }); if (!privilegeToDelete) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "Privilege not found", - }); + return APIResponse.error( + res, + apiId, + `Privilege not found`, + 'Not found', + HttpStatus.NOT_FOUND + ) } // Delete the privilege const response = await this.privilegeRepository.delete(privilegeId); @@ -201,89 +200,76 @@ export class PostgresPrivilegeService { await this.rolePrivilegeMappingRepository.delete({ privilegeId: privilegeId, }); + return APIResponse.success(res, APIID.PRIVILEGE_DELETE, { rowCount: response.affected }, HttpStatus.OK, 'Privilege deleted successfully.') - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Privilege deleted successfully.", - data: { - rowCount: response.affected, - }, - }); } catch (e) { - console.log(e); - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: "Internal server error", - }); + return APIResponse.error(res, APIID.PRIVILEGE_DELETE, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } -} - - public async getPrivilegebyRoleId(tenantId, roleId, request) { - - if (!isUUID(tenantId) || !isUUID(roleId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please Enter valid tenantId and roleId (UUID)", - }); - } + } - try { - const valid = await this.checkValidTenantIdRoleIdCombination(tenantId, roleId) + public async getPrivilegebyRoleId(tenantId, roleId, request, response: Response) { + const apiId = APIID.PRIVILEGE_BYROLEID + if (!isUUID(tenantId) || !isUUID(roleId)) { + return APIResponse.error( + response, + apiId, + `Please Enter valid tenantId and roleId (UUID)`, + 'Invalid Tenant Id or Role Id', + HttpStatus.BAD_REQUEST + ) + } - if (!valid) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Invalid combination of roleId and tenantId", - }); - } + try { + const valid = await this.checkValidTenantIdRoleIdCombination(tenantId, roleId) + if (!valid) { + return APIResponse.error( + response, + apiId, + `Invalid combination of roleId and tenantId`, + 'Invalid roleId or tenantId ', + HttpStatus.BAD_REQUEST + ) + } - let query = `SELECT r.*, u.* + let query = `SELECT r.*, u.* FROM public."RolePrivilegesMapping" AS r inner JOIN public."Privileges" AS u ON r."privilegeId" = u."privilegeId" where r."roleId"=$1` - const result = await this.privilegeRepository.query(query, [roleId]); - const privilegeResponseArray: PrivilegeResponseDto[] = result.map((item: any) => { - const privilegeDto = new PrivilegeDto(item); - privilegeDto.title = item.name - return new PrivilegeResponseDto(privilegeDto); - }); - - if (!privilegeResponseArray.length) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "No privileges assigned to the role", - }); - } - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Ok", - data: privilegeResponseArray - }); - } - catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); - } - + const result = await this.privilegeRepository.query(query, [roleId]); + const privilegeResponseArray: PrivilegeResponseDto[] = result.map((item: any) => { + const privilegeDto = new PrivilegeDto(item); + privilegeDto.title = item.name + return new PrivilegeResponseDto(privilegeDto); + }); + if (!privilegeResponseArray.length) { + APIResponse.error( + response, + apiId, + `No privileges assigned to the role`, + 'Not found', + HttpStatus.NOT_FOUND + ) + } + return APIResponse.success(response, apiId, privilegeResponseArray, HttpStatus.OK, 'privilege fetched successfully by Role Id') } + catch (error) { + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${error}`, HttpStatus.INTERNAL_SERVER_ERROR); + } + } - public async checkValidTenantIdRoleIdCombination(tenantId, roleId) { - try { - - const ValidTenantIdRoleCombination = await this.roleRepository.findOne({ where: { tenantId: tenantId, roleId: roleId } }); - return ValidTenantIdRoleCombination; - } - catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); - } + public async checkValidTenantIdRoleIdCombination(tenantId, roleId) { + try { + const ValidTenantIdRoleCombination = await this.roleRepository.findOne({ where: { tenantId: tenantId, roleId: roleId } }); + return ValidTenantIdRoleCombination; } + catch (error) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: error, + }); + } + } } diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index 4cb4dd2e..bd1ca03b 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -1,4 +1,4 @@ -import { ConsoleLogger, HttpStatus, Injectable } from "@nestjs/common"; +import { HttpStatus, Injectable } from "@nestjs/common"; import { Role } from "src/rbac/role/entities/role.entity"; import { RolePrivilegeMapping } from "src/rbac/assign-privilege/entities/assign-privilege.entity"; import { InjectRepository } from "@nestjs/typeorm"; @@ -8,14 +8,13 @@ import { RoleDto, RolesResponseDto, } from "../../../rbac/role/dto/role.dto"; -import { SuccessResponse } from "src/success-response"; -import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { RoleSearchDto } from "../../../rbac/role/dto/role-search.dto"; import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entity"; import { Privilege } from "src/rbac/privilege/entities/privilege.entity"; import { isUUID } from "class-validator"; import APIResponse from "src/common/responses/response"; import { Response } from 'express'; +import { APIID } from 'src/common/utils/api-id.config' @Injectable() export class PostgresRoleService { @@ -28,15 +27,15 @@ export class PostgresRoleService { private readonly roleprivilegeMappingRepository: Repository ) { } public async createRole(request: any, createRolesDto: CreateRolesDto, response: Response) { - const apiId = 'api.create.role' + const apiId = APIID.ROLE_CREATE const tenant = await this.checkTenantID(createRolesDto.tenantId) if (!tenant) { - APIResponse.error( + return APIResponse.error( response, apiId, `Please enter valid tenantId`, 'Invalid Tenant Id', - String(HttpStatus.BAD_REQUEST) + HttpStatus.BAD_REQUEST ) } const roles = []; @@ -75,39 +74,38 @@ export class PostgresRoleService { roles.push(new RolesResponseDto(response)); } } catch (e) { - APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } - APIResponse.success(response, apiId, { successCount: roles.length, errorCount: errors.length, roles, errors }, - String(HttpStatus.OK), 'Role successfully Created') + return APIResponse.success(response, apiId, { successCount: roles.length, errorCount: errors.length, roles, errors }, + HttpStatus.OK, 'Role successfully Created') } public async getRole(roleId: string, request: any, response: Response) { - const apiId = 'api.get.role'; + const apiId = APIID.ROLE_GET try { const [roles, totalCount] = await this.roleRepository.findAndCount({ where: { roleId }, }); - APIResponse.success(response, apiId, { roles, totalCount }, String(HttpStatus.OK), 'Roles fetched successfully') + return APIResponse.success(response, apiId, { roles, totalCount }, HttpStatus.OK, 'Roles fetched successfully') } catch (e) { - APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } public async updateRole(roleId: string, request: any, roleDto: RoleDto, response: Response) { - const apiId = 'api.update.role'; + const apiId = APIID.ROLE_UPDATE try { - const code = roleDto.title.toLowerCase().replace(/\s+/g, '_'); roleDto.code = code; const result = await this.roleRepository.update(roleId, roleDto); - APIResponse.success(response, apiId, { rowCount: result.affected, }, String(HttpStatus.OK), 'Roles Updated successful') + return APIResponse.success(response, apiId, { rowCount: result.affected, }, HttpStatus.OK, 'Roles Updated successful') } catch (e) { - APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } public async searchRole(roleSearchDto: RoleSearchDto, response: Response) { - const apiId = 'api.search.Role'; + const apiId = APIID.ROLE_SEARCH try { let { limit, page, filters } = roleSearchDto; @@ -127,21 +125,21 @@ export class PostgresRoleService { }); } if (whereClause.userId && !whereClause.tenantId) { - APIResponse.error( + return APIResponse.error( response, - apiId, + APIID.ROLE_SEARCH, `Please Enter Tenenat id or Valid Filter`, 'Invalid Tenant Id or Valid Filter', - String(HttpStatus.BAD_REQUEST) + HttpStatus.BAD_REQUEST ) } if (whereClause.field && !["Privilege"].includes(whereClause?.field)) { - APIResponse.error( + return APIResponse.error( response, - apiId, + APIID.ROLE_SEARCH, `Please Enter valid field value.`, 'Invalid field value.', - String(HttpStatus.BAD_REQUEST) + HttpStatus.BAD_REQUEST ) } if (whereClause.userId && whereClause.tenantId && whereClause.field === "Privilege") { @@ -159,10 +157,10 @@ export class PostgresRoleService { privileges: roleResult ? roleResult : [] }; }); - APIResponse.success(response, apiId, roles, String(HttpStatus.OK), 'Role For User with Privileges fetched successfully.') + return APIResponse.success(response, apiId, roles, HttpStatus.OK, 'Role For User with Privileges fetched successfully.') } else if (whereClause.userId && whereClause.tenantId && !whereClause.field) { const data = await this.findUserRoleData(whereClause.userId, whereClause.tenantId) - APIResponse.success(response, apiId, data, String(HttpStatus.OK), 'Role For User Id fetched successfully.') + return APIResponse.success(response, apiId, data, HttpStatus.OK, 'Role For User Id fetched successfully.') } else if (whereClause.tenantId && whereClause.field === "Privilege") { const userRoleData = await this.findRoleData(whereClause.tenantId); @@ -176,34 +174,34 @@ export class PostgresRoleService { privileges: roleResult ? roleResult : [] }; }); - APIResponse.success(response, apiId, roles, String(HttpStatus.OK), 'Role For Tenant with Privileges fetched successfully.') + return APIResponse.success(response, apiId, roles, HttpStatus.OK, 'Role For Tenant with Privileges fetched successfully.') } else if (whereClause.tenantId && !whereClause.field) { const data = await this.findRoleData(whereClause.tenantId); - APIResponse.success(response, apiId, data, String(HttpStatus.OK), 'Role For Tenant fetched successfully.') + return APIResponse.success(response, apiId, data, HttpStatus.OK, 'Role For Tenant fetched successfully.') } else { - APIResponse.error( + return APIResponse.error( response, - apiId, + APIID.ROLE_SEARCH, `Please Enter Valid Filter`, 'Invalid Filter', - String(HttpStatus.BAD_REQUEST) + HttpStatus.BAD_REQUEST ) } } catch (e) { - APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } public async deleteRole(roleId: string, res: Response) { - const apiId = 'api.delete.role'; + const apiId = APIID.ROLE_DELETE try { if (!isUUID(roleId)) { - APIResponse.error( + return APIResponse.error( res, apiId, `Please Enter valid (UUID)`, 'Invalid UUID', - String(HttpStatus.BAD_REQUEST) + HttpStatus.BAD_REQUEST ) } @@ -212,12 +210,12 @@ export class PostgresRoleService { }); if (!roleToDelete) { - APIResponse.error( + return APIResponse.error( res, apiId, `Role not found`, 'Not found', - String(HttpStatus.NOT_FOUND) + HttpStatus.NOT_FOUND ) } // Delete the role @@ -233,9 +231,9 @@ export class PostgresRoleService { await this.userRoleMappingRepository.delete({ roleId: roleId, }); - APIResponse.success(res, apiId, { rowCount: response.affected }, String(HttpStatus.OK), 'Role deleted successfully.') + return APIResponse.success(res, apiId, { rowCount: response.affected }, HttpStatus.OK, 'Role deleted successfully.') } catch (e) { - APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -276,19 +274,12 @@ export class PostgresRoleService { } public async checkTenantID(tenantId) { - try { - let query = `SELECT "tenantId" FROM public."Tenants" + let query = `SELECT "tenantId" FROM public."Tenants" where "tenantId"= $1 `; - let response = await this.roleRepository.query(query, [tenantId]); - if (response.length > 0) { - return true; - } - } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); + let response = await this.roleRepository.query(query, [tenantId]); + if (response.length > 0) { + return true; } - + return false; } } diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 8935378f..5ac4d130 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -54,7 +54,7 @@ export class PostgresUserService { @InjectRepository(Role) private roleRepository: Repository, ) { } - + async searchUser(tenantId: string, request: any, response: any, @@ -67,7 +67,7 @@ export class PostgresUserService { // statusCode: HttpStatus.BAD_REQUEST, // message: 'Either Filter is wrong or No Data Found For the User', // }); - return APIResponse.error(response, apiId, "Bad request", `Either Filter is wrong or No Data Found For the User`, String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(response, apiId, "Bad request", `Either Filter is wrong or No Data Found For the User`, HttpStatus.BAD_REQUEST); } // return new SuccessResponse({ // statusCode: HttpStatus.OK, @@ -75,13 +75,13 @@ export class PostgresUserService { // data: findData, // }); return await APIResponse.success(response, apiId, findData, - String(HttpStatus.OK), 'User List fetched.') + HttpStatus.OK, 'User List fetched.') } catch (e) { // return new ErrorResponseTypeOrm({ // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: e, // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -119,7 +119,7 @@ export class PostgresUserService { // statusCode: HttpStatus.BAD_REQUEST, // message: 'Please Enter Valid UUID', // }); - return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID`, String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID`, HttpStatus.BAD_REQUEST); } const checkExistUser = await this.usersRepository.find({ where: { @@ -160,18 +160,18 @@ export class PostgresUserService { // statusCode: HttpStatus.NOT_FOUND, // message: 'User Not Found', // }); - return APIResponse.error(response, apiId, "Not Found", `User Not Found`, String(HttpStatus.NOT_FOUND)); - } + return APIResponse.error(response, apiId, "Not Found", `User Not Found`, HttpStatus.NOT_FOUND); + } if (!userData.fieldValue) { // new SuccessResponse({ // statusCode: HttpStatus.OK, // message: 'Ok.', // data: userDetails, // }); - return await APIResponse.success(response, apiId, {userData: userDetails}, - String(HttpStatus.OK), 'User details Fetched Successfully.') - } - const customFields = await this.findCustomFields(userData,roleInUpper) + return await APIResponse.success(response, apiId, { userData: userDetails }, + HttpStatus.OK, 'User details Fetched Successfully.') + } + const customFields = await this.findCustomFields(userData, roleInUpper) result.userData = userDetails; const filledValuesMap = new Map(filledValues.map(item => [item.fieldId, item.value])); @@ -201,14 +201,14 @@ export class PostgresUserService { // message: 'User details Fetched Successfully.', // data: result, // }); - return await APIResponse.success(response, apiId, {...result}, - String(HttpStatus.OK), 'User details Fetched Successfully.') + return await APIResponse.success(response, apiId, { ...result }, + HttpStatus.OK, 'User details Fetched Successfully.') } catch (e) { // new ErrorResponseTypeOrm({ // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: e, // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -425,13 +425,13 @@ export class PostgresUserService { // error: errorMessage // }); return await APIResponse.success(response, apiId, updatedData, - String(HttpStatus.OK), "User has been updated successfully.") + HttpStatus.OK, "User has been updated successfully.") } catch (e) { // return new ErrorResponseTypeOrm({ // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: e, // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -487,10 +487,10 @@ export class PostgresUserService { // statusCode: HttpStatus.CONFLICT, // errorMessage: "Duplicate fieldId found in fieldValues.", // }); - return APIResponse.error(response, apiId, "Conflict", `Duplicate fieldId found in fieldValues.`, String(HttpStatus.CONFLICT)); + return APIResponse.error(response, apiId, "Conflict", `Duplicate fieldId found in fieldValues.`, HttpStatus.CONFLICT); } } - + // check and validate all fields let validateBodyFields = await this.validateBodyFields(userCreateDto) @@ -510,7 +510,7 @@ export class PostgresUserService { // statusCode: HttpStatus.FORBIDDEN, // errorMessage: "User Already Exist", // }); - return APIResponse.error(response, apiId, "Forbidden", `User Already Exist`, String(HttpStatus.FORBIDDEN)); + return APIResponse.error(response, apiId, "Forbidden", `User Already Exist`, HttpStatus.FORBIDDEN); } resKeycloak = await createUserInKeyCloak(userSchema, token).catch( (error) => { @@ -519,7 +519,7 @@ export class PostgresUserService { // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: error, // }); - return APIResponse.error(response, apiId, "Internal Server Error",`${errKeycloak}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `${errKeycloak}`, HttpStatus.INTERNAL_SERVER_ERROR); } ); userCreateDto.userId = resKeycloak; @@ -543,19 +543,19 @@ export class PostgresUserService { // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: `Error is ${result}`, // }); - return APIResponse.error(response, apiId, "Internal Server Error",`Error is ${result}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${result}`, HttpStatus.INTERNAL_SERVER_ERROR); } } } } - + // return new SuccessResponse({ // statusCode: 200, // message: "User has been created successfully.", // data: result, // }); - APIResponse.success(response, apiId, {userData: result}, - String(HttpStatus.CREATED), "User has been created successfully.") + APIResponse.success(response, apiId, { userData: result }, + HttpStatus.CREATED, "User has been created successfully.") } } catch (e) { if (e instanceof ErrorResponseTypeOrm) { @@ -565,7 +565,7 @@ export class PostgresUserService { // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, // errorMessage: e.toString(), // or any custom error message you want // }); - return APIResponse.error(response, apiId, "Internal Server Error",`Error is ${e}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); } } } @@ -752,7 +752,7 @@ export class PostgresUserService { // errorCode: `404`, // errorMessage: "User with given username not found", // }); - return APIResponse.error(response, apiId, "Not Found", `User with given username not found`, String(HttpStatus.NOT_FOUND)); + return APIResponse.error(response, apiId, "Not Found", `User with given username not found`, HttpStatus.NOT_FOUND); } // const data = JSON.stringify({ @@ -777,7 +777,7 @@ export class PostgresUserService { // errorCode: `${e.response.status}`, // errorMessage: e.response.data.error, // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, HttpStatus.INTERNAL_SERVER_ERROR); } if (apiResponse.statusCode === 204) { @@ -787,17 +787,17 @@ export class PostgresUserService { // data: apiResponse.data, // }); return await APIResponse.success(response, apiId, {}, - String(HttpStatus.NO_CONTENT), 'User Password Updated Successfully.') + HttpStatus.NO_CONTENT, 'User Password Updated Successfully.') } else { // return new ErrorResponse({ // errorCode: "400", // errorMessage: apiResponse.errors, // }); - return APIResponse.error(response, apiId, "Bad Request", `Error : ${apiResponse?.errors}`, String(HttpStatus.BAD_REQUEST)); + return APIResponse.error(response, apiId, "Bad Request", `Error : ${apiResponse?.errors}`, HttpStatus.BAD_REQUEST); } } catch (e) { // return e; - return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -870,42 +870,42 @@ export class PostgresUserService { }; } - public async deleteUserById(userId: string,response: Response){ + public async deleteUserById(userId: string, response: Response) { const apiId = APIID.USER_DELETE; const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; - // Validate userId format - if (!isUUID(userId)) { + // Validate userId format + if (!isUUID(userId)) { // return new ErrorResponseTypeOrm({ // statusCode: HttpStatus.BAD_REQUEST, // errorMessage: "Please enter a valid UUID for userId", // }); - return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID for userId`, String(HttpStatus.BAD_REQUEST)); - } - - try { - // Check if user exists in usersRepository - const user = await this.usersRepository.findOne({ where :{userId:userId}}); - if (!user) { + return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID for userId`, HttpStatus.BAD_REQUEST); + } + + try { + // Check if user exists in usersRepository + const user = await this.usersRepository.findOne({ where: { userId: userId } }); + if (!user) { // return new ErrorResponseTypeOrm({ // statusCode: HttpStatus.NOT_FOUND, // errorMessage: "User not found in user table.", // }); - return APIResponse.error(response, apiId, "Not Found", `User not found in user table.`, String(HttpStatus.NOT_FOUND)); - } - - - // Delete from User table - const userResult = await this.usersRepository.delete(userId); - - // Delete from CohortMembers table - const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); - - // Delete from UserTenantMapping table - const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); - - // Delete from UserRoleMapping table - const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); - + return APIResponse.error(response, apiId, "Not Found", `User not found in user table.`, HttpStatus.NOT_FOUND); + } + + + // Delete from User table + const userResult = await this.usersRepository.delete(userId); + + // Delete from CohortMembers table + const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); + + // Delete from UserTenantMapping table + const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); + + // Delete from UserRoleMapping table + const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); + // Delete from FieldValues table where ItemId matches userId const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); @@ -914,25 +914,26 @@ export class PostgresUserService { await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { headers: { - 'Authorization': `Bearer ${token}` - }}); - - - // return new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: "User and related entries deleted Successfully.", - // data: { - // user: userResult - // }, - // }); - return await APIResponse.success(response, apiId, userResult, - String(HttpStatus.OK), "User and related entries deleted Successfully.") - } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, String(HttpStatus.INTERNAL_SERVER_ERROR)); - } + 'Authorization': `Bearer ${token}` + } + }); + + + // return new SuccessResponse({ + // statusCode: HttpStatus.OK, + // message: "User and related entries deleted Successfully.", + // data: { + // user: userResult + // }, + // }); + return await APIResponse.success(response, apiId, userResult, + HttpStatus.OK, "User and related entries deleted Successfully.") + } catch (e) { + // return new ErrorResponseTypeOrm({ + // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + // errorMessage: e, + // }); + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, HttpStatus.INTERNAL_SERVER_ERROR); } + } } diff --git a/src/adapters/privilegeservicelocator.ts b/src/adapters/privilegeservicelocator.ts index d36fa01c..09cdec306 100644 --- a/src/adapters/privilegeservicelocator.ts +++ b/src/adapters/privilegeservicelocator.ts @@ -2,16 +2,18 @@ import { CreatePrivilegesDto, PrivilegeDto, } from "src/rbac/privilege/dto/privilege.dto"; +import { Response } from "express"; export interface IServicelocator { - createPrivilege(loggedinUser: any, createPrivileges: CreatePrivilegesDto); - getPrivilege( - privilegeId?: string, - request?: any, - ); - // updatePrivilege(privilegeId, request, privilegeDto) - getAllPrivilege(request:any) - getPrivilegebyRoleId(tenantId:string, roleId:string,request:any) + createPrivilege(loggedinUser: any, createPrivileges: CreatePrivilegesDto, response?: Response); + getPrivilege( + privilegeId?: string, + request?: any, + response?: Response + ); // updatePrivilege(privilegeId, request, privilegeDto) - deletePrivilege(privilegeId); + getAllPrivilege(request: any, response?: Response) + getPrivilegebyRoleId(tenantId: string, roleId: string, request: any, response?: Response) + // updatePrivilege(privilegeId, request, privilegeDto) + deletePrivilege(privilegeId, response?: Response); } diff --git a/src/common/filters/exception.filter.ts b/src/common/filters/exception.filter.ts index f9817cd7..9c487220 100644 --- a/src/common/filters/exception.filter.ts +++ b/src/common/filters/exception.filter.ts @@ -21,7 +21,7 @@ export class AllExceptionsFilter implements ExceptionFilter { this.apiId, detailedErrorMessage, exception instanceof HttpException ? exception.name : 'InternalServerError', // error - status.toString() + status ); } } \ No newline at end of file diff --git a/src/common/responses/response-interface.ts b/src/common/responses/response-interface.ts index 86394aa1..c6b61917 100644 --- a/src/common/responses/response-interface.ts +++ b/src/common/responses/response-interface.ts @@ -1,34 +1,25 @@ import { IsOptional } from "class-validator"; - // structure for server responses export interface ServerResponse { // api id id: string; - // response param params: Params; - // response code - responseCode: string; - + responseCode: number; //server result result: any; - // time stamp ts: string; - // api version ver: string; - headers?: any; - response: any; } - export interface Params { resmsgid: string; err?: any; status: string; errmsg?: any; successmessage?: string; -} +} \ No newline at end of file diff --git a/src/common/responses/response.ts b/src/common/responses/response.ts index cf50feef..4877467b 100644 --- a/src/common/responses/response.ts +++ b/src/common/responses/response.ts @@ -1,13 +1,12 @@ import { v4 } from 'uuid'; import { Params } from './response-interface'; import { Response } from 'express'; - export default class APIResponse { public static success( response: Response, id: string, result: Type, - statusCode: string, + statusCode: number, successmessage: string ) { try { @@ -18,7 +17,6 @@ export default class APIResponse { errmsg: null, successmessage: successmessage }; - const resObj = { id, ver: '1.0', @@ -27,18 +25,17 @@ export default class APIResponse { responseCode: statusCode, result, }; - return response.status(Number(statusCode)).json(resObj); + return response.status(statusCode).json(resObj); } catch (e) { return e; } } - public static error( response: Response, id: string, errmsg: string, error: string, - statusCode: string, + statusCode: number, ) { try { const params: Params = { @@ -47,7 +44,6 @@ export default class APIResponse { err: error, errmsg: errmsg, }; - const resObj = { id, ver: '1.0', @@ -56,9 +52,9 @@ export default class APIResponse { responseCode: statusCode, result: {}, }; - return response.status(Number(statusCode)).json(resObj); + return response.status(statusCode).json(resObj); } catch (e) { return e; } } -} +} \ No newline at end of file diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index 5caf0de4..a3612241 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -4,5 +4,14 @@ export const APIID = { USER_UPDATE: "api.user.update", USER_LIST: "api.user.list", USER_RESET_PASSWORD: "api.user.resetPassword", - USER_DELETE: "api.user.delete" + USER_DELETE: "api.user.delete", + ROLE_GET: "api.role.get", + ROLE_CREATE: "api.role.create", + ROLE_UPDATE: "api.role.update", + ROLE_SEARCH: "api.role.search", + ROLE_DELETE: "api.role.delete", + PRIVILEGE_BYROLEID: "api.privilegebyRoleId.get", + PRIVILEGE_BYPRIVILEGEID: 'api.privilegebyPrivilegeId.get', + PRIVILEGE_CREATE: 'api.privilege.create', + PRIVILEGE_DELETE: 'api.privilege.delete' } diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index 69bdf25a..f7fed339 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -16,6 +16,7 @@ import { Delete, UseGuards, Query, + UseFilters, } from "@nestjs/common"; import { ApiTags, @@ -35,30 +36,33 @@ import { Response, response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { PrivilegeAdapter } from "./privilegeadapter"; import { v4 as uuidv4 } from "uuid"; +import { AllExceptionsFilter } from "src/common/filters/exception.filter"; +import { APIID } from "src/common/utils/api-id.config"; @UseGuards(JwtAuthGuard) @ApiTags("rbac") @Controller('rbac/privileges') export class PrivilegeController { - constructor(private readonly privilegeAdapter: PrivilegeAdapter) {} + constructor(private readonly privilegeAdapter: PrivilegeAdapter) { } + @UseFilters(new AllExceptionsFilter(APIID.PRIVILEGE_BYROLEID)) @Get() @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Privilege Detail." }) @ApiBadRequestResponse({ description: "Bad Request" }) @ApiInternalServerErrorResponse({ description: "Internal Server Error" }) - @SerializeOptions({strategy: "excludeAll",}) + @SerializeOptions({ strategy: "excludeAll", }) public async getPrivilegebyRoleId( @Query("tenantId") tenantId: string, @Query("roleId") roleId: string, @Req() request: Request, @Res() response: Response ) { - const result = await this.privilegeAdapter.buildPrivilegeAdapter().getPrivilegebyRoleId(tenantId, roleId,request); - return response.status(result.statusCode).json(result); + return await this.privilegeAdapter.buildPrivilegeAdapter().getPrivilegebyRoleId(tenantId, roleId, request, response); } + @UseFilters(new AllExceptionsFilter(APIID.PRIVILEGE_BYPRIVILEGEID)) @Get("/:privilegeId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Privilege Detail." }) @@ -71,15 +75,15 @@ export class PrivilegeController { @Req() request: Request, @Res() response: Response ) { - const result = await this.privilegeAdapter + return await this.privilegeAdapter .buildPrivilegeAdapter() - .getPrivilege(privilegeId, request); - return response.status(result.statusCode).json(result); + .getPrivilege(privilegeId, request, response); } + @UseFilters(new AllExceptionsFilter(APIID.PRIVILEGE_CREATE)) @Post("/create") @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @@ -96,10 +100,9 @@ export class PrivilegeController { @Body() createPrivilegesDto: CreatePrivilegesDto, @Res() response: Response ) { - const result = await this.privilegeAdapter + return await this.privilegeAdapter .buildPrivilegeAdapter() - .createPrivilege(request.user.userId, createPrivilegesDto); - return response.status(result.statusCode).json(result); + .createPrivilege(request.user.userId, createPrivilegesDto, response); } // @Put("/:id") @@ -136,7 +139,8 @@ export class PrivilegeController { // const result = await this.privilegeAdapter.buildPrivilegeAdapter().getAllPrivilege(request); // return response.status(result.statusCode).json(result); // } - + + @UseFilters(new AllExceptionsFilter(APIID.PRIVILEGE_DELETE)) @Delete("/:id") @ApiBasicAuth("access-token") @ApiHeader({ name: "tenantid" }) @@ -147,9 +151,8 @@ export class PrivilegeController { @Param("privilegeId") privilegeId: string, @Res() response: Response ) { - const result = await this.privilegeAdapter + return await this.privilegeAdapter .buildPrivilegeAdapter() - .deletePrivilege(privilegeId); - return response.status(result.statusCode).json(result); + .deletePrivilege(privilegeId, response); } } diff --git a/src/rbac/role/role.controller.ts b/src/rbac/role/role.controller.ts index 10444ca3..66b09a06 100644 --- a/src/rbac/role/role.controller.ts +++ b/src/rbac/role/role.controller.ts @@ -13,6 +13,8 @@ import { Headers, Delete, UseGuards, + UseFilters, + ParseUUIDPipe, } from "@nestjs/common"; import { ApiTags, @@ -31,7 +33,8 @@ import { RoleSearchDto } from "./dto/role-search.dto"; import { Response } from "express"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { RoleAdapter } from "./roleadapter" - +import { AllExceptionsFilter } from "src/common/filters/exception.filter"; +import { APIID } from 'src/common/utils/api-id.config'; @ApiTags("rbac") @Controller("rbac/roles") @UseGuards(JwtAuthGuard) @@ -39,6 +42,7 @@ export class RoleController { constructor(private readonly roleAdapter: RoleAdapter) { } //Get role + @UseFilters(new AllExceptionsFilter(APIID.ROLE_GET)) @Get("read/:id") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Role Detail." }) @@ -46,14 +50,15 @@ export class RoleController { @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({ strategy: "excludeAll", }) public async getRole( - @Param("id") roleId: string, + @Param("id", ParseUUIDPipe) roleId: string, @Req() request: Request, @Res() response: Response ) { - await this.roleAdapter.buildRbacAdapter().getRole(roleId, request, response); + return await this.roleAdapter.buildRbacAdapter().getRole(roleId, request, response); } //Create role + @UseFilters(new AllExceptionsFilter(APIID.ROLE_CREATE)) @Post("/create") @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") @@ -66,10 +71,11 @@ export class RoleController { @Body() createRolesDto: CreateRolesDto, @Res() response: Response ) { - await this.roleAdapter.buildRbacAdapter().createRole(request, createRolesDto, response); + return await this.roleAdapter.buildRbacAdapter().createRole(request, createRolesDto, response); } //Update Role + @UseFilters(new AllExceptionsFilter(APIID.ROLE_UPDATE)) @Put("update/:id") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role updated successfully." }) @@ -82,10 +88,11 @@ export class RoleController { @Body() roleDto: RoleDto, @Res() response: Response ) { - await this.roleAdapter.buildRbacAdapter().updateRole(roleId, request, roleDto, response) + return await this.roleAdapter.buildRbacAdapter().updateRole(roleId, request, roleDto, response) } // search Role + @UseFilters(new AllExceptionsFilter(APIID.ROLE_SEARCH)) @Post("list/roles") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Role List." }) @@ -101,10 +108,11 @@ export class RoleController { @Res() response: Response ) { // let tenantid = headers["tenantid"]; - await this.roleAdapter.buildRbacAdapter().searchRole(roleSearchDto, response); + return await this.roleAdapter.buildRbacAdapter().searchRole(roleSearchDto, response); } //delete role + @UseFilters(new AllExceptionsFilter(APIID.ROLE_DELETE)) @Delete("delete/:roleId") @ApiBasicAuth("access-token") @ApiHeader({ name: "tenantid" }) @@ -115,6 +123,6 @@ export class RoleController { @Param("roleId") roleId: string, @Res() response: Response ) { - await this.roleAdapter.buildRbacAdapter().deleteRole(roleId, response); + return await this.roleAdapter.buildRbacAdapter().deleteRole(roleId, response); } } From 75fffd64a3a95b7d91164c13f90e780a2088c1a1 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 29 May 2024 09:39:12 +0530 Subject: [PATCH 363/408] resolve conflict --- src/cohortMembers/dto/cohortMembers.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cohortMembers/dto/cohortMembers.dto.ts b/src/cohortMembers/dto/cohortMembers.dto.ts index 9c481d42..9abe39ad 100644 --- a/src/cohortMembers/dto/cohortMembers.dto.ts +++ b/src/cohortMembers/dto/cohortMembers.dto.ts @@ -1,6 +1,6 @@ import { Exclude, Expose } from "class-transformer"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -import { IsNotEmpty, IsString, IsUUID } from "class-validator"; +import { IsNotEmpty, IsUUID } from "class-validator"; export class CohortMembersDto { //generated fields From 74320c561d5a3e180d9294420b02b3717349fe46 Mon Sep 17 00:00:00 2001 From: poojakarma Date: Wed, 29 May 2024 10:15:03 +0530 Subject: [PATCH 364/408] Resolved comments --- .../postgres/rbac/privilege-adapter.ts | 19 ++++++++++++------- src/adapters/postgres/rbac/role-adapter.ts | 15 ++++++++++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index b3f6bb6e..5c8fe26d 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -57,7 +57,8 @@ export class PostgresPrivilegeService { privileges.push(new PrivilegeResponseDto(response)); } } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } return APIResponse.success(response, apiId, { @@ -78,7 +79,7 @@ export class PostgresPrivilegeService { } catch (error) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, + errorMessage: error.message || "Internal server error", }); } } @@ -112,7 +113,8 @@ export class PostgresPrivilegeService { return APIResponse.success(response, apiId, privilege, HttpStatus.OK, 'Privilege fetched successfully') } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -163,7 +165,8 @@ export class PostgresPrivilegeService { const [privileges, totalCount] = await this.privilegeRepository.findAndCount(); return APIResponse.success(response, APIID.ROLE_GET, { privileges, totalCount }, HttpStatus.OK, 'privileges fetched successfully') } catch (e) { - return APIResponse.error(response, APIID.PRIVILEGE_BYROLEID, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(response, APIID.PRIVILEGE_BYROLEID, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -203,7 +206,8 @@ export class PostgresPrivilegeService { return APIResponse.success(res, APIID.PRIVILEGE_DELETE, { rowCount: response.affected }, HttpStatus.OK, 'Privilege deleted successfully.') } catch (e) { - return APIResponse.error(res, APIID.PRIVILEGE_DELETE, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(res, APIID.PRIVILEGE_DELETE, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -255,7 +259,8 @@ export class PostgresPrivilegeService { return APIResponse.success(response, apiId, privilegeResponseArray, HttpStatus.OK, 'privilege fetched successfully by Role Id') } catch (error) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${error}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -267,7 +272,7 @@ export class PostgresPrivilegeService { catch (error) { return new ErrorResponseTypeOrm({ statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, + errorMessage: error.message || "Internal server error", }); } } diff --git a/src/adapters/postgres/rbac/role-adapter.ts b/src/adapters/postgres/rbac/role-adapter.ts index bd1ca03b..e229884d 100644 --- a/src/adapters/postgres/rbac/role-adapter.ts +++ b/src/adapters/postgres/rbac/role-adapter.ts @@ -74,7 +74,8 @@ export class PostgresRoleService { roles.push(new RolesResponseDto(response)); } } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } return APIResponse.success(response, apiId, { successCount: roles.length, errorCount: errors.length, roles, errors }, HttpStatus.OK, 'Role successfully Created') @@ -88,7 +89,8 @@ export class PostgresRoleService { }); return APIResponse.success(response, apiId, { roles, totalCount }, HttpStatus.OK, 'Roles fetched successfully') } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -100,7 +102,8 @@ export class PostgresRoleService { const result = await this.roleRepository.update(roleId, roleDto); return APIResponse.success(response, apiId, { rowCount: result.affected, }, HttpStatus.OK, 'Roles Updated successful') } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -188,7 +191,8 @@ export class PostgresRoleService { ) } } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -233,7 +237,8 @@ export class PostgresRoleService { }); return APIResponse.success(res, apiId, { rowCount: response.affected }, HttpStatus.OK, 'Role deleted successfully.') } catch (e) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(res, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } } From a0c8fcbdb9fd6dc2548dfef7b86c6cb522e37d1f Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 29 May 2024 12:21:09 +0530 Subject: [PATCH 365/408] PS-634:chore-[changes in catch block error message] --- src/adapters/postgres/cohort-adapter.ts | 59 +++++++++++++++---------- src/adapters/postgres/fields-adapter.ts | 8 ++-- src/common/utils/api-id.config.ts | 8 +++- 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 59f15ad6..434d1fb7 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -20,6 +20,7 @@ import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import { isUUID } from "class-validator"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; import APIResponse from "src/common/responses/response"; +import { APIID } from "src/common/utils/api-id.config"; @Injectable() export class PostgresCohortService { @@ -45,7 +46,7 @@ export class PostgresCohortService { request: any, res: any ) { - let apiId = 'api.get.getCohortList'; + const apiId = APIID.COHORT_LIST; try { let findCohortId = await this.findCohortName(userId); let result = { @@ -67,13 +68,14 @@ export class PostgresCohortService { return APIResponse.success(res, apiId, result, (HttpStatus.OK), "Cohort list fetched successfully"); } catch (error) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(res, apiId, "Internal Server Error", errorMessage, (HttpStatus.INTERNAL_SERVER_ERROR)); } } public async getCohortsDetails(cohortId: string, res) { - let apiId = 'api.get.getCohortDetails'; + const apiId = APIID.COHORT_READ; try { @@ -103,7 +105,8 @@ export class PostgresCohortService { } } catch (error) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${error}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(res, apiId, "Internal Server Error", errorMessage, (HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -203,7 +206,7 @@ export class PostgresCohortService { public async createCohort(request: any, cohortCreateDto: CohortCreateDto, res) { - let apiId = 'api.post.createCohort'; + const apiId = APIID.COHORT_CREATE; try { let field_value_array = cohortCreateDto.fieldValues.split("|"); @@ -298,8 +301,9 @@ export class PostgresCohortService { return APIResponse.success(res, apiId, response, (HttpStatus.CREATED), "Cohort Created Successfully."); - } catch (e) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + } catch (error) { + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(res, apiId, "Internal Server Error", errorMessage, (HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -309,7 +313,7 @@ export class PostgresCohortService { cohortUpdateDto: CohortUpdateDto, res ) { - let apiId = 'api.put.updateCohort'; + const apiId = APIID.COHORT_UPDATE; try { let field_value_array = cohortUpdateDto.fieldValues.split("|"); @@ -453,8 +457,9 @@ export class PostgresCohortService { (HttpStatus.NOT_FOUND) ) } - } catch (e) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + } catch (error) { + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(res, apiId, "Internal Server Error", errorMessage, (HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -464,7 +469,7 @@ export class PostgresCohortService { request: any, cohortSearchDto: CohortSearchDto, response ) { - let apiId = 'api.post.searchCohort'; + const apiId = APIID.COHORT_LIST; try { let { limit, page, filters } = cohortSearchDto; @@ -549,6 +554,8 @@ export class PostgresCohortService { cohortDetails: [], }; + let count=0 + if (whereClause['userId']) { const additionalFields = Object.keys(whereClause).filter(key => key !== 'userId'); if (additionalFields.length > 0) { @@ -577,31 +584,33 @@ export class PostgresCohortService { (HttpStatus.BAD_REQUEST) ) } - const [cohortData] = await this.cohortMembersRepository.findAndCount({ + const [data,totalCount] = await this.cohortMembersRepository.findAndCount({ where: whereClause, skip: offset, - take: limit, }); - + const cohortData = data.slice(offset, offset + (limit)); + count=totalCount for (let data of cohortData) { let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); results.cohortDetails.push(cohortDetails); } } else { - const [cohortData] = await this.cohortRepository.findAndCount({ + const [data,totalcount] = await this.cohortRepository.findAndCount({ where: whereClause, - skip: offset, - take: limit, + skip: offset }); + const cohortData = data.slice(offset, offset + (limit)); + count=totalcount for (let data of cohortData) { let cohortDetails = await this.getCohortDataWithCustomfield(data.cohortId); results.cohortDetails.push(cohortDetails); } } - + if (results.cohortDetails.length > 0) { - return APIResponse.success(response, apiId, results, (HttpStatus.OK), "Cohort details fetched successfully"); + const totalCount = results.cohortDetails.length + return APIResponse.success(response, apiId, {count,results}, (HttpStatus.OK), "Cohort details fetched successfully"); } else { return APIResponse.error( @@ -614,8 +623,9 @@ export class PostgresCohortService { } - } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + } catch (error) { + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, (HttpStatus.INTERNAL_SERVER_ERROR)); } } @@ -625,7 +635,7 @@ export class PostgresCohortService { request: any, response ) { - let apiId = 'api.delete.updateCohortStatus'; + const apiId = APIID.COHORT_DELETE; try { const decoded: any = jwt_decode(request.headers.authorization); // const createdBy = decoded?.sub; @@ -667,8 +677,9 @@ export class PostgresCohortService { (HttpStatus.BAD_REQUEST) ) } - } catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + } catch (error) { + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, (HttpStatus.INTERNAL_SERVER_ERROR)); } } diff --git a/src/adapters/postgres/fields-adapter.ts b/src/adapters/postgres/fields-adapter.ts index 7888b41b..2ac62e28 100644 --- a/src/adapters/postgres/fields-adapter.ts +++ b/src/adapters/postgres/fields-adapter.ts @@ -12,6 +12,7 @@ import { Repository } from "typeorm"; import { SuccessResponse } from "src/success-response"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import APIResponse from "src/common/responses/response"; +import { APIID } from "src/common/utils/api-id.config"; @Injectable() export class PostgresFieldsService { @@ -102,7 +103,7 @@ export class PostgresFieldsService { } async createFieldValues(request: any, fieldValuesDto: FieldValuesDto,res) { - let apiId = 'api.post.createFieldValues'; + const apiId = APIID.FIELDVALUES_CREATE; try { @@ -120,8 +121,9 @@ export class PostgresFieldsService { return APIResponse.success(res, apiId, result, (HttpStatus.CREATED), "Ok"); - } catch (e) { - return APIResponse.error(res, apiId, "Internal Server Error", `Error is ${e}`, (HttpStatus.INTERNAL_SERVER_ERROR)); + } catch (error) { + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(res, apiId, "Internal Server Error",errorMessage, (HttpStatus.INTERNAL_SERVER_ERROR)); } } diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index a3612241..252e6fb7 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -13,5 +13,11 @@ export const APIID = { PRIVILEGE_BYROLEID: "api.privilegebyRoleId.get", PRIVILEGE_BYPRIVILEGEID: 'api.privilegebyPrivilegeId.get', PRIVILEGE_CREATE: 'api.privilege.create', - PRIVILEGE_DELETE: 'api.privilege.delete' + PRIVILEGE_DELETE: 'api.privilege.delete', + COHORT_CREATE:"api.cohort.create", + COHORT_LIST:"api.cohort.list", + COHORT_READ:"api.cohort.read", + COHORT_UPDATE:"api.cohort.update", + COHORT_DELETE:"api.cohort.delete", + FIELDVALUES_CREATE:"api.fieldValues.create" } From 1ecae10653922e3d4d45dd2d109351b0c35325db Mon Sep 17 00:00:00 2001 From: Dhanashree-Patil95 Date: Wed, 29 May 2024 12:34:02 +0530 Subject: [PATCH 366/408] PS-634:chore-[Added exception filters in controller] --- src/cohort/cohort.controller.ts | 13 ++++++++----- src/fields/fields.controller.ts | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/cohort/cohort.controller.ts b/src/cohort/cohort.controller.ts index c17a168d..0907e458 100644 --- a/src/cohort/cohort.controller.ts +++ b/src/cohort/cohort.controller.ts @@ -29,6 +29,7 @@ import { ValidationPipe, UsePipes, BadRequestException, + UseFilters, } from "@nestjs/common"; import { CohortSearchDto } from "./dto/cohort-search.dto"; import { Request } from "@nestjs/common"; @@ -40,6 +41,8 @@ import { CohortAdapter } from "./cohortadapter"; import { CohortCreateDto } from "./dto/cohort-create.dto"; import { CohortUpdateDto } from "./dto/cohort-update.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { AllExceptionsFilter } from "src/common/filters/exception.filter"; +import { APIID } from "src/common/utils/api-id.config"; @ApiTags("Cohort") @Controller("cohort") @@ -47,7 +50,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; export class CohortController { constructor(private readonly cohortAdapter: CohortAdapter) { } - + @UseFilters(new AllExceptionsFilter(APIID.COHORT_READ)) @Get("/read/:cohortId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Cohort details Fetched Successfully" }) @@ -67,7 +70,7 @@ export class CohortController { } - + @UseFilters(new AllExceptionsFilter(APIID.COHORT_CREATE)) @Post("/create") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @@ -111,7 +114,7 @@ export class CohortController { } - + @UseFilters(new AllExceptionsFilter(APIID.COHORT_LIST)) @Post("/search") @ApiBasicAuth("access-token") @ApiBody({ type: CohortSearchDto }) @@ -140,7 +143,7 @@ export class CohortController { ); } - //update + @UseFilters(new AllExceptionsFilter(APIID.COHORT_UPDATE)) @Put("/update/:cohortId") @ApiConsumes("multipart/form-data") @ApiBasicAuth("access-token") @@ -174,7 +177,7 @@ export class CohortController { } - //delete cohort + @UseFilters(new AllExceptionsFilter(APIID.COHORT_DELETE)) @Delete("/delete/:cohortId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Cohort has been deleted successfully." }) diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 9e0a3594..4279324a 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -15,6 +15,7 @@ import { Headers, UseGuards, Res, + UseFilters, } from "@nestjs/common"; import { FieldsSearchDto } from "./dto/fields-search.dto"; import { Request } from "@nestjs/common"; @@ -27,6 +28,8 @@ import { FieldValuesDto } from "./dto/field-values.dto"; import { FieldValuesSearchDto } from "./dto/field-values-search.dto"; import { FieldsService } from "./fields.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { AllExceptionsFilter } from "src/common/filters/exception.filter"; +import { APIID } from "src/common/utils/api-id.config"; @ApiTags("Fields") @Controller("fields") @@ -93,6 +96,7 @@ export class FieldsController { //field values //create fields values + @UseFilters(new AllExceptionsFilter(APIID.FIELDVALUES_CREATE)) @Post("/values") @ApiBasicAuth("access-token") @ApiCreatedResponse({ From 701e1b613d8e5f5bf1fbf00740019e2892382181 Mon Sep 17 00:00:00 2001 From: poojakarma Date: Wed, 29 May 2024 12:58:11 +0530 Subject: [PATCH 367/408] Change Responses in UserRole APIS --- src/adapters/assignroleservicelocater.ts | 8 +- .../postgres/rbac/assignrole-adapter.ts | 380 +++++++++--------- .../postgres/rbac/privilege-adapter.ts | 10 - src/common/utils/api-id.config.ts | 5 +- .../assign-role/assign-role.controller.ts | 43 +- src/rbac/privilege/privilege.controller.ts | 5 +- 6 files changed, 227 insertions(+), 224 deletions(-) diff --git a/src/adapters/assignroleservicelocater.ts b/src/adapters/assignroleservicelocater.ts index 35f8fb50..00f0487a 100644 --- a/src/adapters/assignroleservicelocater.ts +++ b/src/adapters/assignroleservicelocater.ts @@ -1,7 +1,7 @@ import { CreateAssignRoleDto } from "src/rbac/assign-role/dto/create-assign-role.dto"; - +import { Response } from "express"; export interface IServicelocatorassignRole { - createAssignRole(request: any, createAssignRoleDto:CreateAssignRoleDto); - getAssignedRole(userId, request); - deleteAssignedRole(deleteAssignRoleDto); + createAssignRole(request: any, createAssignRoleDto: CreateAssignRoleDto, response: Response); + getAssignedRole(userId, request, response: Response); + deleteAssignedRole(deleteAssignRoleDto, response: Response); } \ No newline at end of file diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts index 72b1f4ab..4276d981 100644 --- a/src/adapters/postgres/rbac/assignrole-adapter.ts +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -10,206 +10,216 @@ import { IsAlpha, IsUUID, isUUID } from 'class-validator'; import { executionAsyncResource } from 'async_hooks'; import jwt_decode from "jwt-decode"; import { DeleteAssignRoleDto } from 'src/rbac/assign-role/dto/delete-assign-role.dto'; - +import { Response } from 'express'; +import { APIID } from 'src/common/utils/api-id.config'; +import APIResponse from 'src/common/responses/response'; @Injectable() export class PostgresAssignroleService { - constructor( - @InjectRepository(UserRoleMapping) - private userRoleMappingRepository: Repository, - @InjectRepository(Role) - private roleRepository: Repository - ) { } - public async createAssignRole(request: Request, createAssignRoleDto: CreateAssignRoleDto) { - try { - // const decoded: any = jwt_decode(request.headers.authorization); - const userId = createAssignRoleDto.userId; - const roles = createAssignRoleDto.roleId; - const tenantId = createAssignRoleDto.tenantId; - - // Check if roles array is not empty - if (!roles || roles.length === 0) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: "Roles array cannot be empty.", - }); - } - let result = []; - let errors = []; + constructor( + @InjectRepository(UserRoleMapping) + private userRoleMappingRepository: Repository, + @InjectRepository(Role) + private roleRepository: Repository + ) { } + public async createAssignRole(request: Request, createAssignRoleDto: CreateAssignRoleDto, response: Response) { + const apiId = APIID.USERROLE__CREATE + try { + // const decoded: any = jwt_decode(request.headers.authorization); + const userId = createAssignRoleDto.userId; + const roles = createAssignRoleDto.roleId; + const tenantId = createAssignRoleDto.tenantId; - for (const roleId of roles) { - // If role already exists for user, return error response - let findExistingRole = await this.userRoleMappingRepository.findOne({ - where: { - userId: userId, - roleId: roleId, - }, - }); - if (findExistingRole) { - errors.push({ - errorMessage: `Role ${roleId} is already assigned to this user.`, - }); - continue; - } + // Check if roles array is not empty + if (!roles || roles.length === 0) { + return APIResponse.error( + response, + apiId, + `Roles array cannot be empty.`, + 'empty array found', + HttpStatus.BAD_REQUEST + ) + } + let result = []; + let errors = []; - //Rele is belong for this tenent - let roleExistforTenant = await this.roleRepository.findOne({ - where: { - roleId: roleId, - tenantId: tenantId, - }, - }); - if (!roleExistforTenant) { - errors.push({ - errorMessage: `Role ${roleId} is not exist for this tenant.`, - }); - continue; - } + for (const roleId of roles) { + // If role already exists for user, return error response + let findExistingRole = await this.userRoleMappingRepository.findOne({ + where: { + userId: userId, + roleId: roleId, + }, + }); + if (findExistingRole) { + errors.push({ + errorMessage: `Role ${roleId} is already assigned to this user.`, + }); + continue; + } - const data = await this.userRoleMappingRepository.save({ - userId: userId, - roleId: roleId, - tenantId: tenantId, - createdBy: request['user'].userId, - updatedBy: request['user'].userId - }) - result.push(new ResponseAssignRoleDto(data, `Role assigned successfully to the user in the specified tenant.`)); - } - - if (result.length == 0) { - return { - statusCode: HttpStatus.BAD_REQUEST, - errorCount: errors.length, - errors, - }; - } - return { - statusCode: HttpStatus.CREATED, - successCount: result.length, - errorCount: errors.length, - data: result, - errors, - }; - } catch (error) { - if (error.code === '23503') { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: `User Id or Role Id Doesn't Exist in Database ` - }); - } - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: JSON.stringify(error) - }); + //Rele is belong for this tenent + let roleExistforTenant = await this.roleRepository.findOne({ + where: { + roleId: roleId, + tenantId: tenantId, + }, + }); + if (!roleExistforTenant) { + errors.push({ + errorMessage: `Role ${roleId} is not exist for this tenant.`, + }); + continue; } - } - public async getAssignedRole(userId: string, request: Request) { - try { - if (!isUUID(userId)) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: 'Please Enter Valid User ID', - }); - } + const data = await this.userRoleMappingRepository.save({ + userId: userId, + roleId: roleId, + tenantId: tenantId, + createdBy: request['user'].userId, + updatedBy: request['user'].userId + }) + result.push(new ResponseAssignRoleDto(data, `Role assigned successfully to the user in the specified tenant.`)); + } - let result = await this.checkExistingRole(userId); - if (!result) { - return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'No Role assigned to user', - data: result, - }); - } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: result, - }); - } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); - } + if (result.length == 0) { + return APIResponse.error( + response, + apiId, + `Please Enter Valid User ID`, + 'Invalid User ID', + HttpStatus.BAD_REQUEST + ) + } + return APIResponse.success(response, apiId, { successCount: result.length, errorCount: errors.length, result, errors }, + HttpStatus.CREATED, 'Role successfully Created') + } catch (error) { + if (error.code === '23503') { + return APIResponse.error( + response, + apiId, + `User Id or Role Id Doesn't Exist in Database`, + 'Not found', + HttpStatus.NOT_FOUND + ) + } + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + public async getAssignedRole(userId: string, request: Request, response: Response) { + const apiId = APIID.USERROLE_GET; + try { + if (!isUUID(userId)) { + return APIResponse.error( + response, + apiId, + `Please Enter Valid User ID`, + 'Invalid User ID', + HttpStatus.BAD_REQUEST + ) + } + let result = await this.checkExistingRole(userId); + if (!result) { + return APIResponse.error( + response, + apiId, + `User Id or Role Id Doesn't Exist in Database`, + 'Not found', + HttpStatus.NOT_FOUND + ) + } + return APIResponse.success(response, apiId, result, HttpStatus.OK, 'User role fetched successfully') + } catch (error) { + const errorMessage = error.message || 'Internal server error'; + return APIResponse.error(response, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); } - public async deleteAssignedRole(deleteAssignRoleDto: DeleteAssignRoleDto) { - try { - // Validate userId format - if (!isUUID(deleteAssignRoleDto.userId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Invalid userId format. Please provide a valid UUID.", - }); - } - // Validate roleId format - for (const roleId of deleteAssignRoleDto.roleId) { - if (!isUUID(roleId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Invalid roleId format. Please provide valid UUIDs.", - }); - } - } - // Check if the userId exists in userRoleMapping table - const userExists = await this.userRoleMappingRepository.findOne({ - where: { userId: deleteAssignRoleDto.userId }, - }); - if (!userExists) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "User not found in userRoleMapping table", - }); - } - // Check if all roleId(s) exist - const roleExists = await this.userRoleMappingRepository.find({ - where: { - userId: deleteAssignRoleDto.userId, - roleId: In(deleteAssignRoleDto.roleId), - }, - }); - // If any roleId(s) are missing, throw an error - if (roleExists.length !== deleteAssignRoleDto.roleId.length) { - // throw new Error("One or more roles not found for the user"); - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Roles not found for the user", - }); - } - // If all validations pass, proceed with deletion - const response = await this.userRoleMappingRepository.delete({ - userId: deleteAssignRoleDto.userId, - roleId: In(deleteAssignRoleDto.roleId), - }); - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "Roles deleted successfully.", - data: { - rowCount: response.affected, - }, - }); - } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e.message || "Internal server error", - }); + } + + public async deleteAssignedRole(deleteAssignRoleDto: DeleteAssignRoleDto, res: Response) { + const apiId = APIID.USERROLE_DELETE; + try { + // Validate userId format + if (!isUUID(deleteAssignRoleDto.userId)) { + return APIResponse.error( + res, + apiId, + `Invalid userId format. Please provide a valid UUID.`, + 'Invalid UUID', + HttpStatus.BAD_REQUEST + ) + + } + // Validate roleId format + for (const roleId of deleteAssignRoleDto.roleId) { + if (!isUUID(roleId)) { + return APIResponse.error( + res, + apiId, + `Invalid roleId format. Please provide valid UUIDs`, + 'Invalid UUID', + HttpStatus.BAD_REQUEST + ) } } + // Check if the userId exists in userRoleMapping table + const userExists = await this.userRoleMappingRepository.findOne({ + where: { userId: deleteAssignRoleDto.userId }, + }); + if (!userExists) { + return APIResponse.error( + res, + apiId, + `User not found in userRoleMapping table`, + 'User not found', + HttpStatus.BAD_REQUEST + ) + } + // Check if all roleId(s) exist + const roleExists = await this.userRoleMappingRepository.find({ + where: { + userId: deleteAssignRoleDto.userId, + roleId: In(deleteAssignRoleDto.roleId), + }, + }); + // If any roleId(s) are missing, throw an error + if (roleExists.length !== deleteAssignRoleDto.roleId.length) { + return APIResponse.error( + res, + apiId, + `Roles not found for the user`, + 'Roles not found', + HttpStatus.BAD_REQUEST + ) + } + // If all validations pass, proceed with deletion + const response = await this.userRoleMappingRepository.delete({ + userId: deleteAssignRoleDto.userId, + roleId: In(deleteAssignRoleDto.roleId), + }); + return APIResponse.success(res, apiId, { rowCount: response.affected }, + HttpStatus.OK, 'Roles deleted successfully.') + } catch (e) { + const errorMessage = e.message || 'Internal server error'; + return APIResponse.error(res, apiId, "Internal Server Error", errorMessage, HttpStatus.INTERNAL_SERVER_ERROR); + } + } - // async checkAndAddUserRole(data){ - // let existingUser = await this.checkExistingRole(data.userId) ; - // if(existingUser){ - // let update = - // } - // } + // async checkAndAddUserRole(data){ + // let existingUser = await this.checkExistingRole(data.userId) ; + // if(existingUser){ + // let update = + // } + // } - async checkExistingRole(userId) { - const result = await this.userRoleMappingRepository.findOne({ - where: { userId }, - }) - return result; - } + async checkExistingRole(userId) { + const result = await this.userRoleMappingRepository.findOne({ + where: { userId }, + }) + return result; + } } diff --git a/src/adapters/postgres/rbac/privilege-adapter.ts b/src/adapters/postgres/rbac/privilege-adapter.ts index 5c8fe26d..0252d763 100644 --- a/src/adapters/postgres/rbac/privilege-adapter.ts +++ b/src/adapters/postgres/rbac/privilege-adapter.ts @@ -173,16 +173,6 @@ export class PostgresPrivilegeService { public async deletePrivilege(privilegeId: string, res: Response) { const apiId = APIID.PRIVILEGE_DELETE try { - if (!isUUID(privilegeId)) { - return APIResponse.error( - res, - apiId, - `Please Enter valid (UUID)`, - 'Invalid (UUID)', - HttpStatus.BAD_REQUEST - ) - } - const privilegeToDelete = await this.privilegeRepository.findOne({ where: { privilegeId: privilegeId }, }); diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index a3612241..6bd54374 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -13,5 +13,8 @@ export const APIID = { PRIVILEGE_BYROLEID: "api.privilegebyRoleId.get", PRIVILEGE_BYPRIVILEGEID: 'api.privilegebyPrivilegeId.get', PRIVILEGE_CREATE: 'api.privilege.create', - PRIVILEGE_DELETE: 'api.privilege.delete' + PRIVILEGE_DELETE: 'api.privilege.delete', + USERROLE__CREATE: "api.userRole.create", + USERROLE_GET: "api.userRole.get", + USERROLE_DELETE: "api.userRole.delete" } diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index 80cd1904..0261d52b 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -1,58 +1,57 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions, Headers, UseGuards } from '@nestjs/common'; +import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions, Headers, UseGuards, UseFilters } from '@nestjs/common'; import { AssignRoleAdapter } from './assign-role.apater'; import { CreateAssignRoleDto } from './dto/create-assign-role.dto'; import { Response, Request } from "express"; import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags, ApiBadRequestResponse, ApiInternalServerErrorResponse, ApiConflictResponse, ApiNotFoundResponse } from '@nestjs/swagger'; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; import { DeleteAssignRoleDto } from './dto/delete-assign-role.dto'; - - - +import { AllExceptionsFilter } from 'src/common/filters/exception.filter'; +import { APIID } from 'src/common/utils/api-id.config'; @ApiTags('rbac') @Controller('rbac/usersRoles') @UseGuards(JwtAuthGuard) export class AssignRoleController { - constructor(private readonly assignRoleAdpater: AssignRoleAdapter) {} + constructor(private readonly assignRoleAdpater: AssignRoleAdapter) { } + @UseFilters(new AllExceptionsFilter(APIID.USERROLE__CREATE)) @Post() @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "Role assigned successfully to the user in the specified tenant." }) @ApiBadRequestResponse({ description: "Bad request." }) @ApiInternalServerErrorResponse({ description: "Internal Server Error." }) - @ApiConflictResponse({description:"Role is already assigned to this user."}) - + @ApiConflictResponse({ description: "Role is already assigned to this user." }) @ApiBody({ type: CreateAssignRoleDto }) // @ApiHeader({ name: "tenantid" }) public async create( - @Req() request: Request, - @Body() createAssignRoleDto:CreateAssignRoleDto , - @Res() response: Response, - @Headers() headers, + @Req() request: Request, + @Body() createAssignRoleDto: CreateAssignRoleDto, + @Res() response: Response, + @Headers() headers, ) { - - const result = await this.assignRoleAdpater.buildassignroleAdapter().createAssignRole(request,createAssignRoleDto); - return response.status(result.statusCode).json(result); + return await this.assignRoleAdpater.buildassignroleAdapter().createAssignRole(request, createAssignRoleDto, response); + // return response.status(result.statusCode).json(result); } + @UseFilters(new AllExceptionsFilter(APIID.USERROLE_GET)) @Get("/:userId") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Role Detail." }) @ApiHeader({ name: "tenantid" }) @ApiForbiddenResponse({ description: "Forbidden" }) - @SerializeOptions({strategy: "excludeAll",}) + @SerializeOptions({ strategy: "excludeAll", }) public async getRole( @Param("userId") userId: string, @Req() request: Request, @Res() response: Response ) { - const result = await this.assignRoleAdpater.buildassignroleAdapter().getAssignedRole(userId, request); - return response.status(result.statusCode).json(result); + return await this.assignRoleAdpater.buildassignroleAdapter().getAssignedRole(userId, request, response); + // return response.status(result.statusCode).json(result); } + @UseFilters(new AllExceptionsFilter(APIID.USERROLE_DELETE)) @Delete("/:userId") @ApiBasicAuth("access-token") @ApiHeader({ name: "tenantid" }) @@ -63,10 +62,10 @@ export class AssignRoleController { @Body() deleteAssignRoleDto: DeleteAssignRoleDto, // Modify this line to accept DeleteAssignRoleDto @Res() response: Response ) { - const result = await this.assignRoleAdpater + return await this.assignRoleAdpater .buildassignroleAdapter() - .deleteAssignedRole(deleteAssignRoleDto); - return response.status(result.statusCode).json(result); + .deleteAssignedRole(deleteAssignRoleDto, response); + // return response.status(result.statusCode).json(result); } - + } diff --git a/src/rbac/privilege/privilege.controller.ts b/src/rbac/privilege/privilege.controller.ts index f7fed339..b5e09266 100644 --- a/src/rbac/privilege/privilege.controller.ts +++ b/src/rbac/privilege/privilege.controller.ts @@ -17,6 +17,7 @@ import { UseGuards, Query, UseFilters, + ParseUUIDPipe, } from "@nestjs/common"; import { ApiTags, @@ -141,14 +142,14 @@ export class PrivilegeController { // } @UseFilters(new AllExceptionsFilter(APIID.PRIVILEGE_DELETE)) - @Delete("/:id") + @Delete("/:privilegeId") @ApiBasicAuth("access-token") @ApiHeader({ name: "tenantid" }) @ApiOkResponse({ description: "Role deleted successfully." }) @ApiNotFoundResponse({ description: "Data not found" }) @ApiBadRequestResponse({ description: "Bad request" }) public async deleteRole( - @Param("privilegeId") privilegeId: string, + @Param("privilegeId", ParseUUIDPipe) privilegeId: string, @Res() response: Response ) { return await this.privilegeAdapter From f963f8035441a954ed31c658ad3c3549effb8b63 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 29 May 2024 13:28:04 +0530 Subject: [PATCH 368/408] chore: removed commented code of user-adapter --- src/adapters/postgres/user-adapter.ts | 122 ++------------------------ 1 file changed, 6 insertions(+), 116 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 5ac4d130..c1cba3bd 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -63,25 +63,12 @@ export class PostgresUserService { try { let findData = await this.findAllUserDetails(userSearchDto); if (!findData.length) { - // return new SuccessResponse({ - // statusCode: HttpStatus.BAD_REQUEST, - // message: 'Either Filter is wrong or No Data Found For the User', - // }); return APIResponse.error(response, apiId, "Bad request", `Either Filter is wrong or No Data Found For the User`, HttpStatus.BAD_REQUEST); } - // return new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: 'Ok.', - // data: findData, - // }); return await APIResponse.success(response, apiId, findData, HttpStatus.OK, 'User List fetched.') } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + return APIResponse.error(response, apiId, "Internal Server Error", "Something went wrong", HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -115,10 +102,6 @@ export class PostgresUserService { const apiId = APIID.USER_GET; try { if (!isUUID(userData.userId)) { - // new SuccessResponse({ - // statusCode: HttpStatus.BAD_REQUEST, - // message: 'Please Enter Valid UUID', - // }); return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID`, HttpStatus.BAD_REQUEST); } const checkExistUser = await this.usersRepository.find({ @@ -128,10 +111,7 @@ export class PostgresUserService { }) if (checkExistUser.length == 0) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: `User Id '${userData.userId}' does not exist.`, - }); + return APIResponse.error(response, apiId, "Not Found",`User Id '${userData.userId}' does not exist.`, HttpStatus.NOT_FOUND); } const result = { @@ -156,18 +136,9 @@ export class PostgresUserService { } if (!userDetails) { - // return new SuccessResponse({ - // statusCode: HttpStatus.NOT_FOUND, - // message: 'User Not Found', - // }); return APIResponse.error(response, apiId, "Not Found", `User Not Found`, HttpStatus.NOT_FOUND); } if (!userData.fieldValue) { - // new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: 'Ok.', - // data: userDetails, - // }); return await APIResponse.success(response, apiId, { userData: userDetails }, HttpStatus.OK, 'User details Fetched Successfully.') } @@ -196,19 +167,10 @@ export class PostgresUserService { } result.userData['customFields'] = customFieldsArray; - // new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: 'User details Fetched Successfully.', - // data: result, - // }); return await APIResponse.success(response, apiId, { ...result }, HttpStatus.OK, 'User details Fetched Successfully.') - } catch (e) { - // new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (e) {; + return APIResponse.error(response, apiId, "Internal Server Error", "Something went wrong", HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -418,20 +380,10 @@ export class PostgresUserService { errorMessage = `Uneditable fields: ${unEditableIdes.join(', ')}` } } - // return ({ - // statusCode: 200, - // message: "User has been updated successfully.", - // data: updatedData, - // error: errorMessage - // }); return await APIResponse.success(response, apiId, updatedData, HttpStatus.OK, "User has been updated successfully.") } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error is : ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + return APIResponse.error(response, apiId, "Internal Server Error", "Something went wrong", HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -483,10 +435,6 @@ export class PostgresUserService { const validateField = await this.validateFieldValues(field_values); if (validateField == false) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.CONFLICT, - // errorMessage: "Duplicate fieldId found in fieldValues.", - // }); return APIResponse.error(response, apiId, "Conflict", `Duplicate fieldId found in fieldValues.`, HttpStatus.CONFLICT); } } @@ -506,19 +454,11 @@ export class PostgresUserService { let checkUserinKeyCloakandDb = await this.checkUserinKeyCloakandDb(userCreateDto) // let checkUserinDb = await this.checkUserinKeyCloakandDb(userCreateDto.username); if (checkUserinKeyCloakandDb) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.FORBIDDEN, - // errorMessage: "User Already Exist", - // }); return APIResponse.error(response, apiId, "Forbidden", `User Already Exist`, HttpStatus.FORBIDDEN); } resKeycloak = await createUserInKeyCloak(userSchema, token).catch( (error) => { errKeycloak = error.response?.data.errorMessage; - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: error, - // }); return APIResponse.error(response, apiId, "Internal Server Error", `${errKeycloak}`, HttpStatus.INTERNAL_SERVER_ERROR); } ); @@ -539,21 +479,12 @@ export class PostgresUserService { } let result = await this.updateCustomFields(userId, fieldData); if (!result) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: `Error is ${result}`, - // }); return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${result}`, HttpStatus.INTERNAL_SERVER_ERROR); } } } } - // return new SuccessResponse({ - // statusCode: 200, - // message: "User has been created successfully.", - // data: result, - // }); APIResponse.success(response, apiId, { userData: result }, HttpStatus.CREATED, "User has been created successfully.") } @@ -561,11 +492,7 @@ export class PostgresUserService { if (e instanceof ErrorResponseTypeOrm) { return e; } else { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e.toString(), // or any custom error message you want - // }); - return APIResponse.error(response, apiId, "Internal Server Error", `Error is ${e}`, HttpStatus.INTERNAL_SERVER_ERROR); + return APIResponse.error(response, apiId, "Internal Server Error", "Something went wrong", HttpStatus.INTERNAL_SERVER_ERROR); } } } @@ -748,10 +675,6 @@ export class PostgresUserService { if (userData?.userId) { userId = userData?.userId; } else { - // return new ErrorResponse({ - // errorCode: `404`, - // errorMessage: "User with given username not found", - // }); return APIResponse.error(response, apiId, "Not Found", `User with given username not found`, HttpStatus.NOT_FOUND); } @@ -773,26 +696,13 @@ export class PostgresUserService { userId ); } catch (e) { - // return new ErrorResponse({ - // errorCode: `${e.response.status}`, - // errorMessage: e.response.data.error, - // }); return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, HttpStatus.INTERNAL_SERVER_ERROR); } if (apiResponse.statusCode === 204) { - // return new SuccessResponse({ - // statusCode: apiResponse.statusCode, - // message: apiResponse.message, - // data: apiResponse.data, - // }); return await APIResponse.success(response, apiId, {}, HttpStatus.NO_CONTENT, 'User Password Updated Successfully.') } else { - // return new ErrorResponse({ - // errorCode: "400", - // errorMessage: apiResponse.errors, - // }); return APIResponse.error(response, apiId, "Bad Request", `Error : ${apiResponse?.errors}`, HttpStatus.BAD_REQUEST); } } catch (e) { @@ -875,10 +785,6 @@ export class PostgresUserService { const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; // Validate userId format if (!isUUID(userId)) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.BAD_REQUEST, - // errorMessage: "Please enter a valid UUID for userId", - // }); return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID for userId`, HttpStatus.BAD_REQUEST); } @@ -886,10 +792,6 @@ export class PostgresUserService { // Check if user exists in usersRepository const user = await this.usersRepository.findOne({ where: { userId: userId } }); if (!user) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.NOT_FOUND, - // errorMessage: "User not found in user table.", - // }); return APIResponse.error(response, apiId, "Not Found", `User not found in user table.`, HttpStatus.NOT_FOUND); } @@ -918,21 +820,9 @@ export class PostgresUserService { } }); - - // return new SuccessResponse({ - // statusCode: HttpStatus.OK, - // message: "User and related entries deleted Successfully.", - // data: { - // user: userResult - // }, - // }); return await APIResponse.success(response, apiId, userResult, HttpStatus.OK, "User and related entries deleted Successfully.") } catch (e) { - // return new ErrorResponseTypeOrm({ - // statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - // errorMessage: e, - // }); return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, HttpStatus.INTERNAL_SERVER_ERROR); } } From 2e18c63df1b15359bf588dd9b916e47bf1fa5b4c Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Wed, 29 May 2024 14:02:03 +0530 Subject: [PATCH 369/408] refactor : added new api responses for assignprivileges --- src/adapters/assignprivilegelocater.ts | 5 +- .../hasura/rbac/privilegerole.adapter.ts | 5 +- .../postgres/rbac/privilegerole.adapter.ts | 70 +++++++------------ src/adapters/postgres/user-adapter.ts | 3 +- src/common/utils/api-id.config.ts | 4 +- .../assign-privilege.controller.ts | 15 ++-- 6 files changed, 43 insertions(+), 59 deletions(-) diff --git a/src/adapters/assignprivilegelocater.ts b/src/adapters/assignprivilegelocater.ts index cf5aca03..22799cf0 100644 --- a/src/adapters/assignprivilegelocater.ts +++ b/src/adapters/assignprivilegelocater.ts @@ -1,6 +1,7 @@ +import { Response } from "express"; import { CreatePrivilegeRoleDto } from "src/rbac/assign-privilege/dto/create-assign-privilege.dto"; export interface IServicelocatorprivilegeRole { - createPrivilegeRole(request: any, createPrivilegeRole:CreatePrivilegeRoleDto); - getPrivilegeRole(userId, request); + createPrivilegeRole(request: any, createPrivilegeRole:CreatePrivilegeRoleDto, response:Response); + getPrivilegeRole(userId, request, response:Response); } \ No newline at end of file diff --git a/src/adapters/hasura/rbac/privilegerole.adapter.ts b/src/adapters/hasura/rbac/privilegerole.adapter.ts index 1ec35c75..417151bb 100644 --- a/src/adapters/hasura/rbac/privilegerole.adapter.ts +++ b/src/adapters/hasura/rbac/privilegerole.adapter.ts @@ -1,12 +1,13 @@ import { HttpService } from "@nestjs/axios"; import { Injectable } from "@nestjs/common"; +import { Response } from "express"; import { CreatePrivilegeRoleDto } from "src/rbac/assign-privilege/dto/create-assign-privilege.dto"; @Injectable() export class HasuraAssignPrivilegeService { constructor(private httpService: HttpService) {} - public async createPrivilegeRole(request: any, createAssignRoleDto:CreatePrivilegeRoleDto){}; - public async getPrivilegeRole(request: any, createAssignRoleDto:CreatePrivilegeRoleDto){}; + public async createPrivilegeRole(request: any, createAssignRoleDto:CreatePrivilegeRoleDto,response : Response){}; + public async getPrivilegeRole(request: any, createAssignRoleDto:CreatePrivilegeRoleDto, response:Response){}; public async deletePrivilegeRole(userId){}; } \ No newline at end of file diff --git a/src/adapters/postgres/rbac/privilegerole.adapter.ts b/src/adapters/postgres/rbac/privilegerole.adapter.ts index 762badd5..02707a18 100644 --- a/src/adapters/postgres/rbac/privilegerole.adapter.ts +++ b/src/adapters/postgres/rbac/privilegerole.adapter.ts @@ -1,11 +1,12 @@ import {HttpStatus, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { In, Repository } from 'typeorm'; -import { SuccessResponse } from 'src/success-response'; -import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { CreatePrivilegeRoleDto } from 'src/rbac/assign-privilege/dto/create-assign-privilege.dto'; import { RolePrivilegeMapping } from 'src/rbac/assign-privilege/entities/assign-privilege.entity'; import { isUUID } from 'class-validator'; +import APIResponse from 'src/common/responses/response'; +import { Response } from 'express'; +import { APIID } from 'src/common/utils/api-id.config'; @Injectable() export class PostgresAssignPrivilegeService { @@ -13,7 +14,8 @@ export class PostgresAssignPrivilegeService { @InjectRepository(RolePrivilegeMapping) private rolePrivilegeMappingRepository: Repository ){} - public async createPrivilegeRole(request: Request,createPrivilegeRoleDto:CreatePrivilegeRoleDto){ + public async createPrivilegeRole(request: Request,createPrivilegeRoleDto:CreatePrivilegeRoleDto,response:Response){ + const apiId = APIID.ASSIGNPRIVILEGE_CREATE; try { let result ; if (createPrivilegeRoleDto.deleteOld) { @@ -37,22 +39,14 @@ export class PostgresAssignPrivilegeService { for (let data of newPrivileges) { result = await this.rolePrivilegeMappingRepository.save(data); } - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Privileges assigned successfully.", - data: result, - }); + + return await APIResponse.success(response, apiId, result,HttpStatus.CREATED, "Privileges assigned successfully.") } catch (error) { - if(error.code === '23503'){ - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: `Privilege Id or Role Id Doesn't Exist in Database ` - }); + if(error.code === '23503') { + return APIResponse.error(response, apiId, "Not Found",`Privilege Id or Role Id Doesn't Exist in Database.`, HttpStatus.NOT_FOUND); } - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: JSON.stringify(error) - }); + + return APIResponse.error(response, apiId, "Not Found",`Error is: ${error}.`, HttpStatus.NOT_FOUND); } } @@ -63,43 +57,31 @@ export class PostgresAssignPrivilegeService { throw error; } } -// public async createPrivilegeRole(){ -// } - public async getPrivilegeRole(userId:string,request: Request){ + + public async getPrivilegeRole(roleId:string,request: Request,response:Response){ + const apiId = APIID.ASSIGNPRIVILEGE_GET; try { - if (!isUUID(userId)) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: 'Please Enter Valid User ID', - }); + if (!isUUID(roleId)) { + return APIResponse.error(response, apiId, "Bad Request","Please Enter Valid User ID.", HttpStatus.BAD_REQUEST); } - let result = await this.checkExistingRole(userId); + let result = await this.checkExistingRole(roleId); + if(!result){ - return new SuccessResponse({ - statusCode: HttpStatus.NOT_FOUND, - message: 'No Role assigned to user', - data: result, - }); + return APIResponse.error(response, apiId, "Not Found","No Role Found.", HttpStatus.NOT_FOUND); } - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', - data: result, - }); + + return await APIResponse.success(response, apiId, result,HttpStatus.OK, "Privileges for role fetched successfully.") + } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: error, - }); + return APIResponse.error(response, apiId, "Internal Server Error",`Something went wrong.`, HttpStatus.INTERNAL_SERVER_ERROR); } } - async checkExistingRole(privilegeId){ - const result= await this.rolePrivilegeMappingRepository.findOne({ - where: { privilegeId}, - relations:['user'] + async checkExistingRole(roleId){ + const result= await this.rolePrivilegeMappingRepository.find({ + where: { roleId } }) return result; } diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index c1cba3bd..d686a14d 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -1,4 +1,4 @@ -import { ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { HttpStatus, Injectable } from '@nestjs/common'; import { User } from '../../user/entities/user-entity' import { FieldValues } from '../../user/entities/field-value-entities'; import { InjectRepository } from '@nestjs/typeorm'; @@ -23,7 +23,6 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; -import { CourseController } from 'src/course/course.controller'; import { UserData } from 'src/user/user.controller'; import APIResponse from 'src/common/responses/response'; import { Response } from 'express'; diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index a3612241..399db9f7 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -13,5 +13,7 @@ export const APIID = { PRIVILEGE_BYROLEID: "api.privilegebyRoleId.get", PRIVILEGE_BYPRIVILEGEID: 'api.privilegebyPrivilegeId.get', PRIVILEGE_CREATE: 'api.privilege.create', - PRIVILEGE_DELETE: 'api.privilege.delete' + PRIVILEGE_DELETE: 'api.privilege.delete', + ASSIGNPRIVILEGE_CREATE: "api.assignprivilege.create", + ASSIGNPRIVILEGE_GET: "api.assignprivilege.get", } diff --git a/src/rbac/assign-privilege/assign-privilege.controller.ts b/src/rbac/assign-privilege/assign-privilege.controller.ts index b37e0af4..545b6df0 100644 --- a/src/rbac/assign-privilege/assign-privilege.controller.ts +++ b/src/rbac/assign-privilege/assign-privilege.controller.ts @@ -1,12 +1,13 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions } from '@nestjs/common'; +import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe, Req, Res, SerializeOptions, UseGuards } from '@nestjs/common'; import { AssignPrivilegeAdapter } from './assign-privilege.apater'; import { CreatePrivilegeRoleDto } from './dto/create-assign-privilege.dto'; import { Response, Request} from "express"; import { ApiBasicAuth, ApiCreatedResponse, ApiBody, ApiForbiddenResponse, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger'; - +import { JwtAuthGuard } from 'src/common/guards/keycloak.guard'; @ApiTags('rbac') @Controller('assignprivilege') +@UseGuards(JwtAuthGuard) export class AssignPrivilegeController { constructor(private readonly assignPrivilegeAdpater: AssignPrivilegeAdapter) {} @@ -20,23 +21,21 @@ export class AssignPrivilegeController { public async create(@Req() request: Request, @Body() createAssignPrivilegeDto:CreatePrivilegeRoleDto , @Res() response: Response) { - const result = await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().createPrivilegeRole(request,createAssignPrivilegeDto); - return response.status(result.statusCode).json(result); + return await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().createPrivilegeRole(request,createAssignPrivilegeDto,response); } - @Get("/:id") + @Get("/:roleid") @ApiBasicAuth("access-token") @ApiOkResponse({ description: "Privilege Details." }) @ApiHeader({ name: "tenantid" }) @ApiForbiddenResponse({ description: "Forbidden" }) @SerializeOptions({strategy: "excludeAll",}) public async getRole( - @Param("id") userId: string, + @Param("roleid") roleId: string, @Req() request: Request, @Res() response: Response ) { - const result = await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().getPrivilegeRole(userId, request); - return response.status(result.statusCode).json(result); + return await this.assignPrivilegeAdpater.buildPrivilegeRoleAdapter().getPrivilegeRole(roleId, request, response); } // @Delete("/:id") From 25151241e2b27869da59e68fce45129d1192ab83 Mon Sep 17 00:00:00 2001 From: poojakarma Date: Wed, 29 May 2024 15:44:17 +0530 Subject: [PATCH 370/408] Resolved comments --- src/adapters/postgres/rbac/assignrole-adapter.ts | 2 +- src/common/utils/api-id.config.ts | 2 +- src/rbac/assign-role/assign-role.controller.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/adapters/postgres/rbac/assignrole-adapter.ts b/src/adapters/postgres/rbac/assignrole-adapter.ts index 4276d981..758e7444 100644 --- a/src/adapters/postgres/rbac/assignrole-adapter.ts +++ b/src/adapters/postgres/rbac/assignrole-adapter.ts @@ -23,7 +23,7 @@ export class PostgresAssignroleService { private roleRepository: Repository ) { } public async createAssignRole(request: Request, createAssignRoleDto: CreateAssignRoleDto, response: Response) { - const apiId = APIID.USERROLE__CREATE + const apiId = APIID.USERROLE_CREATE try { // const decoded: any = jwt_decode(request.headers.authorization); const userId = createAssignRoleDto.userId; diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index 895f9904..3872bc84 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -14,7 +14,7 @@ export const APIID = { PRIVILEGE_BYPRIVILEGEID: 'api.privilegebyPrivilegeId.get', PRIVILEGE_CREATE: 'api.privilege.create', PRIVILEGE_DELETE: 'api.privilege.delete', - USERROLE__CREATE: "api.userRole.create", + USERROLE_CREATE: "api.userRole.create", USERROLE_GET: "api.userRole.get", USERROLE_DELETE: "api.userRole.delete", COHORT_CREATE: "api.cohort.create", diff --git a/src/rbac/assign-role/assign-role.controller.ts b/src/rbac/assign-role/assign-role.controller.ts index 0261d52b..cf7cd6da 100644 --- a/src/rbac/assign-role/assign-role.controller.ts +++ b/src/rbac/assign-role/assign-role.controller.ts @@ -15,7 +15,7 @@ import { APIID } from 'src/common/utils/api-id.config'; export class AssignRoleController { constructor(private readonly assignRoleAdpater: AssignRoleAdapter) { } - @UseFilters(new AllExceptionsFilter(APIID.USERROLE__CREATE)) + @UseFilters(new AllExceptionsFilter(APIID.USERROLE_CREATE)) @Post() @UsePipes(new ValidationPipe()) @ApiBasicAuth("access-token") From 1b1ce2333569366dab61c452ad77adb6cc0d77c8 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 30 May 2024 16:24:24 +0530 Subject: [PATCH 371/408] PS-547 Masked PI data in the user table and columns --- src/adapters/postgres/user-adapter.ts | 79 +++------------------------ 1 file changed, 7 insertions(+), 72 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 157a4636..d3b0e040 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -464,7 +464,6 @@ export class PostgresUserService { userCreateDto.userId = resKeycloak; let result = await this.createUserInDatabase(request, userCreateDto); - let fieldData = {}; if (userCreateDto.fieldValues) { @@ -789,25 +788,19 @@ export class PostgresUserService { }; } -<<<<<<< HEAD - public async deleteUserById(userId) { + public async deleteUserById(userId: string, response: Response) { + const apiId = APIID.USER_DELETE; const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; // Validate userId format if (!isUUID(userId)) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.BAD_REQUEST, - errorMessage: "Please enter a valid UUID for userId", - }); + return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID for userId`, HttpStatus.BAD_REQUEST); } try { // Check if user exists in usersRepository const user = await this.usersRepository.findOne({ where: { userId: userId } }); if (!user) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.NOT_FOUND, - errorMessage: "User not found in user table.", - }); + return APIResponse.error(response, apiId, "Not Found", `User not found in user table.`, HttpStatus.NOT_FOUND); } @@ -835,68 +828,10 @@ export class PostgresUserService { } }); - - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: "User and related entries deleted Successfully.", - data: { - user: userResult - }, - }); + return await APIResponse.success(response, apiId, userResult, + HttpStatus.OK, "User and related entries deleted Successfully.") } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); -======= - public async deleteUserById(userId: string, response: Response) { - const apiId = APIID.USER_DELETE; - const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; - // Validate userId format - if (!isUUID(userId)) { - return APIResponse.error(response, apiId, "Bad request", `Please Enter Valid UUID for userId`, HttpStatus.BAD_REQUEST); ->>>>>>> 6fea9fcd95d1db6e36f77477aeff30bd7355eed7 - } - } - - - - try { - // Check if user exists in usersRepository - const user = await this.usersRepository.findOne({ where: { userId: userId } }); - if (!user) { - return APIResponse.error(response, apiId, "Not Found", `User not found in user table.`, HttpStatus.NOT_FOUND); - } - - - // Delete from User table - const userResult = await this.usersRepository.delete(userId); - - // Delete from CohortMembers table - const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); - - // Delete from UserTenantMapping table - const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); - - // Delete from UserRoleMapping table - const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); - - // Delete from FieldValues table where ItemId matches userId - const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); - - const keycloakResponse = await getKeycloakAdminToken(); - const token = keycloakResponse.data.access_token; - - await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { - headers: { - 'Authorization': `Bearer ${token}` + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, HttpStatus.INTERNAL_SERVER_ERROR); } - }); - - return await APIResponse.success(response, apiId, userResult, - HttpStatus.OK, "User and related entries deleted Successfully.") -} catch (e) { - return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${e?.response?.data.error}`, HttpStatus.INTERNAL_SERVER_ERROR); -} } } From e597f799964d94bed926c712acba1ed4db842ca8 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 30 May 2024 17:13:21 +0530 Subject: [PATCH 372/408] Task #220234 : chore - Changed responses of user tenant mapping --- .../hasura/userTenantMapping.adapter.ts | 3 +- .../postgres/userTenantMapping-adapter.ts | 34 ++++++++----------- src/adapters/usertenantmappinglocator.ts | 5 +-- src/common/utils/api-id.config.ts | 3 +- .../user-tenant-mapping.adapter.ts | 6 ++-- .../user-tenant-mapping.controller.ts | 13 +++---- 6 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/adapters/hasura/userTenantMapping.adapter.ts b/src/adapters/hasura/userTenantMapping.adapter.ts index 2b04e38c..5188c0bf 100644 --- a/src/adapters/hasura/userTenantMapping.adapter.ts +++ b/src/adapters/hasura/userTenantMapping.adapter.ts @@ -3,9 +3,10 @@ import { InjectRepository } from '@nestjs/typeorm'; import { In, Repository } from 'typeorm'; import { UserTenantMapping } from 'src/userTenantMapping/entities/user-tenant-mapping.entity'; import { UserTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; +import { IServicelocatorAssignTenant } from '../usertenantmappinglocator'; @Injectable() -export class HasuraAssignTenantService { +export class HasuraAssignTenantService implements IServicelocatorAssignTenant { constructor( @InjectRepository(UserTenantMapping) private userTenantMappingRepository: Repository, diff --git a/src/adapters/postgres/userTenantMapping-adapter.ts b/src/adapters/postgres/userTenantMapping-adapter.ts index c8f7fb30..2e66144c 100644 --- a/src/adapters/postgres/userTenantMapping-adapter.ts +++ b/src/adapters/postgres/userTenantMapping-adapter.ts @@ -7,10 +7,13 @@ import { ErrorResponseTypeOrm } from 'src/error-response-typeorm'; import { SuccessResponse } from 'src/success-response'; import { User } from "src/user/entities/user-entity"; import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; - +import { IServicelocatorAssignTenant } from '../usertenantmappinglocator'; +import APIResponse from 'src/common/responses/response'; +import { Response } from 'express'; +import { APIID } from 'src/common/utils/api-id.config'; @Injectable() -export class PostgresAssignTenantService { +export class PostgresAssignTenantService implements IServicelocatorAssignTenant { constructor( @InjectRepository(UserTenantMapping) private userTenantMappingRepository: Repository, @@ -49,18 +52,15 @@ export class PostgresAssignTenantService { return true; } - public async userTenantMapping(request: any, assignTenantMappingDto: UserTenantMappingDto) { + public async userTenantMapping(request: any, assignTenantMappingDto: UserTenantMappingDto, response: Response) { + const apiId = APIID.ASSIGN_TENANT_CREATE; try { - const userId = assignTenantMappingDto.userId; const tenantIds = assignTenantMappingDto.tenantId; // Check if tenant array is not empty if (!tenantIds || tenantIds.length === 0) { - return new SuccessResponse({ - statusCode: HttpStatus.BAD_REQUEST, - message: "Please provide at least one tenant Id", - }); + return APIResponse.error(response, apiId, "Bad Request", "Please provide at least one tenant Id", HttpStatus.BAD_REQUEST); } let result = []; @@ -84,25 +84,19 @@ export class PostgresAssignTenantService { } if (result.length == 0) { - return { - statusCode: HttpStatus.BAD_REQUEST, - errorCount: errors.length, - errors, - }; + return APIResponse.error(response, apiId, "Bad Request", `User not added to tenants`, HttpStatus.BAD_REQUEST); } - return { - statusCode: HttpStatus.CREATED, + const res = { successCount: result.length, errorCount: errors.length, data: result, errors, }; + + return await APIResponse.success(response, apiId, res ,HttpStatus.OK, "User added to tenants successfully.") } catch (error) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: JSON.stringify(error) - }); + const errorMessage = error?.message || 'Something went wrong'; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${errorMessage}`, HttpStatus.INTERNAL_SERVER_ERROR) } } - } diff --git a/src/adapters/usertenantmappinglocator.ts b/src/adapters/usertenantmappinglocator.ts index 07bcd65e..adc30d46 100644 --- a/src/adapters/usertenantmappinglocator.ts +++ b/src/adapters/usertenantmappinglocator.ts @@ -1,4 +1,5 @@ +import { Response } from "express"; import { UserTenantMappingDto } from "src/userTenantMapping/dto/user-tenant-mapping.dto"; -export interface IServicelocatorassignTenant { - userTenantMapping(request: any, assignTenantMappingDto:UserTenantMappingDto); +export interface IServicelocatorAssignTenant { + userTenantMapping(request: any, assignTenantMappingDto: UserTenantMappingDto,response: Response); } \ No newline at end of file diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index cd819757..4a5d7b20 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -29,5 +29,6 @@ export const APIID = { COHORT_READ: "api.cohort.read", COHORT_UPDATE: "api.cohort.update", COHORT_DELETE: "api.cohort.delete", - FIELDVALUES_CREATE: "api.fieldValues.create" + FIELDVALUES_CREATE: "api.fieldValues.create", + ASSIGN_TENANT_CREATE:"api.assigntenant.create" } diff --git a/src/userTenantMapping/user-tenant-mapping.adapter.ts b/src/userTenantMapping/user-tenant-mapping.adapter.ts index f96061f2..1bb9ef7e 100644 --- a/src/userTenantMapping/user-tenant-mapping.adapter.ts +++ b/src/userTenantMapping/user-tenant-mapping.adapter.ts @@ -1,14 +1,14 @@ import { Injectable } from "@nestjs/common"; import { PostgresAssignTenantService } from "src/adapters/postgres/userTenantMapping-adapter"; import { HasuraAssignTenantService } from "src/adapters/hasura/userTenantMapping.adapter"; -import { IServicelocatorassignTenant } from "src/adapters/usertenantmappinglocator"; +import { IServicelocatorAssignTenant } from "src/adapters/usertenantmappinglocator"; @Injectable() export class AssignTenantAdapter { constructor(private hasuraProvider: HasuraAssignTenantService, private postgresProvider:PostgresAssignTenantService) {} - buildAssignTenantAdapter(): IServicelocatorassignTenant { - let adapter: IServicelocatorassignTenant; + buildAssignTenantAdapter(): IServicelocatorAssignTenant { + let adapter: IServicelocatorAssignTenant; switch (process.env.ADAPTERSOURCE) { case "hasura": diff --git a/src/userTenantMapping/user-tenant-mapping.controller.ts b/src/userTenantMapping/user-tenant-mapping.controller.ts index 5db5f912..d0cecf8a 100644 --- a/src/userTenantMapping/user-tenant-mapping.controller.ts +++ b/src/userTenantMapping/user-tenant-mapping.controller.ts @@ -25,14 +25,15 @@ import { UseGuards, ValidationPipe, UsePipes, + UseFilters, } from "@nestjs/common"; import { Request } from "@nestjs/common"; -import { FileInterceptor } from "@nestjs/platform-express"; - import { Response, response } from "express"; import { AssignTenantAdapter } from "./user-tenant-mapping.adapter"; import { UserTenantMappingDto } from "./dto/user-tenant-mapping.dto"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; +import { AllExceptionsFilter } from "src/common/filters/exception.filter"; +import { APIID } from "src/common/utils/api-id.config"; @ApiTags("AssignTenant") @Controller("assign-tenant") @@ -40,7 +41,7 @@ import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; export class AssignTenantController { constructor(private readonly assignTenantAdapter: AssignTenantAdapter) { } - //create cohort + @UseFilters(new AllExceptionsFilter(APIID.ASSIGN_TENANT_CREATE)) @Post() @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Tenant assigned successfully to the user." }) @@ -49,7 +50,7 @@ export class AssignTenantController { @ApiConflictResponse({ description: "Tenant is already assigned to this user." }) @UsePipes(new ValidationPipe()) @ApiBody({ type: UserTenantMappingDto }) - public async createCohort( + public async createUserTenantMapping( @Headers() headers, @Req() request: Request, @Body() userTenantMappingDto: UserTenantMappingDto, @@ -57,9 +58,9 @@ export class AssignTenantController { ) { const result = await this.assignTenantAdapter.buildAssignTenantAdapter().userTenantMapping( request, - userTenantMappingDto + userTenantMappingDto, + response ); return response.status(result.statusCode).json(result); } - } From 89758702422134f93167da89b5a27c0e0ff6f353 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 30 May 2024 17:15:28 +0530 Subject: [PATCH 373/408] Task #220234 : chore - minor changes --- src/adapters/postgres/user-adapter.ts | 3 ++- src/common/filters/exception.filter.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index a1c13655..1c2cda44 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -27,9 +27,10 @@ import { UserData } from 'src/user/user.controller'; import APIResponse from 'src/common/responses/response'; import { Response } from 'express'; import { APIID } from 'src/common/utils/api-id.config'; +import { IServicelocator } from '../userservicelocator'; @Injectable() -export class PostgresUserService { +export class PostgresUserService implements IServicelocator { axios = require("axios"); constructor( diff --git a/src/common/filters/exception.filter.ts b/src/common/filters/exception.filter.ts index 9c487220..1ca84985 100644 --- a/src/common/filters/exception.filter.ts +++ b/src/common/filters/exception.filter.ts @@ -20,7 +20,7 @@ export class AllExceptionsFilter implements ExceptionFilter { response, this.apiId, detailedErrorMessage, - exception instanceof HttpException ? exception.name : 'InternalServerError', // error + exception instanceof HttpException ? exception.name : 'Internal Server Error', // error status ); } From d4cd71c5081e4f96626a92d05c7d63b065ca8253 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 30 May 2024 17:16:26 +0530 Subject: [PATCH 374/408] Task #220234 : chore - minor changes for user tenant mapping --- src/adapters/postgres/userTenantMapping-adapter.ts | 4 ++-- src/userTenantMapping/user-tenant-mapping.controller.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/adapters/postgres/userTenantMapping-adapter.ts b/src/adapters/postgres/userTenantMapping-adapter.ts index 2e66144c..00261ec5 100644 --- a/src/adapters/postgres/userTenantMapping-adapter.ts +++ b/src/adapters/postgres/userTenantMapping-adapter.ts @@ -1,4 +1,4 @@ -import { BadRequestException, ConsoleLogger, HttpStatus, Injectable } from '@nestjs/common'; +import { HttpStatus, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { In, Repository } from 'typeorm'; import { UserTenantMapping } from 'src/userTenantMapping/entities/user-tenant-mapping.entity'; @@ -84,7 +84,7 @@ export class PostgresAssignTenantService implements IServicelocatorAssignTenant } if (result.length == 0) { - return APIResponse.error(response, apiId, "Bad Request", `User not added to tenants`, HttpStatus.BAD_REQUEST); + return APIResponse.error(response, apiId, "Bad Request", `User not added to tenants ${JSON.stringify(errors)}`, HttpStatus.BAD_REQUEST); } const res = { successCount: result.length, diff --git a/src/userTenantMapping/user-tenant-mapping.controller.ts b/src/userTenantMapping/user-tenant-mapping.controller.ts index d0cecf8a..11907845 100644 --- a/src/userTenantMapping/user-tenant-mapping.controller.ts +++ b/src/userTenantMapping/user-tenant-mapping.controller.ts @@ -56,11 +56,10 @@ export class AssignTenantController { @Body() userTenantMappingDto: UserTenantMappingDto, @Res() response: Response ) { - const result = await this.assignTenantAdapter.buildAssignTenantAdapter().userTenantMapping( + return await this.assignTenantAdapter.buildAssignTenantAdapter().userTenantMapping( request, userTenantMappingDto, response ); - return response.status(result.statusCode).json(result); } } From e8877943fdeefed1d92086f6a14273230c806273 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 30 May 2024 17:23:33 +0530 Subject: [PATCH 375/408] show field name --- src/adapters/postgres/user-adapter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index d3b0e040..f6a2dee6 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -154,6 +154,7 @@ export class PostgresUserService { const customField = { fieldId: data.fieldId, + name: data.name, label: data.label, order: data.ordering, value: fieldValue || '', From 7aa43a09f2636d5a974f31b2af7bedff91dbbf2d Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Thu, 30 May 2024 18:14:40 +0530 Subject: [PATCH 376/408] resolve comments --- src/adapters/postgres/user-adapter.ts | 2 +- src/utils/mask-data.ts | 19 ++++++++++--------- tsconfig.json | 9 +++++++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index f6a2dee6..e91b86f9 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -23,7 +23,7 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; -import { maskMobileNumber, maskEmail, maskDateOfBirth, encrypt } from "src/utils/mask-data"; +import { maskMobileNumber, maskEmail, maskDateOfBirth, encrypt } from "@utils/mask-data"; import { UserData } from 'src/user/user.controller'; import APIResponse from 'src/common/responses/response'; import { Response } from 'express'; diff --git a/src/utils/mask-data.ts b/src/utils/mask-data.ts index 6f95a92f..a3081f6f 100644 --- a/src/utils/mask-data.ts +++ b/src/utils/mask-data.ts @@ -1,23 +1,24 @@ import { Injectable } from '@nestjs/common'; import { createCipheriv, createDecipheriv } from 'crypto'; - const secretKey = Buffer.from(process.env.SECRET_KEY, 'base64'); +// Encrypts the given data export function encrypt(data: string): string { const cipher = createCipheriv('aes-256-ecb', secretKey, null); const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]).toString('base64'); return encrypted; - } +} - export function decrypt(encryptedData: string): string { +// Decrypts the given encrypted data +export function decrypt(encryptedData: string): string { const decipher = createDecipheriv('aes-256-ecb', secretKey, null); const decrypted = Buffer.concat([decipher.update(Buffer.from(encryptedData, 'base64')), decipher.final()]).toString('utf8'); return decrypted; - } - +} -export function maskMobileNumber(mobileNumber: any): string { +// Masks the given mobile number +export function maskMobileNumber(mobileNumber: string): string { const mobileNumberStr = String(mobileNumber); if (mobileNumberStr.length !== 10) { throw new Error('Mobile number must be 10 digits long'); @@ -27,6 +28,7 @@ export function maskMobileNumber(mobileNumber: any): string { return `${prefix}******${suffix}`; } +// Masks the given email address export function maskEmail(email: string): string { if (typeof email !== 'string' || !email.includes('@')) { throw new Error('Invalid email address'); @@ -39,17 +41,16 @@ export function maskEmail(email: string): string { return `${maskedLocalPart}@${domain}`; } - +// Validates the date format export function isValidDateFormat(date: string): boolean { const regex = /^\d{4}-\d{2}-\d{2}$/; return regex.test(date); } +// Masks the given date of birth export function maskDateOfBirth(dob: string): string { if (!isValidDateFormat(dob)) { throw new Error('Invalid date of birth format. Expected format: YYYY-MM-DD'); } return `****${dob.substring(4)}`; } - - diff --git a/tsconfig.json b/tsconfig.json index 46e59c36..1a787ed8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,6 +19,11 @@ "forceConsistentCasingInFileNames": false, "noFallthroughCasesInSwitch": false, "resolveJsonModule": true, - "esModuleInterop": true + "esModuleInterop": true, + "paths": { + "@utils/*": [ + "src/utils/*" + ] // Adjust according to your folder structure + } } -} +} \ No newline at end of file From 44b348430b0e37985188f5496c0fe035355d0399 Mon Sep 17 00:00:00 2001 From: Vaishali K Date: Thu, 30 May 2024 19:06:41 +0530 Subject: [PATCH 377/408] Revert "Task #PS-726 & PS-730 Masked PI data in the user table and columns" --- src/adapters/postgres/user-adapter.ts | 24 +++--------- src/user/entities/user-entity.ts | 23 ++++------- src/utils/mask-data.ts | 56 --------------------------- tsconfig.json | 9 +---- 4 files changed, 15 insertions(+), 97 deletions(-) delete mode 100644 src/utils/mask-data.ts diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index e91b86f9..a1c13655 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -23,7 +23,6 @@ import { UserRoleMapping } from "src/rbac/assign-role/entities/assign-role.entit import { Tenants } from "src/userTenantMapping/entities/tenant.entity"; import { Cohort } from "src/cohort/entities/cohort.entity"; import { Role } from "src/rbac/role/entities/role.entity"; -import { maskMobileNumber, maskEmail, maskDateOfBirth, encrypt } from "@utils/mask-data"; import { UserData } from 'src/user/user.controller'; import APIResponse from 'src/common/responses/response'; import { Response } from 'express'; @@ -31,7 +30,7 @@ import { APIID } from 'src/common/utils/api-id.config'; @Injectable() export class PostgresUserService { - axios = require("axios"); maskEmail + axios = require("axios"); constructor( // private axiosInstance: AxiosInstance, @@ -111,7 +110,7 @@ export class PostgresUserService { }) if (checkExistUser.length == 0) { - return APIResponse.error(response, apiId, "Not Found", `User Id '${userData.userId}' does not exist.`, HttpStatus.NOT_FOUND); + return APIResponse.error(response, apiId, "Not Found",`User Id '${userData.userId}' does not exist.`, HttpStatus.NOT_FOUND); } const result = { @@ -154,7 +153,6 @@ export class PostgresUserService { const customField = { fieldId: data.fieldId, - name: data.name, label: data.label, order: data.ordering, value: fieldValue || '', @@ -169,8 +167,7 @@ export class PostgresUserService { result.userData['customFields'] = customFieldsArray; return await APIResponse.success(response, apiId, { ...result }, HttpStatus.OK, 'User details Fetched Successfully.') - } catch (e) { - ; + } catch (e) {; return APIResponse.error(response, apiId, "Internal Server Error", "Something went wrong", HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -465,6 +462,7 @@ export class PostgresUserService { userCreateDto.userId = resKeycloak; let result = await this.createUserInDatabase(request, userCreateDto); + let fieldData = {}; if (userCreateDto.fieldValues) { @@ -578,8 +576,7 @@ export class PostgresUserService { user.username = userCreateDto?.username user.name = userCreateDto?.name user.email = userCreateDto?.email - user.mobile = userCreateDto?.mobile, - user.dob = userCreateDto?.dob, + user.mobile = Number(userCreateDto?.mobile) || null, user.createdBy = userCreateDto?.createdBy user.updatedBy = userCreateDto?.updatedBy user.userId = userCreateDto?.userId, @@ -588,17 +585,8 @@ export class PostgresUserService { user.address = userCreateDto?.address, user.pincode = userCreateDto?.pincode - if (userCreateDto?.email) { - user.email = maskEmail(user.email) - user.encryptedEmail = encrypt(user.email) - } - if (userCreateDto?.mobile) { - user.mobile = maskMobileNumber(user.mobile) - user.encryptedMobile = encrypt(user.mobile) - } if (userCreateDto?.dob) { - user.dob = maskDateOfBirth(user.dob); - user.encryptedDob = encrypt(user.dob) + user.dob = new Date(userCreateDto.dob); } let result = await this.usersRepository.save(user); diff --git a/src/user/entities/user-entity.ts b/src/user/entities/user-entity.ts index b45c7fa0..1f108b1b 100644 --- a/src/user/entities/user-entity.ts +++ b/src/user/entities/user-entity.ts @@ -12,6 +12,12 @@ export class User { @Column() name: string; + @Column({ type: "date", nullable: true }) + dob: Date; + + @Column({ nullable: true }) + email: string; + @Column({ nullable: true }) district: string; @@ -31,22 +37,7 @@ export class User { updatedAt: Date; @Column() - mobile: string; - - @Column() - encryptedMobile: string; - - @Column({ nullable: true }) - dob: string; - - @Column() - encryptedDob: string; - - @Column({ nullable: true }) - email: string; - - @Column() - encryptedEmail: string; + mobile: number; @Column({ nullable: true }) createdBy: string; diff --git a/src/utils/mask-data.ts b/src/utils/mask-data.ts deleted file mode 100644 index a3081f6f..00000000 --- a/src/utils/mask-data.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { createCipheriv, createDecipheriv } from 'crypto'; - -const secretKey = Buffer.from(process.env.SECRET_KEY, 'base64'); - -// Encrypts the given data -export function encrypt(data: string): string { - const cipher = createCipheriv('aes-256-ecb', secretKey, null); - const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]).toString('base64'); - return encrypted; -} - -// Decrypts the given encrypted data -export function decrypt(encryptedData: string): string { - const decipher = createDecipheriv('aes-256-ecb', secretKey, null); - const decrypted = Buffer.concat([decipher.update(Buffer.from(encryptedData, 'base64')), decipher.final()]).toString('utf8'); - return decrypted; -} - -// Masks the given mobile number -export function maskMobileNumber(mobileNumber: string): string { - const mobileNumberStr = String(mobileNumber); - if (mobileNumberStr.length !== 10) { - throw new Error('Mobile number must be 10 digits long'); - } - const prefix = mobileNumberStr.substring(0, 2); - const suffix = mobileNumberStr.substring(8, 10); - return `${prefix}******${suffix}`; -} - -// Masks the given email address -export function maskEmail(email: string): string { - if (typeof email !== 'string' || !email.includes('@')) { - throw new Error('Invalid email address'); - } - const [localPart, domain] = email.split('@'); - if (localPart.length < 2) { - throw new Error('Invalid email address'); - } - const maskedLocalPart = localPart[0] + '*'.repeat(localPart.length - 2) + localPart[localPart.length - 1]; - return `${maskedLocalPart}@${domain}`; -} - -// Validates the date format -export function isValidDateFormat(date: string): boolean { - const regex = /^\d{4}-\d{2}-\d{2}$/; - return regex.test(date); -} - -// Masks the given date of birth -export function maskDateOfBirth(dob: string): string { - if (!isValidDateFormat(dob)) { - throw new Error('Invalid date of birth format. Expected format: YYYY-MM-DD'); - } - return `****${dob.substring(4)}`; -} diff --git a/tsconfig.json b/tsconfig.json index 1a787ed8..46e59c36 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,11 +19,6 @@ "forceConsistentCasingInFileNames": false, "noFallthroughCasesInSwitch": false, "resolveJsonModule": true, - "esModuleInterop": true, - "paths": { - "@utils/*": [ - "src/utils/*" - ] // Adjust according to your folder structure - } + "esModuleInterop": true } -} \ No newline at end of file +} From 054119d147517a44b09ac8e8b0835295e1eef640 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 30 May 2024 20:08:39 +0530 Subject: [PATCH 378/408] Task #220234 : chore - Changed responses of fields APIs mapping --- src/adapters/fieldsservicelocator.ts | 9 ++-- src/adapters/postgres/fields-adapter.ts | 65 ++++++++++++------------- src/common/utils/api-id.config.ts | 5 +- src/fields/fields.controller.ts | 20 ++++---- 4 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/adapters/fieldsservicelocator.ts b/src/adapters/fieldsservicelocator.ts index 36fd9181..13e69f59 100644 --- a/src/adapters/fieldsservicelocator.ts +++ b/src/adapters/fieldsservicelocator.ts @@ -2,16 +2,17 @@ import { FieldsSearchDto } from "src/fields/dto/fields-search.dto"; import { FieldsDto } from "src/fields/dto/fields.dto"; import { FieldValuesDto } from "src/fields/dto/field-values.dto"; import { FieldValuesSearchDto } from "src/fields/dto/field-values-search.dto"; +import { Response } from "express"; export interface IServicelocatorfields { //fields - createFields(request: any, fieldsDto: FieldsDto); + createFields(request: any, fieldsDto: FieldsDto, response: Response); // getFields(tenantId, fieldsId, request); - searchFields(tenantid, request: any, fieldsSearchDto: FieldsSearchDto); + searchFields(tenantid, request: any, fieldsSearchDto: FieldsSearchDto,response: Response); // updateFields(fieldsId: string, request: any, fieldsDto: FieldsDto); //field values - createFieldValues(request: any, fieldValuesDto: FieldValuesDto,response); + createFieldValues(request: any, fieldValuesDto: FieldValuesDto,response : Response); // getFieldValues(id, request); - searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto); + searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto, response: Response); updateFieldValues(id: string, request: any, fieldValuesDto: FieldValuesDto); } diff --git a/src/adapters/postgres/fields-adapter.ts b/src/adapters/postgres/fields-adapter.ts index 2ac62e28..9003bb93 100644 --- a/src/adapters/postgres/fields-adapter.ts +++ b/src/adapters/postgres/fields-adapter.ts @@ -13,9 +13,11 @@ import { SuccessResponse } from "src/success-response"; import { ErrorResponseTypeOrm } from "src/error-response-typeorm"; import APIResponse from "src/common/responses/response"; import { APIID } from "src/common/utils/api-id.config"; +import { IServicelocatorfields } from "../fieldsservicelocator"; +import { Response } from "express"; @Injectable() -export class PostgresFieldsService { +export class PostgresFieldsService implements IServicelocatorfields { constructor( @InjectRepository(Fields) private fieldsRepository: Repository, @@ -24,9 +26,9 @@ export class PostgresFieldsService { ) { } //fields - async createFields(request: any, fieldsDto: FieldsDto) { + async createFields(request: any, fieldsDto: FieldsDto, response: Response,) { + const apiId = APIID.FIELDS_CREATE; try { - const fieldsData: any = {}; // Define an empty object to store field data Object.keys(fieldsDto).forEach((e) => { @@ -42,21 +44,18 @@ export class PostgresFieldsService { }); let result = await this.fieldsRepository.save(fieldsData); - return new SuccessResponse({ - statusCode: HttpStatus.CREATED, - message: "Ok.", - data: result, - }); + + return await APIResponse.success(response, apiId, result, + HttpStatus.CREATED, 'Fields created successfully.') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + const errorMessage = e?.message || 'Something went wrong'; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${errorMessage}`, HttpStatus.INTERNAL_SERVER_ERROR) } } - async searchFields(tenantId: string, request: any, fieldsSearchDto: FieldsSearchDto) { + async searchFields(tenantId: string, request: any, fieldsSearchDto: FieldsSearchDto,response :Response) { + const apiId = APIID.FIELDS_SEARCH; try { const getConditionalData = await this.search(fieldsSearchDto) @@ -67,18 +66,18 @@ export class PostgresFieldsService { const getFieldValue = await this.searchFieldData(offset, limit, whereClause) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', + const result = { totalCount: getFieldValue.totalCount, - data: getFieldValue.mappedResponse, - }); + fields: getFieldValue.mappedResponse, + } + + return await APIResponse.success(response, apiId, result, + HttpStatus.OK, 'Fields fetched successfully.') + } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + const errorMessage = e?.message || 'Something went wrong'; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${errorMessage}`, HttpStatus.INTERNAL_SERVER_ERROR) } } @@ -102,7 +101,7 @@ export class PostgresFieldsService { return { mappedResponse, totalCount }; } - async createFieldValues(request: any, fieldValuesDto: FieldValuesDto,res) { + async createFieldValues(request: any, fieldValuesDto: FieldValuesDto,res:Response) { const apiId = APIID.FIELDVALUES_CREATE; @@ -128,7 +127,8 @@ export class PostgresFieldsService { } } - async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto) { + async searchFieldValues(request: any, fieldValuesSearchDto: FieldValuesSearchDto, response: Response) { + const apiId = APIID.FIELDVALUES_SEARCH; try { const getConditionalData = await this.search(fieldValuesSearchDto) const offset = getConditionalData.offset; @@ -137,18 +137,17 @@ export class PostgresFieldsService { const getFieldValue = await this.getSearchFieldValueData(offset, limit, whereClause) - return new SuccessResponse({ - statusCode: HttpStatus.OK, - message: 'Ok.', + const result = { totalCount: getFieldValue.totalCount, - data: getFieldValue.mappedResponse, - }); + fields: getFieldValue.mappedResponse, + } + + return await APIResponse.success(response, apiId, result, + HttpStatus.OK, 'Field Values fetched successfully.') } catch (e) { - return new ErrorResponseTypeOrm({ - statusCode: HttpStatus.INTERNAL_SERVER_ERROR, - errorMessage: e, - }); + const errorMessage = e?.message || 'Something went wrong'; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${errorMessage}`, HttpStatus.INTERNAL_SERVER_ERROR) } } diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index 4a5d7b20..54ba080e 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -29,6 +29,9 @@ export const APIID = { COHORT_READ: "api.cohort.read", COHORT_UPDATE: "api.cohort.update", COHORT_DELETE: "api.cohort.delete", + ASSIGN_TENANT_CREATE:"api.assigntenant.create", + FIELDS_CREATE: "api.fields.create", + FIELDS_SEARCH:"api.fields.search", FIELDVALUES_CREATE: "api.fieldValues.create", - ASSIGN_TENANT_CREATE:"api.assigntenant.create" + FIELDVALUES_SEARCH: "api.fieldValues.search" } diff --git a/src/fields/fields.controller.ts b/src/fields/fields.controller.ts index 4279324a..676c725e 100644 --- a/src/fields/fields.controller.ts +++ b/src/fields/fields.controller.ts @@ -42,7 +42,7 @@ export class FieldsController { //fields //create fields - @Post() + @Post("/create") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Fields has been created successfully." }) @ApiBody({ type: FieldsDto }) @@ -62,8 +62,7 @@ export class FieldsController { tenantId: tenantid, }; Object.assign(fieldsDto, payload); - const result = await this.fieldsAdapter.buildFieldsAdapter().createFields(request, fieldsDto); - return response.status(result.statusCode).json(result); + return await this.fieldsAdapter.buildFieldsAdapter().createFields(request, fieldsDto, response); } //search @@ -86,18 +85,18 @@ export class FieldsController { @Res() response: Response ) { let tenantid = headers["tenantid"]; - const result = await this.fieldsAdapter.buildFieldsAdapter().searchFields( + return await this.fieldsAdapter.buildFieldsAdapter().searchFields( tenantid, request, - fieldsSearchDto + fieldsSearchDto, + response ); - return response.status(result.statusCode).json(result); } //field values //create fields values @UseFilters(new AllExceptionsFilter(APIID.FIELDVALUES_CREATE)) - @Post("/values") + @Post("/values/create") @ApiBasicAuth("access-token") @ApiCreatedResponse({ description: "Fields Values has been created successfully.", @@ -115,7 +114,6 @@ export class FieldsController { fieldValuesDto, response ); - } //search fields values @@ -133,10 +131,10 @@ export class FieldsController { @Body() fieldValuesSearchDto: FieldValuesSearchDto, @Res() response: Response ) { - const result = await this.fieldsAdapter.buildFieldsAdapter().searchFieldValues( + return await this.fieldsAdapter.buildFieldsAdapter().searchFieldValues( request, - fieldValuesSearchDto + fieldValuesSearchDto, + response ); - return response.status(result.statusCode).json(result); } } From 64986549d6ea22da9a4ca83cb04e85a73f758b57 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 30 May 2024 20:59:02 +0530 Subject: [PATCH 379/408] Task #220234 : chore - minor fix --- src/user/user.controller.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 2c7cf72e..d4ba5f47 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -187,6 +187,7 @@ export class UserController { } //delete + @UseFilters(new AllExceptionsFilter(APIID.USER_DELETE)) @Delete("delete/:userId") @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") From 17b3eb828267f22e69b10bc72934095a45294de4 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam Date: Thu, 30 May 2024 21:13:01 +0530 Subject: [PATCH 380/408] Task #220252 : refactor - Update responses for keycloak auth apis --- src/auth/auth.controller.ts | 25 ++++++----- src/auth/auth.service.ts | 70 ++++++++++++++++++------------- src/common/utils/api-id.config.ts | 6 ++- 3 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index f75ac149..e564b26d 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -14,12 +14,12 @@ import { SerializeOptions, Req, Res, - Response, HttpStatus, HttpCode, UsePipes, ValidationPipe, UseGuards, + UseFilters, } from "@nestjs/common"; import { AuthDto, @@ -28,24 +28,27 @@ import { } from "./dto/auth-dto"; import { AuthService } from "./auth.service"; import { JwtAuthGuard } from "src/common/guards/keycloak.guard"; -import { RbacAuthGuard } from "src/common/guards/rbac.guard"; -import { Permissions } from "src/common/decorators/permission.decorator"; +import { APIID } from "src/common/utils/api-id.config"; +import { AllExceptionsFilter } from "src/common/filters/exception.filter"; +import { Response } from "express"; @ApiTags("Auth") @Controller("auth") export class AuthController { constructor(private authService: AuthService) {} + @UseFilters(new AllExceptionsFilter(APIID.LOGIN)) @Post("/login") @ApiBody({ type: AuthDto }) @UsePipes(ValidationPipe) @HttpCode(HttpStatus.OK) @ApiForbiddenResponse({ description: "Forbidden" }) - public async login(@Body() authDto: AuthDto) { - return this.authService.login(authDto); + public async login(@Body() authDto: AuthDto, @Res() response: Response) { + return this.authService.login(authDto,response); } - @Get("/user") + @UseFilters(new AllExceptionsFilter(APIID.USER_AUTH)) + @Get("/") @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiOkResponse({ description: "User detail." }) @@ -57,23 +60,25 @@ export class AuthController { return this.authService.getUserByAuth(request, response); } + @UseFilters(new AllExceptionsFilter(APIID.REFRESH)) @Post("/refresh") @HttpCode(HttpStatus.OK) @ApiBody({ type: RefreshTokenRequestBody }) @UsePipes(ValidationPipe) - refreshToken(@Body() body: RefreshTokenRequestBody) { + refreshToken(@Body() body: RefreshTokenRequestBody, @Res() response: Response) { const { refresh_token: refreshToken } = body; - return this.authService.refreshToken(refreshToken); + return this.authService.refreshToken(refreshToken,response); } + @UseFilters(new AllExceptionsFilter(APIID.LOGOUT)) @Post("/logout") @UsePipes(ValidationPipe) @HttpCode(HttpStatus.OK) @ApiBody({ type: LogoutRequestBody }) - async logout(@Body() body: LogoutRequestBody) { + async logout(@Body() body: LogoutRequestBody, @Res() response: Response) { const { refresh_token: refreshToken } = body; - await this.authService.logout(refreshToken); + await this.authService.logout(refreshToken,response); } } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 9572c864..6022aad8 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -2,8 +2,10 @@ import { HttpStatus, Injectable, NotFoundException, UnauthorizedException } from import { UserAdapter } from "src/user/useradapter"; import axios from "axios"; import jwt_decode from "jwt-decode"; -import APIResponse from "src/utils/response"; +import APIResponse from "src/common/responses/response"; import { KeycloakService } from "src/common/utils/keycloak.service"; +import { APIID } from "src/common/utils/api-id.config"; +import { Response } from "express"; type LoginResponse = { @@ -14,15 +16,14 @@ type LoginResponse = { }; @Injectable() export class AuthService { - private axiosInstance; + constructor( private readonly useradapter: UserAdapter, private readonly keycloakService: KeycloakService - ) { - this.axiosInstance = axios.create(); - } + ) {} - async login(authDto) { + async login(authDto,response: Response) { + const apiId = APIID.LOGIN; const { username, password } = authDto; try { const { @@ -33,64 +34,73 @@ export class AuthService { token_type } = await this.keycloakService.login(username, password); - return { + const res = { access_token, refresh_token, expires_in, refresh_expires_in, token_type }; + + return APIResponse.success(response, apiId, res, + HttpStatus.OK, "Auth Token fetched Successfully.") } catch (error) { if (error.response && error.response.status === 401) { throw new NotFoundException("Invalid username or password"); } else { - throw error; + const errorMessage = error?.message || 'Something went wrong'; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${errorMessage}`, HttpStatus.INTERNAL_SERVER_ERROR) } } } - public async getUserByAuth(request: any, response) { - let apiId = "api.auth.getUserDetails"; + public async getUserByAuth(request: any, response:Response) { + let apiId = APIID.USER_AUTH; try { const decoded: any = jwt_decode(request.headers.authorization); const username = decoded.preferred_username; - let data = await this.useradapter.buildUserAdapter().findUserDetails(null, username); - return response - .status(HttpStatus.OK) - .send(APIResponse.success(apiId, data, "OK")); + const data = await this.useradapter.buildUserAdapter().findUserDetails(null, username); + + return APIResponse.success(response, apiId, data, + HttpStatus.OK, "User fetched by auth token Successfully.") } catch (e) { - response - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .send( - APIResponse.error( - apiId, - "Something went wrong In finding UserDetails", - e, - "INTERNAL_SERVER_ERROR" - ) - ); + const errorMessage = e?.message || 'Something went wrong'; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${errorMessage}`, HttpStatus.INTERNAL_SERVER_ERROR) } } - async refreshToken(refreshToken: string): Promise { + async refreshToken(refreshToken: string, response: Response): Promise { + const apiId = APIID.REFRESH; const { access_token, expires_in, refresh_token, refresh_expires_in } = await this.keycloakService.refreshToken(refreshToken).catch(() => { throw new UnauthorizedException(); }); - return { + const res = { access_token, refresh_token, expires_in, refresh_expires_in, }; + return APIResponse.success(response, apiId, res, + HttpStatus.OK, "Refresh Token fetched Successfully.") } - async logout(refreshToken: string) { - await this.keycloakService.logout(refreshToken).catch(() => { - throw new UnauthorizedException(); - }); + async logout(refreshToken: string, response: Response) { + const apiId = APIID.LOGOUT; + try { + const logout = await this.keycloakService.logout(refreshToken); + return APIResponse.success(response, apiId, logout, + HttpStatus.OK, "Logged Out Successfully.") + } catch (error) { + if (error.response && error.response.status === 400) { + throw new UnauthorizedException(); + } else { + const errorMessage = error?.message || 'Something went wrong'; + return APIResponse.error(response, apiId, "Internal Server Error", `Error : ${errorMessage}`, HttpStatus.INTERNAL_SERVER_ERROR) + } + } } } diff --git a/src/common/utils/api-id.config.ts b/src/common/utils/api-id.config.ts index 54ba080e..400cfe23 100644 --- a/src/common/utils/api-id.config.ts +++ b/src/common/utils/api-id.config.ts @@ -33,5 +33,9 @@ export const APIID = { FIELDS_CREATE: "api.fields.create", FIELDS_SEARCH:"api.fields.search", FIELDVALUES_CREATE: "api.fieldValues.create", - FIELDVALUES_SEARCH: "api.fieldValues.search" + FIELDVALUES_SEARCH: "api.fieldValues.search", + LOGIN: "api.login", + LOGOUT: "api.logout", + REFRESH: "api.refresh", + USER_AUTH: "api.user.auth" } From 3cd26aa3a25b773b95357b76e30db43b80a1354b Mon Sep 17 00:00:00 2001 From: Shubham Date: Fri, 31 May 2024 14:23:17 +0530 Subject: [PATCH 381/408] Issue PS-728 fix: Adeed name data in Custom field Response --- src/adapters/postgres/user-adapter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 1c2cda44..28d79628 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -154,6 +154,7 @@ export class PostgresUserService implements IServicelocator { const customField = { fieldId: data.fieldId, + name:data?.name, label: data.label, order: data.ordering, value: fieldValue || '', From 3d1d48e4e9dead9673da1a90072415e45de9bdf9 Mon Sep 17 00:00:00 2001 From: AbhilashKD Date: Fri, 31 May 2024 17:57:03 +0530 Subject: [PATCH 382/408] Adding Backend file for Shiksha --- manifest/backend.yaml | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 manifest/backend.yaml diff --git a/manifest/backend.yaml b/manifest/backend.yaml new file mode 100644 index 00000000..58c7e6bd --- /dev/null +++ b/manifest/backend.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: /snap/kompose/19/kompose-linux-amd64 convert -f shiksha.yaml + kompose.version: 1.21.0 (992df58d8) + creationTimestamp: null + labels: + io.kompose.service: backend + name: backend +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: backend + strategy: {} + template: + metadata: + annotations: + kompose.cmd: /snap/kompose/19/kompose-linux-amd64 convert -f shiksha.yaml + kompose.version: 1.21.0 (992df58d8) + creationTimestamp: null + labels: + io.kompose.service: backend + spec: + containers: + - image: dubea/pratham-backend:latest + imagePullPolicy: "" + name: backend-pratham + ports: + - containerPort: 3000 + resources: {} + restartPolicy: Always + serviceAccountName: "" + volumes: null +status: {} + +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: /snap/kompose/19/kompose-linux-amd64 convert -f backend.yaml + kompose.version: 1.21.0 (992df58d8) + labels: + io.kompose.service: backend + name: backend +spec: + type: NodePort + ports: + - port: 31265 + targetPort: 3000 + nodePort: 31265 + selector: + io.kompose.service: backend From f408286a09a17af2ab40d78051477cf0feaf5b3e Mon Sep 17 00:00:00 2001 From: AbhilashKD Date: Fri, 31 May 2024 18:07:57 +0530 Subject: [PATCH 383/408] Added the repo for backend --- manifest/backend.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/backend.yaml b/manifest/backend.yaml index 58c7e6bd..6b36c6ee 100644 --- a/manifest/backend.yaml +++ b/manifest/backend.yaml @@ -24,7 +24,7 @@ spec: io.kompose.service: backend spec: containers: - - image: dubea/pratham-backend:latest + - image: ${ECR_REPOSITORY}:${IMAGE_TAG} imagePullPolicy: "" name: backend-pratham ports: From 940712544389db99b60ba279a35417751be17739 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Fri, 31 May 2024 18:09:20 +0530 Subject: [PATCH 384/408] Create eks-pratham-deployment.yamleks-pratham-deployment.yaml --- ...deployment.yamleks-pratham-deployment.yaml | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml diff --git a/.github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml new file mode 100644 index 00000000..415baf95 --- /dev/null +++ b/.github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml @@ -0,0 +1,73 @@ +name: Deploy to EKS-Pratham-Backend Service +on: + push: + branches: + - main +env: + ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} + EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} + AWS_REGION: ${{ secrets.AWS_REGION_NAME }} + +jobs: + + build: + + name: Deployment + runs-on: ubuntu-latest + + steps: + - name: Set short git commit SHA + id: commit + uses: prompt/actions-commit-hash@v2 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{env.AWS_REGION}} + + - name: Setup Node Env + uses: actions/setup-node@v3 + with: + node-version: 21.1.0 + + - name: Copy .env file + env: + ENV_FILE_CONTENT: ${{ secrets.ENV_FILE_CONTENT }} + run: echo "$ENV_FILE_CONTENT" > .env + + - name: Show PWD and list content + run: | + echo "Current Working Directory: pwd" + pwd + ls -ltra + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build, tag, and push image to Amazon ECR + run: | + aws ecr --region ${{ secrets.AWS_REGION_NAME }} | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} + docker build -t ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} . + docker push ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} + + - name: Update kube config + run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION_NAME }} + + - name: Deploy to EKS + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: ${{ secrets.IMAGE_TAG }} + ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} + ECR_IMAGE: ${{ secrets.ECR_IMAGE }} + run: | + export ECR_REPOSITORY=${{ secrets.ECR_REPOSITORY }} + export IMAGE_TAG=${{ secrets.IMAGE_TAG }} + export ECR_IMAGE=${{ secrets.ECR_IMAGE }} + envsubst < manifest/attendance-service.yaml > manifest/attendance-service-updated.yaml + cat manifest/attendance-service-updated.yaml + kubectl apply -f manifest/attendance-service-updated.yaml From 866be4aa931283d54050472f5224cecba6066964 Mon Sep 17 00:00:00 2001 From: AbhilashKD Date: Fri, 31 May 2024 18:11:16 +0530 Subject: [PATCH 385/408] Renamed the EKS file --- .github/workflows/eks-pratham-deployment.yaml | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/eks-pratham-deployment.yaml diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml new file mode 100644 index 00000000..415baf95 --- /dev/null +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -0,0 +1,73 @@ +name: Deploy to EKS-Pratham-Backend Service +on: + push: + branches: + - main +env: + ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} + EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} + AWS_REGION: ${{ secrets.AWS_REGION_NAME }} + +jobs: + + build: + + name: Deployment + runs-on: ubuntu-latest + + steps: + - name: Set short git commit SHA + id: commit + uses: prompt/actions-commit-hash@v2 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{env.AWS_REGION}} + + - name: Setup Node Env + uses: actions/setup-node@v3 + with: + node-version: 21.1.0 + + - name: Copy .env file + env: + ENV_FILE_CONTENT: ${{ secrets.ENV_FILE_CONTENT }} + run: echo "$ENV_FILE_CONTENT" > .env + + - name: Show PWD and list content + run: | + echo "Current Working Directory: pwd" + pwd + ls -ltra + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build, tag, and push image to Amazon ECR + run: | + aws ecr --region ${{ secrets.AWS_REGION_NAME }} | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} + docker build -t ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} . + docker push ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} + + - name: Update kube config + run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION_NAME }} + + - name: Deploy to EKS + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: ${{ secrets.IMAGE_TAG }} + ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} + ECR_IMAGE: ${{ secrets.ECR_IMAGE }} + run: | + export ECR_REPOSITORY=${{ secrets.ECR_REPOSITORY }} + export IMAGE_TAG=${{ secrets.IMAGE_TAG }} + export ECR_IMAGE=${{ secrets.ECR_IMAGE }} + envsubst < manifest/attendance-service.yaml > manifest/attendance-service-updated.yaml + cat manifest/attendance-service-updated.yaml + kubectl apply -f manifest/attendance-service-updated.yaml From 27d10ef47dac337e7b8c3620b4cc605cd88448cf Mon Sep 17 00:00:00 2001 From: AbhilashKD Date: Fri, 31 May 2024 18:13:25 +0530 Subject: [PATCH 386/408] Removed EKS file --- .github/workflows/eks-pratham-deployment.yaml | 73 ------------------- ...deployment.yamleks-pratham-deployment.yaml | 73 ------------------- 2 files changed, 146 deletions(-) delete mode 100644 .github/workflows/eks-pratham-deployment.yaml delete mode 100644 .github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml deleted file mode 100644 index 415baf95..00000000 --- a/.github/workflows/eks-pratham-deployment.yaml +++ /dev/null @@ -1,73 +0,0 @@ -name: Deploy to EKS-Pratham-Backend Service -on: - push: - branches: - - main -env: - ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} - EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} - AWS_REGION: ${{ secrets.AWS_REGION_NAME }} - -jobs: - - build: - - name: Deployment - runs-on: ubuntu-latest - - steps: - - name: Set short git commit SHA - id: commit - uses: prompt/actions-commit-hash@v2 - - - name: Check out code - uses: actions/checkout@v2 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{env.AWS_REGION}} - - - name: Setup Node Env - uses: actions/setup-node@v3 - with: - node-version: 21.1.0 - - - name: Copy .env file - env: - ENV_FILE_CONTENT: ${{ secrets.ENV_FILE_CONTENT }} - run: echo "$ENV_FILE_CONTENT" > .env - - - name: Show PWD and list content - run: | - echo "Current Working Directory: pwd" - pwd - ls -ltra - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Build, tag, and push image to Amazon ECR - run: | - aws ecr --region ${{ secrets.AWS_REGION_NAME }} | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} - docker build -t ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} . - docker push ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} - - - name: Update kube config - run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION_NAME }} - - - name: Deploy to EKS - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: ${{ secrets.IMAGE_TAG }} - ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} - ECR_IMAGE: ${{ secrets.ECR_IMAGE }} - run: | - export ECR_REPOSITORY=${{ secrets.ECR_REPOSITORY }} - export IMAGE_TAG=${{ secrets.IMAGE_TAG }} - export ECR_IMAGE=${{ secrets.ECR_IMAGE }} - envsubst < manifest/attendance-service.yaml > manifest/attendance-service-updated.yaml - cat manifest/attendance-service-updated.yaml - kubectl apply -f manifest/attendance-service-updated.yaml diff --git a/.github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml deleted file mode 100644 index 415baf95..00000000 --- a/.github/workflows/eks-pratham-deployment.yamleks-pratham-deployment.yaml +++ /dev/null @@ -1,73 +0,0 @@ -name: Deploy to EKS-Pratham-Backend Service -on: - push: - branches: - - main -env: - ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} - EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} - AWS_REGION: ${{ secrets.AWS_REGION_NAME }} - -jobs: - - build: - - name: Deployment - runs-on: ubuntu-latest - - steps: - - name: Set short git commit SHA - id: commit - uses: prompt/actions-commit-hash@v2 - - - name: Check out code - uses: actions/checkout@v2 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{env.AWS_REGION}} - - - name: Setup Node Env - uses: actions/setup-node@v3 - with: - node-version: 21.1.0 - - - name: Copy .env file - env: - ENV_FILE_CONTENT: ${{ secrets.ENV_FILE_CONTENT }} - run: echo "$ENV_FILE_CONTENT" > .env - - - name: Show PWD and list content - run: | - echo "Current Working Directory: pwd" - pwd - ls -ltra - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Build, tag, and push image to Amazon ECR - run: | - aws ecr --region ${{ secrets.AWS_REGION_NAME }} | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} - docker build -t ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} . - docker push ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} - - - name: Update kube config - run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION_NAME }} - - - name: Deploy to EKS - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: ${{ secrets.IMAGE_TAG }} - ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} - ECR_IMAGE: ${{ secrets.ECR_IMAGE }} - run: | - export ECR_REPOSITORY=${{ secrets.ECR_REPOSITORY }} - export IMAGE_TAG=${{ secrets.IMAGE_TAG }} - export ECR_IMAGE=${{ secrets.ECR_IMAGE }} - envsubst < manifest/attendance-service.yaml > manifest/attendance-service-updated.yaml - cat manifest/attendance-service-updated.yaml - kubectl apply -f manifest/attendance-service-updated.yaml From 41df3d49926c508280aa68492442267dd366015e Mon Sep 17 00:00:00 2001 From: AbhilashKD Date: Fri, 31 May 2024 18:14:16 +0530 Subject: [PATCH 387/408] Added EKS file --- .github/workflows/eks-pratham-deployment.yaml | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/eks-pratham-deployment.yaml diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml new file mode 100644 index 00000000..415baf95 --- /dev/null +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -0,0 +1,73 @@ +name: Deploy to EKS-Pratham-Backend Service +on: + push: + branches: + - main +env: + ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} + EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} + AWS_REGION: ${{ secrets.AWS_REGION_NAME }} + +jobs: + + build: + + name: Deployment + runs-on: ubuntu-latest + + steps: + - name: Set short git commit SHA + id: commit + uses: prompt/actions-commit-hash@v2 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{env.AWS_REGION}} + + - name: Setup Node Env + uses: actions/setup-node@v3 + with: + node-version: 21.1.0 + + - name: Copy .env file + env: + ENV_FILE_CONTENT: ${{ secrets.ENV_FILE_CONTENT }} + run: echo "$ENV_FILE_CONTENT" > .env + + - name: Show PWD and list content + run: | + echo "Current Working Directory: pwd" + pwd + ls -ltra + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build, tag, and push image to Amazon ECR + run: | + aws ecr --region ${{ secrets.AWS_REGION_NAME }} | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} + docker build -t ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} . + docker push ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} + + - name: Update kube config + run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION_NAME }} + + - name: Deploy to EKS + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: ${{ secrets.IMAGE_TAG }} + ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} + ECR_IMAGE: ${{ secrets.ECR_IMAGE }} + run: | + export ECR_REPOSITORY=${{ secrets.ECR_REPOSITORY }} + export IMAGE_TAG=${{ secrets.IMAGE_TAG }} + export ECR_IMAGE=${{ secrets.ECR_IMAGE }} + envsubst < manifest/attendance-service.yaml > manifest/attendance-service-updated.yaml + cat manifest/attendance-service-updated.yaml + kubectl apply -f manifest/attendance-service-updated.yaml From be96174ab2be4a2154fc769892aa0716efcbbc90 Mon Sep 17 00:00:00 2001 From: AbhilashKD Date: Fri, 31 May 2024 18:15:40 +0530 Subject: [PATCH 388/408] Changed the file name --- .github/workflows/eks-pratham-deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index 415baf95..39bf1406 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -2,7 +2,7 @@ name: Deploy to EKS-Pratham-Backend Service on: push: branches: - - main + - Shiksha-2.0 env: ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} From a51e590f37aec24c2437fa012c28a26eee5d3554 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Fri, 31 May 2024 18:21:44 +0530 Subject: [PATCH 389/408] Update eks-pratham-deployment.yaml --- .github/workflows/eks-pratham-deployment.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index 39bf1406..11e58d33 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -68,6 +68,6 @@ jobs: export ECR_REPOSITORY=${{ secrets.ECR_REPOSITORY }} export IMAGE_TAG=${{ secrets.IMAGE_TAG }} export ECR_IMAGE=${{ secrets.ECR_IMAGE }} - envsubst < manifest/attendance-service.yaml > manifest/attendance-service-updated.yaml - cat manifest/attendance-service-updated.yaml - kubectl apply -f manifest/attendance-service-updated.yaml + envsubst < manifest/backend.yaml > manifest/backend-updated.yaml + cat manifest/backend-updated.yaml + kubectl apply -f manifest/backend-updated.yaml From 4a3881c65a9352030dad7fa5f0110824bb59d828 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Sun, 2 Jun 2024 14:12:37 +0530 Subject: [PATCH 390/408] Update Profile: Store wrong data into database --- src/adapters/postgres/user-adapter.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 28d79628..9dd088ae 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -111,7 +111,7 @@ export class PostgresUserService implements IServicelocator { }) if (checkExistUser.length == 0) { - return APIResponse.error(response, apiId, "Not Found",`User Id '${userData.userId}' does not exist.`, HttpStatus.NOT_FOUND); + return APIResponse.error(response, apiId, "Not Found", `User Id '${userData.userId}' does not exist.`, HttpStatus.NOT_FOUND); } const result = { @@ -154,7 +154,7 @@ export class PostgresUserService implements IServicelocator { const customField = { fieldId: data.fieldId, - name:data?.name, + name: data?.name, label: data.label, order: data.ordering, value: fieldValue || '', @@ -169,7 +169,8 @@ export class PostgresUserService implements IServicelocator { result.userData['customFields'] = customFieldsArray; return await APIResponse.success(response, apiId, { ...result }, HttpStatus.OK, 'User details Fetched Successfully.') - } catch (e) {; + } catch (e) { + ; return APIResponse.error(response, apiId, "Internal Server Error", "Something went wrong", HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -404,7 +405,7 @@ export class PostgresUserService implements IServicelocator { for (let value of data.value) { dataArray.push(value.toLowerCase().replace(/ /g, '_')); } - data.value = dataArray.join(', '); + data.value = dataArray.join(','); } let result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); From d02182e8d805743172da1a536002ceed2f3cb71d Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 3 Jun 2024 19:30:05 +0530 Subject: [PATCH 391/408] Issue Fix PS-766: Added DTO validation in Update User API --- src/user/dto/user-update.dto.ts | 25 ++++++++++++++++++++----- src/user/user.controller.ts | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/user/dto/user-update.dto.ts b/src/user/dto/user-update.dto.ts index 8079b6d3..55c24f59 100644 --- a/src/user/dto/user-update.dto.ts +++ b/src/user/dto/user-update.dto.ts @@ -1,18 +1,22 @@ -import { IsString, IsOptional, IsArray, ValidateNested } from 'class-validator'; +import { IsString, IsOptional, IsArray, ValidateNested, IsNotEmpty, IsEnum } from 'class-validator'; import { Expose, Type } from 'class-transformer'; class UserDataDTO { @IsString() + @IsOptional() username: string; @IsString() + @IsNotEmpty() name: string; @IsString() + @IsOptional() role: string; @IsOptional() + @IsString() dob: string | null; @IsOptional() @@ -36,44 +40,55 @@ class UserDataDTO { pincode: string | null; @IsString() + @IsOptional() createdAt: string; @IsString() + @IsOptional() updatedAt: string; @IsString() + @IsOptional() createdBy: string; @IsString() + @IsOptional() updatedBy: string; @IsString() + @IsOptional() tenantId: string; @IsString() + @IsOptional() status: string; } - class CustomFieldDTO { + @IsString() + @Expose() + @IsNotEmpty() fieldId: string; - @IsString() - value: string; + @IsNotEmpty() + @Expose() + value: string | string[]; } export class UserUpdateDTO { - @IsString() userId: string; @Expose() @ValidateNested() + @IsNotEmpty() @Type(() => UserDataDTO) userData: UserDataDTO; @IsArray() + @IsOptional() @ValidateNested({ each: true }) @Type(() => CustomFieldDTO) + @Expose() customFields: CustomFieldDTO[]; } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index d4ba5f47..e8457ff7 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -113,6 +113,7 @@ export class UserController { @UseFilters(new AllExceptionsFilter(APIID.USER_UPDATE)) @Patch("update/:userid") + @UsePipes(new ValidationPipe()) @UseGuards(JwtAuthGuard) @ApiBasicAuth("access-token") @ApiBody({ type: UserUpdateDTO }) From d0ddc21dcf2949d9b2cb8fe5527997deab19264c Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 4 Jun 2024 17:04:39 +0530 Subject: [PATCH 392/408] Issue PS-770 Feat: Added Logic for fetching state Options . --- src/adapters/postgres/cohort-adapter.ts | 46 ++++++++++++++++++++++--- src/cohort/cohort.module.ts | 3 +- src/cohort/entities/state.entity.ts | 16 +++++++++ src/fields/entities/fields.entity.ts | 3 ++ src/user/dto/user-update.dto.ts | 1 - 5 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 src/cohort/entities/state.entity.ts diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index 434d1fb7..b0d73155 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -21,12 +21,15 @@ import { isUUID } from "class-validator"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; import APIResponse from "src/common/responses/response"; import { APIID } from "src/common/utils/api-id.config"; +import { State } from "src/cohort/entities/state.entity"; @Injectable() export class PostgresCohortService { constructor( + @InjectRepository(State) + private stateRepository: Repository, @InjectRepository(Cohort) private cohortRepository: Repository, @InjectRepository(CohortMembers) @@ -38,6 +41,7 @@ export class PostgresCohortService { @InjectRepository(UserTenantMapping) private UserTenantMappingRepository: Repository, private fieldsService: PostgresFieldsService, + ) { } public async getCohortList( @@ -93,7 +97,6 @@ export class PostgresCohortService { if (checkData === true) { const result = await this.getCohortDataWithCustomfield(cohortId); return APIResponse.success(res, apiId, result, (HttpStatus.OK), "Cohort details fetched succcessfully."); - } else { return APIResponse.error( res, @@ -135,12 +138,48 @@ export class PostgresCohortService { options: data?.fieldParams?.['options'] || {}, type: data.type || '' }; + customField["dependsOn"] = null; + if(data.source_details){ + // We need to add the dependence Condition here. + if(data?.source_details?.source === 'table' && data?.source_details.depends_on === "null"){ + let dynamicOptions = await this.findDynamicOptions(data?.source_details?.table); + customField.options = dynamicOptions + customField["dependsOn"] = null; + }else if(data?.source_details?.source === 'table' && data?.source_details.depends_on){ + customField.options = {}; + customField["dependsOn"] = data?.source_details.depends_on; + }else{ + customField["dependsOn"] = null; + customField.options = data.fieldParams; + } + } customFieldsArray.push(customField); } result.cohortData['customFields'] = customFieldsArray; return result } + async findDynamicOptions(tableName,whereClause?:{}){ + let query:string; + let result; + if(whereClause){ + query = `select * from public."${tableName} where=${whereClause}"` + result = await this.cohortRepository.query(query); + if(!result){ + return null; + } + return result; + } + query = `select * from public."${tableName}"` + result = await this.cohortRepository.query(query); + if(!result){ + return null; + } + return result.map(result => ({ + value: result.value, + label: result.name + })); + } async findFilledValues(cohortId: string) { let query = `SELECT C."cohortId",F."fieldId",F."value" FROM public."Cohort" C @@ -168,6 +207,7 @@ export class PostgresCohortService { return customFields; } + public async findCohortName(userId: any) { let query = `SELECT c."name",c."cohortId",c."parentId" FROM public."CohortMembers" AS cm @@ -202,9 +242,7 @@ export class PostgresCohortService { } return { valid: true, fieldId: "true" }; }; - - - + public async createCohort(request: any, cohortCreateDto: CohortCreateDto, res) { const apiId = APIID.COHORT_CREATE; diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index e8dddc71..5df09e1d 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -12,10 +12,11 @@ import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { PostgresModule } from "src/adapters/postgres/potsgres-module"; import { PostgresCohortService } from "src/adapters/postgres/cohort-adapter"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; +import { State } from "./entities/state.entity"; @Module({ imports: [ - TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers, UserTenantMapping]), + TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers, UserTenantMapping,State]), HttpModule, HasuraModule, PostgresModule diff --git a/src/cohort/entities/state.entity.ts b/src/cohort/entities/state.entity.ts new file mode 100644 index 00000000..324a613c --- /dev/null +++ b/src/cohort/entities/state.entity.ts @@ -0,0 +1,16 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + } from "typeorm"; + + @Entity({ name: "states" }) + export class State { + @PrimaryGeneratedColumn('uuid') + value: string; + + @Column({ nullable: true }) + name: string; + + } + \ No newline at end of file diff --git a/src/fields/entities/fields.entity.ts b/src/fields/entities/fields.entity.ts index 13a2799f..172cb4b9 100644 --- a/src/fields/entities/fields.entity.ts +++ b/src/fields/entities/fields.entity.ts @@ -95,4 +95,7 @@ export class Fields { @Column({ type: 'jsonb' }) fieldParams: object; + + @Column({ type: 'jsonb',nullable: true }) + source_details: any; } diff --git a/src/user/dto/user-update.dto.ts b/src/user/dto/user-update.dto.ts index 55c24f59..fb1ba108 100644 --- a/src/user/dto/user-update.dto.ts +++ b/src/user/dto/user-update.dto.ts @@ -70,7 +70,6 @@ class CustomFieldDTO { @IsNotEmpty() fieldId: string; - @IsNotEmpty() @Expose() value: string | string[]; } From 40b499a1862881d245e5a57c4dcf962447924d5f Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 4 Jun 2024 18:01:26 +0530 Subject: [PATCH 393/408] Revert "Issue PS-770 Feat: Added Logic for fetching state Options ." This reverts commit d0ddc21dcf2949d9b2cb8fe5527997deab19264c. --- src/adapters/postgres/cohort-adapter.ts | 46 +++---------------------- src/cohort/cohort.module.ts | 3 +- src/cohort/entities/state.entity.ts | 16 --------- src/fields/entities/fields.entity.ts | 3 -- src/user/dto/user-update.dto.ts | 1 + 5 files changed, 6 insertions(+), 63 deletions(-) delete mode 100644 src/cohort/entities/state.entity.ts diff --git a/src/adapters/postgres/cohort-adapter.ts b/src/adapters/postgres/cohort-adapter.ts index b0d73155..434d1fb7 100644 --- a/src/adapters/postgres/cohort-adapter.ts +++ b/src/adapters/postgres/cohort-adapter.ts @@ -21,15 +21,12 @@ import { isUUID } from "class-validator"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; import APIResponse from "src/common/responses/response"; import { APIID } from "src/common/utils/api-id.config"; -import { State } from "src/cohort/entities/state.entity"; @Injectable() export class PostgresCohortService { constructor( - @InjectRepository(State) - private stateRepository: Repository, @InjectRepository(Cohort) private cohortRepository: Repository, @InjectRepository(CohortMembers) @@ -41,7 +38,6 @@ export class PostgresCohortService { @InjectRepository(UserTenantMapping) private UserTenantMappingRepository: Repository, private fieldsService: PostgresFieldsService, - ) { } public async getCohortList( @@ -97,6 +93,7 @@ export class PostgresCohortService { if (checkData === true) { const result = await this.getCohortDataWithCustomfield(cohortId); return APIResponse.success(res, apiId, result, (HttpStatus.OK), "Cohort details fetched succcessfully."); + } else { return APIResponse.error( res, @@ -138,48 +135,12 @@ export class PostgresCohortService { options: data?.fieldParams?.['options'] || {}, type: data.type || '' }; - customField["dependsOn"] = null; - if(data.source_details){ - // We need to add the dependence Condition here. - if(data?.source_details?.source === 'table' && data?.source_details.depends_on === "null"){ - let dynamicOptions = await this.findDynamicOptions(data?.source_details?.table); - customField.options = dynamicOptions - customField["dependsOn"] = null; - }else if(data?.source_details?.source === 'table' && data?.source_details.depends_on){ - customField.options = {}; - customField["dependsOn"] = data?.source_details.depends_on; - }else{ - customField["dependsOn"] = null; - customField.options = data.fieldParams; - } - } customFieldsArray.push(customField); } result.cohortData['customFields'] = customFieldsArray; return result } - async findDynamicOptions(tableName,whereClause?:{}){ - let query:string; - let result; - if(whereClause){ - query = `select * from public."${tableName} where=${whereClause}"` - result = await this.cohortRepository.query(query); - if(!result){ - return null; - } - return result; - } - query = `select * from public."${tableName}"` - result = await this.cohortRepository.query(query); - if(!result){ - return null; - } - return result.map(result => ({ - value: result.value, - label: result.name - })); - } async findFilledValues(cohortId: string) { let query = `SELECT C."cohortId",F."fieldId",F."value" FROM public."Cohort" C @@ -207,7 +168,6 @@ export class PostgresCohortService { return customFields; } - public async findCohortName(userId: any) { let query = `SELECT c."name",c."cohortId",c."parentId" FROM public."CohortMembers" AS cm @@ -242,7 +202,9 @@ export class PostgresCohortService { } return { valid: true, fieldId: "true" }; }; - + + + public async createCohort(request: any, cohortCreateDto: CohortCreateDto, res) { const apiId = APIID.COHORT_CREATE; diff --git a/src/cohort/cohort.module.ts b/src/cohort/cohort.module.ts index 5df09e1d..e8dddc71 100644 --- a/src/cohort/cohort.module.ts +++ b/src/cohort/cohort.module.ts @@ -12,11 +12,10 @@ import { CohortMembers } from "src/cohortMembers/entities/cohort-member.entity"; import { PostgresModule } from "src/adapters/postgres/potsgres-module"; import { PostgresCohortService } from "src/adapters/postgres/cohort-adapter"; import { UserTenantMapping } from "src/userTenantMapping/entities/user-tenant-mapping.entity"; -import { State } from "./entities/state.entity"; @Module({ imports: [ - TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers, UserTenantMapping,State]), + TypeOrmModule.forFeature([Cohort, FieldValues, Fields, CohortMembers, UserTenantMapping]), HttpModule, HasuraModule, PostgresModule diff --git a/src/cohort/entities/state.entity.ts b/src/cohort/entities/state.entity.ts deleted file mode 100644 index 324a613c..00000000 --- a/src/cohort/entities/state.entity.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - } from "typeorm"; - - @Entity({ name: "states" }) - export class State { - @PrimaryGeneratedColumn('uuid') - value: string; - - @Column({ nullable: true }) - name: string; - - } - \ No newline at end of file diff --git a/src/fields/entities/fields.entity.ts b/src/fields/entities/fields.entity.ts index 172cb4b9..13a2799f 100644 --- a/src/fields/entities/fields.entity.ts +++ b/src/fields/entities/fields.entity.ts @@ -95,7 +95,4 @@ export class Fields { @Column({ type: 'jsonb' }) fieldParams: object; - - @Column({ type: 'jsonb',nullable: true }) - source_details: any; } diff --git a/src/user/dto/user-update.dto.ts b/src/user/dto/user-update.dto.ts index fb1ba108..55c24f59 100644 --- a/src/user/dto/user-update.dto.ts +++ b/src/user/dto/user-update.dto.ts @@ -70,6 +70,7 @@ class CustomFieldDTO { @IsNotEmpty() fieldId: string; + @IsNotEmpty() @Expose() value: string | string[]; } From 2f70a66a3eada2720fb93f9e07647c401faf2093 Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 4 Jun 2024 18:06:18 +0530 Subject: [PATCH 394/408] Issue PS-766 fix: Added minor chaneg in update DTO. --- src/user/dto/user-update.dto.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/user/dto/user-update.dto.ts b/src/user/dto/user-update.dto.ts index 55c24f59..17742143 100644 --- a/src/user/dto/user-update.dto.ts +++ b/src/user/dto/user-update.dto.ts @@ -1,4 +1,4 @@ -import { IsString, IsOptional, IsArray, ValidateNested, IsNotEmpty, IsEnum } from 'class-validator'; +import { IsString, IsOptional, IsArray, ValidateNested, IsNotEmpty, IsEnum, ValidateIf } from 'class-validator'; import { Expose, Type } from 'class-transformer'; class UserDataDTO { @@ -70,6 +70,7 @@ class CustomFieldDTO { @IsNotEmpty() fieldId: string; + @ValidateIf(o => o.value !== '') @IsNotEmpty() @Expose() value: string | string[]; From b7247f8d9324bebdfa43aac61d9c580d079e3703 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:10:11 +0530 Subject: [PATCH 395/408] Update eks-pratham-deployment.yaml --- .github/workflows/eks-pratham-deployment.yaml | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index 11e58d33..0e8ae2a7 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -1,66 +1,75 @@ -name: Deploy to EKS-Pratham-Backend Service +name: Deploy to EKS-Pratham on: push: branches: - - Shiksha-2.0 + - main +# pull_request_target: +# types: [closed] +# branches: +# - main env: ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} AWS_REGION: ${{ secrets.AWS_REGION_NAME }} - jobs: - build: - name: Deployment runs-on: ubuntu-latest - steps: - name: Set short git commit SHA id: commit uses: prompt/actions-commit-hash@v2 - - name: Check out code uses: actions/checkout@v2 - - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{env.AWS_REGION}} - - name: Setup Node Env uses: actions/setup-node@v3 with: node-version: 21.1.0 - - name: Copy .env file env: ENV_FILE_CONTENT: ${{ secrets.ENV_FILE_CONTENT }} run: echo "$ENV_FILE_CONTENT" > .env - - name: Show PWD and list content run: | echo "Current Working Directory: pwd" pwd ls -ltra + - name: Creating Dockerfile + env: + DOCKERFILE_FILE_CONTENT: ${{ secrets.DOCKERFILE_FILE_CONTENT }} + run: echo "$DOCKERFILE_FILE_CONTENT" > Dockerfile + - name: Show PWD and list content + run: | + echo "Current Working Directory: pwd" + pwd + ls -ltra + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - - name: Build, tag, and push image to Amazon ECR + env: + ECR_REGISTRY: ${{ secrets.ECR_REPOSITORY }} + IMAGE_TAG: ${{ secrets.ECR_IMAGE }} run: | - aws ecr --region ${{ secrets.AWS_REGION_NAME }} | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} docker build -t ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} . docker push ${{ secrets.ECR_REPOSITORY }}:${{ secrets.IMAGE_TAG }} - - name: Update kube config run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION_NAME }} - - name: Deploy to EKS env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REGISTRY: ${{ secrets.ECR_REPOSITORY }} IMAGE_TAG: ${{ secrets.IMAGE_TAG }} ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} ECR_IMAGE: ${{ secrets.ECR_IMAGE }} @@ -69,5 +78,12 @@ jobs: export IMAGE_TAG=${{ secrets.IMAGE_TAG }} export ECR_IMAGE=${{ secrets.ECR_IMAGE }} envsubst < manifest/backend.yaml > manifest/backend-updated.yaml - cat manifest/backend-updated.yaml + cat manifest/backend-updated.yaml + rm -rf manifest/backend-service.yaml + kubectl delete deployment backend + kubectl delete service backend kubectl apply -f manifest/backend-updated.yaml + sleep 10 + kubectl get pods + kubectl get services + kubectl get deployment From 6e7696a6bf97fa569300b33a57f783c689c83d26 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:12:13 +0530 Subject: [PATCH 396/408] Update backend.yaml --- manifest/backend.yaml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/manifest/backend.yaml b/manifest/backend.yaml index 6b36c6ee..2c2cb36c 100644 --- a/manifest/backend.yaml +++ b/manifest/backend.yaml @@ -39,17 +39,14 @@ status: {} apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: /snap/kompose/19/kompose-linux-amd64 convert -f backend.yaml - kompose.version: 1.21.0 (992df58d8) - labels: - io.kompose.service: backend name: backend + labels: + app: backend spec: - type: NodePort + type: ClusterIP ports: - - port: 31265 - targetPort: 3000 - nodePort: 31265 + - name: http-backend + protocol: TCP + port: 3000 selector: - io.kompose.service: backend + app: backend From df13de7c18983c35becf1f2740982c96c98680e8 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:13:40 +0530 Subject: [PATCH 397/408] Update eks-pratham-deployment.yaml --- .github/workflows/eks-pratham-deployment.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index 0e8ae2a7..a34fd0ea 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -2,11 +2,7 @@ name: Deploy to EKS-Pratham on: push: branches: - - main -# pull_request_target: -# types: [closed] -# branches: -# - main + - Shiksha-2.0 env: ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} From c720e57cc3153b48176ddeb253e2c613d205b2e8 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:16:52 +0530 Subject: [PATCH 398/408] Update eks-pratham-deployment.yaml --- .github/workflows/eks-pratham-deployment.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index a34fd0ea..7ae70469 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -36,15 +36,6 @@ jobs: echo "Current Working Directory: pwd" pwd ls -ltra - - name: Creating Dockerfile - env: - DOCKERFILE_FILE_CONTENT: ${{ secrets.DOCKERFILE_FILE_CONTENT }} - run: echo "$DOCKERFILE_FILE_CONTENT" > Dockerfile - - name: Show PWD and list content - run: | - echo "Current Working Directory: pwd" - pwd - ls -ltra - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: From 2c317e367c215ce505aa51ecfcc4e6308906526e Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 5 Jun 2024 17:55:15 +0530 Subject: [PATCH 399/408] Cohort: Update Cohort Data --- src/adapters/postgres/user-adapter.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 9dd088ae..763505eb 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -402,9 +402,6 @@ export class PostgresUserService implements IServicelocator { if (Array.isArray(data.value) === true) { let dataArray = []; - for (let value of data.value) { - dataArray.push(value.toLowerCase().replace(/ /g, '_')); - } data.value = dataArray.join(','); } From f546fc83a51f4636ec750ca2279dd373b01be66c Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 5 Jun 2024 19:05:08 +0530 Subject: [PATCH 400/408] add --- src/adapters/postgres/user-adapter.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 763505eb..677f1f18 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -400,13 +400,19 @@ export class PostgresUserService implements IServicelocator { async updateCustomFields(itemId, data) { + console.log("hi"); + if (Array.isArray(data.value) === true) { + let dataArray = []; + for (let value of data.value) { + dataArray.push(value); + } data.value = dataArray.join(','); } - let result = await this.fieldsValueRepository.update({ itemId, fieldId: data.fieldId }, { value: data.value }); let newResult; + if (result.affected === 0) { newResult = await this.fieldsValueRepository.save({ itemId, From c1a4882bfd38708c262ebd0ffd32ce7288ce5143 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 5 Jun 2024 19:10:06 +0530 Subject: [PATCH 401/408] add --- src/adapters/postgres/user-adapter.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index 677f1f18..b23a3c13 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -400,10 +400,7 @@ export class PostgresUserService implements IServicelocator { async updateCustomFields(itemId, data) { - console.log("hi"); - if (Array.isArray(data.value) === true) { - let dataArray = []; for (let value of data.value) { dataArray.push(value); From ea3141b64e7a4be64d4e812372ad08bfee7ed52e Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:11:26 +0530 Subject: [PATCH 402/408] Update backend.yaml --- manifest/backend.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/manifest/backend.yaml b/manifest/backend.yaml index 2c2cb36c..5da64c65 100644 --- a/manifest/backend.yaml +++ b/manifest/backend.yaml @@ -29,6 +29,9 @@ spec: name: backend-pratham ports: - containerPort: 3000 + envFrom: + - configMapRef: + name: backend-service-config resources: {} restartPolicy: Always serviceAccountName: "" From eb6a0218705b8afff5795ff921432adc39c9b3a3 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:13:56 +0530 Subject: [PATCH 403/408] Update eks-pratham-deployment.yaml --- .github/workflows/eks-pratham-deployment.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index 7ae70469..3c8a688c 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -30,7 +30,7 @@ jobs: - name: Copy .env file env: ENV_FILE_CONTENT: ${{ secrets.ENV_FILE_CONTENT }} - run: echo "$ENV_FILE_CONTENT" > .env + run: echo "$ENV_FILE_CONTENT" > manifest/configmap.yaml - name: Show PWD and list content run: | echo "Current Working Directory: pwd" @@ -70,6 +70,7 @@ jobs: kubectl delete deployment backend kubectl delete service backend kubectl apply -f manifest/backend-updated.yaml + kubectl apply -f manifest/configmap.yaml sleep 10 kubectl get pods kubectl get services From c7766f20d0e4fcb85e76ac334edc1f6c7dd18ac8 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:17:50 +0530 Subject: [PATCH 404/408] Update eks-pratham-deployment.yaml --- .github/workflows/eks-pratham-deployment.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index 3c8a688c..89e6bc86 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -69,6 +69,7 @@ jobs: rm -rf manifest/backend-service.yaml kubectl delete deployment backend kubectl delete service backend + kubectl delete cm backend-service-config kubectl apply -f manifest/backend-updated.yaml kubectl apply -f manifest/configmap.yaml sleep 10 From d306789a537edab6279b699ec142e2dc0d40139f Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Tue, 11 Jun 2024 19:06:12 +0530 Subject: [PATCH 405/408] auto deploy test --- src/adapters/postgres/cohortMembers-adapter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/adapters/postgres/cohortMembers-adapter.ts b/src/adapters/postgres/cohortMembers-adapter.ts index e19af71a..c0b83828 100644 --- a/src/adapters/postgres/cohortMembers-adapter.ts +++ b/src/adapters/postgres/cohortMembers-adapter.ts @@ -35,6 +35,7 @@ export class PostgresCohortMembersService { private cohortRepository: Repository ) { } + //Get cohort member async getCohortMembers(cohortId: any, tenantId: any, fieldvalue: any, res: Response) { const apiId = APIID.COHORT_MEMBER_GET try { From 7c015f7ef4e670c60b791210af39ced07f52c844 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Tue, 11 Jun 2024 20:19:51 +0530 Subject: [PATCH 406/408] Update eks-pratham-deployment.yaml --- .github/workflows/eks-pratham-deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/eks-pratham-deployment.yaml b/.github/workflows/eks-pratham-deployment.yaml index 89e6bc86..ee3ba67a 100644 --- a/.github/workflows/eks-pratham-deployment.yaml +++ b/.github/workflows/eks-pratham-deployment.yaml @@ -2,7 +2,7 @@ name: Deploy to EKS-Pratham on: push: branches: - - Shiksha-2.0 + - june15-pilot env: ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} EKS_CLUSTER_NAME: ${{ secrets.EKS_CLUSTER_NAME }} From 32fc88abbb5ea7d59119d5bc214713171d316f81 Mon Sep 17 00:00:00 2001 From: souravbhowmik1999 Date: Wed, 12 Jun 2024 09:25:42 +0530 Subject: [PATCH 407/408] User Create: Email Field Optional for User Creation --- src/user/dto/user-create.dto.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/user/dto/user-create.dto.ts b/src/user/dto/user-create.dto.ts index b3d8eadd..aa6ffac0 100644 --- a/src/user/dto/user-create.dto.ts +++ b/src/user/dto/user-create.dto.ts @@ -1,4 +1,4 @@ -import {Expose, Type } from "class-transformer"; +import { Expose, Type } from "class-transformer"; import { MaxLength, IsNotEmpty, @@ -13,7 +13,7 @@ import { import { User } from "../entities/user-entity"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; -export class tenantRoleMappingDto{ +export class tenantRoleMappingDto { @ApiProperty({ type: String, description: "Tenant Id", @@ -42,7 +42,7 @@ export class tenantRoleMappingDto{ roleId: string; } -export class FieldValuesDto{ +export class FieldValuesDto { @ApiPropertyOptional({ type: String, description: "Field Id", @@ -91,8 +91,6 @@ export class UserCreateDto { description: "The email of the user", }) @Expose() - @IsEmail() - @IsNotEmpty() email: string; @ApiProperty({ From d705dbffc16a8049fce0a1a5130e576e842c6b92 Mon Sep 17 00:00:00 2001 From: AbhilashKD <124042593+AbhilashKD@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:33:03 +0530 Subject: [PATCH 408/408] Update backend.yaml --- manifest/backend.yaml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/manifest/backend.yaml b/manifest/backend.yaml index 5da64c65..a4119b8f 100644 --- a/manifest/backend.yaml +++ b/manifest/backend.yaml @@ -1,27 +1,21 @@ apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: /snap/kompose/19/kompose-linux-amd64 convert -f shiksha.yaml - kompose.version: 1.21.0 (992df58d8) creationTimestamp: null labels: - io.kompose.service: backend + app: backend name: backend spec: replicas: 1 selector: matchLabels: - io.kompose.service: backend + app: backend strategy: {} template: metadata: - annotations: - kompose.cmd: /snap/kompose/19/kompose-linux-amd64 convert -f shiksha.yaml - kompose.version: 1.21.0 (992df58d8) creationTimestamp: null labels: - io.kompose.service: backend + app: backend spec: containers: - image: ${ECR_REPOSITORY}:${IMAGE_TAG} @@ -34,8 +28,6 @@ spec: name: backend-service-config resources: {} restartPolicy: Always - serviceAccountName: "" - volumes: null status: {} --- @@ -43,13 +35,10 @@ apiVersion: v1 kind: Service metadata: name: backend - labels: - app: backend spec: type: ClusterIP ports: - - name: http-backend + - port: 3000 protocol: TCP - port: 3000 selector: app: backend