From b5df14fe48c4d04ea4314a873137c6a06d1c8337 Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Tue, 13 Feb 2024 15:12:26 -0500
Subject: [PATCH 01/17] fix: collection update api[]
---
src/modules/workspace/payloads/collection.payload.ts | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/modules/workspace/payloads/collection.payload.ts b/src/modules/workspace/payloads/collection.payload.ts
index 3b53b218..c49f7361 100644
--- a/src/modules/workspace/payloads/collection.payload.ts
+++ b/src/modules/workspace/payloads/collection.payload.ts
@@ -93,8 +93,13 @@ export class CreateCollectionDto {
export class UpdateCollectionDto {
@ApiProperty({ example: "Swagger Petstore - OpenAPI 3.0" })
@IsString()
- @IsNotEmpty()
- name: string;
+ @IsOptional()
+ name?: string;
+
+ @ApiProperty({ example: "Its a mock description" })
+ @IsString()
+ @IsOptional()
+ description?: string;
@ApiProperty({ type: [CollectionItem] })
@IsArray()
From 4bd27e53feb323738289dad053829f419de5d5b9 Mon Sep 17 00:00:00 2001
From: Astitva877
Date: Fri, 23 Feb 2024 17:40:24 +0530
Subject: [PATCH 02/17] fix: Added SMTP mail services []
---
.env.example | 4 ++++
src/modules/common/config/configuration.ts | 4 ++++
src/modules/common/config/env.validation.ts | 13 +++++++++++++
.../identity/services/team-user.service.ts | 8 +++++---
src/modules/identity/services/user.service.ts | 19 +++++++++++--------
.../workspace/services/workspace.service.ts | 8 +++++---
6 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/.env.example b/.env.example
index e4a67b87..a31db450 100755
--- a/.env.example
+++ b/.env.example
@@ -26,6 +26,10 @@ KAFKA_BROKER=localhost:9092
#EMAIL
SENDER_EMAIL=
SENDER_PASSWORD=
+MAIL_HOST=
+MAIL_PORT=
+MAIL_SECURE=
+USER_NAME=
# REFRESH TOKEN
REFRESH_TOKEN_SECRET_KEY=refresh-token-secret
diff --git a/src/modules/common/config/configuration.ts b/src/modules/common/config/configuration.ts
index cc0b1052..86ede8c6 100644
--- a/src/modules/common/config/configuration.ts
+++ b/src/modules/common/config/configuration.ts
@@ -21,6 +21,10 @@ export default () => ({
refreshTokenMaxLimit: parseInt(process.env.REFRESH_TOKEN_MAX_LIMIT),
senderEmail: process.env.SENDER_EMAIL,
senderPassword: process.env.SENDER_PASSWORD,
+ mailHost: process.env.MAIL_HOST,
+ mailPort: process.env.MAIL_PORT,
+ mailSecure: process.env.MAIL_SECURE,
+ userName: process.env.USER_NAME,
},
db: {
url: process.env.DB_URL,
diff --git a/src/modules/common/config/env.validation.ts b/src/modules/common/config/env.validation.ts
index 52344042..3ee6942c 100644
--- a/src/modules/common/config/env.validation.ts
+++ b/src/modules/common/config/env.validation.ts
@@ -67,6 +67,19 @@ export class EnvironmentVariables {
@IsString()
SENDER_PASSWORD: string;
+ @Type(() => Number)
+ @IsNumber()
+ MAIL_PORT: number;
+
+ @IsString()
+ MAIL_HOST: string;
+
+ @IsString()
+ MAIL_SECURE: string;
+
+ @IsString()
+ USER_NAME: string;
+
@Type(() => Number)
@IsNumber()
EMAIL_VALIDATION_CODE_EXPIRY_TIME: number;
diff --git a/src/modules/identity/services/team-user.service.ts b/src/modules/identity/services/team-user.service.ts
index b5521380..c079ad36 100644
--- a/src/modules/identity/services/team-user.service.ts
+++ b/src/modules/identity/services/team-user.service.ts
@@ -15,7 +15,6 @@ import { TeamRole } from "@src/modules/common/enum/roles.enum";
import { TeamService } from "./team.service";
import * as nodemailer from "nodemailer";
import hbs = require("nodemailer-express-handlebars");
-import { EmailServiceProvider } from "@src/modules/common/models/user.model";
import { ConfigService } from "@nestjs/config";
import path = require("path");
/**
@@ -71,11 +70,14 @@ export class TeamUserService {
async inviteUserInTeamEmail(payload: TeamInviteMailDto) {
const currentUser = await this.contextService.get("user");
const transporter = nodemailer.createTransport({
- service: EmailServiceProvider.GMAIL,
+ host: this.configService.get("app.mailHost"),
+ port: this.configService.get("app.mailPort"),
+ secure: this.configService.get("app.mailSecure") === "true",
auth: {
- user: this.configService.get("app.senderEmail"),
+ user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
+ sender: this.configService.get("app.senderEmail"),
});
const handlebarOptions = {
//view engine contains default and partial templates
diff --git a/src/modules/identity/services/user.service.ts b/src/modules/identity/services/user.service.ts
index 26e4b045..b0ca3580 100644
--- a/src/modules/identity/services/user.service.ts
+++ b/src/modules/identity/services/user.service.ts
@@ -8,10 +8,7 @@ import { UserRepository } from "../repositories/user.repository";
import { RegisterPayload } from "../payloads/register.payload";
import { ConfigService } from "@nestjs/config";
import { AuthService } from "./auth.service";
-import {
- EmailServiceProvider,
- User,
-} from "@src/modules/common/models/user.model";
+import { User } from "@src/modules/common/models/user.model";
import {
EarlyAccessPayload,
ResetPasswordPayload,
@@ -135,11 +132,14 @@ export class UserService {
throw new UnauthorizedException(ErrorMessages.BadRequestError);
}
const transporter = nodemailer.createTransport({
- service: EmailServiceProvider.GMAIL,
+ host: this.configService.get("app.mailHost"),
+ port: this.configService.get("app.mailPort"),
+ secure: this.configService.get("app.mailSecure") === "true",
auth: {
- user: this.configService.get("app.senderEmail"),
+ user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
+ sender: this.configService.get("app.senderEmail"),
});
const verificationCode = this.generateEmailVerificationCode().toUpperCase();
const handlebarOptions = {
@@ -173,11 +173,14 @@ export class UserService {
async sendWelcomeEmail(earlyAccessDto: EarlyAccessPayload): Promise {
const transporter = nodemailer.createTransport({
- service: EmailServiceProvider.GMAIL,
+ host: this.configService.get("app.mailHost"),
+ port: this.configService.get("app.mailPort"),
+ secure: this.configService.get("app.mailSecure") === "true",
auth: {
- user: this.configService.get("app.senderEmail"),
+ user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
+ sender: this.configService.get("app.senderEmail"),
});
const handlebarOptions = {
viewEngine: {
diff --git a/src/modules/workspace/services/workspace.service.ts b/src/modules/workspace/services/workspace.service.ts
index a54faa65..8cdf533c 100644
--- a/src/modules/workspace/services/workspace.service.ts
+++ b/src/modules/workspace/services/workspace.service.ts
@@ -42,7 +42,6 @@ import { User } from "@src/modules/common/models/user.model";
import { isString } from "class-validator";
import * as nodemailer from "nodemailer";
import hbs = require("nodemailer-express-handlebars");
-import { EmailServiceProvider } from "@src/modules/common/models/user.model";
import { ConfigService } from "@nestjs/config";
import path = require("path");
/**
@@ -513,11 +512,14 @@ export class WorkspaceService {
async inviteUserInWorkspaceEmail(payload: WorkspaceInviteMailDto) {
const currentUser = await this.contextService.get("user");
const transporter = nodemailer.createTransport({
- service: EmailServiceProvider.GMAIL,
+ host: this.configService.get("app.mailHost"),
+ port: this.configService.get("app.mailPort"),
+ secure: this.configService.get("app.mailSecure") === "true",
auth: {
- user: this.configService.get("app.senderEmail"),
+ user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
+ sender: this.configService.get("app.senderEmail"),
});
const handlebarOptions = {
//view engine contains default and partial templates
From 97939e7cc3f8110be3e6718cfc25d2b806b53d7a Mon Sep 17 00:00:00 2001
From: Astitva877
Date: Fri, 23 Feb 2024 17:58:13 +0530
Subject: [PATCH 03/17] fix: Added env keys in yml []
---
deploymentManifests/deployment.yml | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/deploymentManifests/deployment.yml b/deploymentManifests/deployment.yml
index 40ed1d00..14b1dc2b 100644
--- a/deploymentManifests/deployment.yml
+++ b/deploymentManifests/deployment.yml
@@ -89,6 +89,26 @@ spec:
secretKeyRef:
name: sparrow-api-secret
key: SENDER_PASSWORD
+ - name: MAIL_HOST
+ valueFrom:
+ secretKeyRef:
+ name: sparrow-api-secret
+ key: MAIL_HOST
+ - name: MAIL_PORT
+ valueFrom:
+ secretKeyRef:
+ name: sparrow-api-secret
+ key: MAIL_PORT
+ - name: MAIL_SECURE
+ valueFrom:
+ secretKeyRef:
+ name: sparrow-api-secret
+ key: MAIL_SECURE
+ - name: USER_NAME
+ valueFrom:
+ secretKeyRef:
+ name: sparrow-api-secret
+ key: USER_NAME
- name: LOGIN_REDIRECT_URL
valueFrom:
secretKeyRef:
From 18ce73be2afeb705ec2b4e8ff9379edcd0e3942a Mon Sep 17 00:00:00 2001
From: Astitva877
Date: Fri, 23 Feb 2024 18:31:01 +0530
Subject: [PATCH 04/17] fix: Remove sender from mail in transport []
---
src/modules/identity/services/team-user.service.ts | 1 -
src/modules/identity/services/user.service.ts | 2 --
src/modules/workspace/services/workspace.service.ts | 1 -
3 files changed, 4 deletions(-)
diff --git a/src/modules/identity/services/team-user.service.ts b/src/modules/identity/services/team-user.service.ts
index c079ad36..ae7ee63f 100644
--- a/src/modules/identity/services/team-user.service.ts
+++ b/src/modules/identity/services/team-user.service.ts
@@ -77,7 +77,6 @@ export class TeamUserService {
user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
- sender: this.configService.get("app.senderEmail"),
});
const handlebarOptions = {
//view engine contains default and partial templates
diff --git a/src/modules/identity/services/user.service.ts b/src/modules/identity/services/user.service.ts
index b0ca3580..28632e68 100644
--- a/src/modules/identity/services/user.service.ts
+++ b/src/modules/identity/services/user.service.ts
@@ -139,7 +139,6 @@ export class UserService {
user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
- sender: this.configService.get("app.senderEmail"),
});
const verificationCode = this.generateEmailVerificationCode().toUpperCase();
const handlebarOptions = {
@@ -180,7 +179,6 @@ export class UserService {
user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
- sender: this.configService.get("app.senderEmail"),
});
const handlebarOptions = {
viewEngine: {
diff --git a/src/modules/workspace/services/workspace.service.ts b/src/modules/workspace/services/workspace.service.ts
index 8cdf533c..3ce8d792 100644
--- a/src/modules/workspace/services/workspace.service.ts
+++ b/src/modules/workspace/services/workspace.service.ts
@@ -519,7 +519,6 @@ export class WorkspaceService {
user: this.configService.get("app.userName"),
pass: this.configService.get("app.senderPassword"),
},
- sender: this.configService.get("app.senderEmail"),
});
const handlebarOptions = {
//view engine contains default and partial templates
From 27ebd8b32acbc16ae5afe85a7029c37ad16fc2b4 Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Fri, 23 Feb 2024 19:38:14 +0530
Subject: [PATCH 05/17] chore: change env variable name[]
---
.env.example | 12 +++++------
deploymentManifests/deployment.yml | 24 ++++++++++-----------
src/modules/common/config/configuration.ts | 12 +++++------
src/modules/common/config/env.validation.ts | 12 +++++------
4 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/.env.example b/.env.example
index a31db450..3a20286f 100755
--- a/.env.example
+++ b/.env.example
@@ -24,12 +24,12 @@ EMAIL_VALIDATION_CODE_EXPIRY_TIME=
KAFKA_BROKER=localhost:9092
#EMAIL
-SENDER_EMAIL=
-SENDER_PASSWORD=
-MAIL_HOST=
-MAIL_PORT=
-MAIL_SECURE=
-USER_NAME=
+SMTP_SENDER_EMAIL=
+SMTP_SENDER_PASSWORD=
+SMTP_MAIL_HOST=
+SMTP_MAIL_PORT=
+SMTP_MAIL_SECURE=
+SMTP_USER_NAME=
# REFRESH TOKEN
REFRESH_TOKEN_SECRET_KEY=refresh-token-secret
diff --git a/deploymentManifests/deployment.yml b/deploymentManifests/deployment.yml
index 14b1dc2b..86d1350c 100644
--- a/deploymentManifests/deployment.yml
+++ b/deploymentManifests/deployment.yml
@@ -79,36 +79,36 @@ spec:
secretKeyRef:
name: sparrow-api-secret
key: REFRESH_TOKEN_MAX_LIMIT
- - name: SENDER_EMAIL
+ - name: SMTP_SENDER_EMAIL
valueFrom:
secretKeyRef:
name: sparrow-api-secret
- key: SENDER_EMAIL
- - name: SENDER_PASSWORD
+ key: SMTP_SENDER_EMAIL
+ - name: SMTP_SENDER_PASSWORD
valueFrom:
secretKeyRef:
name: sparrow-api-secret
- key: SENDER_PASSWORD
- - name: MAIL_HOST
+ key: SMTP_SENDER_PASSWORD
+ - name: SMTP_MAIL_HOST
valueFrom:
secretKeyRef:
name: sparrow-api-secret
- key: MAIL_HOST
- - name: MAIL_PORT
+ key: SMTP_MAIL_HOST
+ - name: SMTP_MAIL_PORT
valueFrom:
secretKeyRef:
name: sparrow-api-secret
- key: MAIL_PORT
- - name: MAIL_SECURE
+ key: SMTP_MAIL_PORT
+ - name: SMTP_MAIL_SECURE
valueFrom:
secretKeyRef:
name: sparrow-api-secret
- key: MAIL_SECURE
- - name: USER_NAME
+ key: SMTP_MAIL_SECURE
+ - name: SMTP_USER_NAME
valueFrom:
secretKeyRef:
name: sparrow-api-secret
- key: USER_NAME
+ key: SMTP_USER_NAME
- name: LOGIN_REDIRECT_URL
valueFrom:
secretKeyRef:
diff --git a/src/modules/common/config/configuration.ts b/src/modules/common/config/configuration.ts
index 86ede8c6..72a46935 100644
--- a/src/modules/common/config/configuration.ts
+++ b/src/modules/common/config/configuration.ts
@@ -19,12 +19,12 @@ export default () => ({
process.env.REFRESH_TOKEN_EXPIRATION_TIME,
),
refreshTokenMaxLimit: parseInt(process.env.REFRESH_TOKEN_MAX_LIMIT),
- senderEmail: process.env.SENDER_EMAIL,
- senderPassword: process.env.SENDER_PASSWORD,
- mailHost: process.env.MAIL_HOST,
- mailPort: process.env.MAIL_PORT,
- mailSecure: process.env.MAIL_SECURE,
- userName: process.env.USER_NAME,
+ senderEmail: process.env.SMTP_SENDER_EMAIL,
+ senderPassword: process.env.SMTP_SENDER_PASSWORD,
+ mailHost: process.env.SMTP_MAIL_HOST,
+ mailPort: process.env.SMTP_MAIL_PORT,
+ mailSecure: process.env.SMTP_MAIL_SECURE,
+ userName: process.env.SMTP_USER_NAME,
},
db: {
url: process.env.DB_URL,
diff --git a/src/modules/common/config/env.validation.ts b/src/modules/common/config/env.validation.ts
index 3ee6942c..71402dd2 100644
--- a/src/modules/common/config/env.validation.ts
+++ b/src/modules/common/config/env.validation.ts
@@ -62,23 +62,23 @@ export class EnvironmentVariables {
REFRESH_TOKEN_MAX_LIMIT: number;
@IsString()
- SENDER_EMAIL: string;
+ SMTP_SENDER_EMAIL: string;
@IsString()
- SENDER_PASSWORD: string;
+ SMTP_SENDER_PASSWORD: string;
@Type(() => Number)
@IsNumber()
- MAIL_PORT: number;
+ SMTP_MAIL_PORT: number;
@IsString()
- MAIL_HOST: string;
+ SMTP_MAIL_HOST: string;
@IsString()
- MAIL_SECURE: string;
+ SMTP_MAIL_SECURE: string;
@IsString()
- USER_NAME: string;
+ SMTP_USER_NAME: string;
@Type(() => Number)
@IsNumber()
From 7af291e853c6866a241f4a5d3e513ab2cda411d9 Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Fri, 23 Feb 2024 19:45:57 +0530
Subject: [PATCH 06/17] fix: swagger url parsing[]
---
src/modules/common/services/parser.service.ts | 17 +++++++++++++----
.../controllers/workspace.controller.ts | 5 +++--
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/modules/common/services/parser.service.ts b/src/modules/common/services/parser.service.ts
index 43f85962..e5b12b81 100644
--- a/src/modules/common/services/parser.service.ts
+++ b/src/modules/common/services/parser.service.ts
@@ -24,7 +24,7 @@ export class ParserService {
private readonly collectionService: CollectionService,
) {}
async parse(file: string): Promise> {
- const openApiDocument = (await SwaggerParser.validate(file)) as OpenAPI303;
+ const openApiDocument = (await SwaggerParser.parse(file)) as OpenAPI303;
const baseUrl = this.getBaseUrl(openApiDocument);
const folderObjMap = new Map();
@@ -38,8 +38,8 @@ export class ParserService {
requestObj.type = ItemTypeEnum.REQUEST;
requestObj.source = SourceTypeEnum.SPEC;
requestObj.id = uuidv4();
- (requestObj.isDeleted = false),
- (requestObj.request = {} as RequestMetaData);
+ requestObj.isDeleted = false;
+ requestObj.request = {} as RequestMetaData;
requestObj.request.method = innerKey.toUpperCase() as HTTPMethods;
requestObj.request.operationId = innerValue.operationId;
requestObj.request.url = baseUrl + key;
@@ -63,7 +63,16 @@ export class ParserService {
body.type = Object.values(BodyModeEnum).find(
(enumMember) => enumMember === type,
) as BodyModeEnum;
- body.schema = (schema as any).schema;
+ const ref = (schema as any).schema?.$ref;
+ if (ref) {
+ const schemaName = ref.slice(
+ ref.lastIndexOf("/") + 1,
+ ref.length,
+ );
+ body.schema = openApiDocument.components.schemas[schemaName];
+ } else {
+ body.schema = (schema as any).schema;
+ }
requestObj.request.body.push(body);
}
}
diff --git a/src/modules/workspace/controllers/workspace.controller.ts b/src/modules/workspace/controllers/workspace.controller.ts
index c275df81..19ffce03 100644
--- a/src/modules/workspace/controllers/workspace.controller.ts
+++ b/src/modules/workspace/controllers/workspace.controller.ts
@@ -360,8 +360,9 @@ export class WorkSpaceController {
const response = await axios.get(importCollectionDto.url);
const data = response.data;
const responseType = response.headers["content-type"];
- const dataObj =
- responseType === BodyModeEnum["application/json"] ? data : yml.load(data);
+ const dataObj = responseType.includes(BodyModeEnum["application/json"])
+ ? data
+ : yml.load(data);
const collectionObj = await this.parserService.parse(dataObj);
await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
From 483a17e0373cb4fce50d9048518e5c22b0b154de Mon Sep 17 00:00:00 2001
From: Astitva877
Date: Sat, 24 Feb 2024 20:14:28 +0530
Subject: [PATCH 07/17] feat: Added Feature APIs []
---
.../common/enum/database.collection.enum.ts | 1 +
src/modules/common/models/feature.model.ts | 33 +++++
.../controllers/feature.controller.ts | 115 ++++++++++++++++++
.../workspace/payloads/feature.payload.ts | 16 +++
.../repositories/feature.repository.ts | 60 +++++++++
.../workspace/services/feature.service.ts | 66 ++++++++++
src/modules/workspace/workspace.module.ts | 8 ++
7 files changed, 299 insertions(+)
create mode 100644 src/modules/common/models/feature.model.ts
create mode 100644 src/modules/workspace/controllers/feature.controller.ts
create mode 100644 src/modules/workspace/payloads/feature.payload.ts
create mode 100644 src/modules/workspace/repositories/feature.repository.ts
create mode 100644 src/modules/workspace/services/feature.service.ts
diff --git a/src/modules/common/enum/database.collection.enum.ts b/src/modules/common/enum/database.collection.enum.ts
index 6823076a..0cd49f88 100644
--- a/src/modules/common/enum/database.collection.enum.ts
+++ b/src/modules/common/enum/database.collection.enum.ts
@@ -5,4 +5,5 @@ export enum Collections {
COLLECTION = "collection",
EARLYACCESS = "earlyaccess",
ENVIRONMENT = "environment",
+ FEATURES = "features",
}
diff --git a/src/modules/common/models/feature.model.ts b/src/modules/common/models/feature.model.ts
new file mode 100644
index 00000000..65d3336c
--- /dev/null
+++ b/src/modules/common/models/feature.model.ts
@@ -0,0 +1,33 @@
+import {
+ IsBoolean,
+ IsDate,
+ IsNotEmpty,
+ IsOptional,
+ IsString,
+} from "class-validator";
+
+export class Feature {
+ @IsString()
+ @IsNotEmpty()
+ name: string;
+
+ @IsBoolean()
+ @IsNotEmpty()
+ isEnabled: boolean;
+
+ @IsDate()
+ @IsOptional()
+ createdAt?: Date;
+
+ @IsDate()
+ @IsOptional()
+ updatedAt?: Date;
+
+ @IsString()
+ @IsOptional()
+ createdBy?: string;
+
+ @IsString()
+ @IsOptional()
+ updatedBy?: string;
+}
diff --git a/src/modules/workspace/controllers/feature.controller.ts b/src/modules/workspace/controllers/feature.controller.ts
new file mode 100644
index 00000000..74db9485
--- /dev/null
+++ b/src/modules/workspace/controllers/feature.controller.ts
@@ -0,0 +1,115 @@
+import {
+ ApiBearerAuth,
+ ApiOperation,
+ ApiResponse,
+ ApiTags,
+} from "@nestjs/swagger";
+import {
+ Body,
+ Controller,
+ Delete,
+ Get,
+ Param,
+ Post,
+ Put,
+ Res,
+ UseGuards,
+} from "@nestjs/common";
+import { AddFeatureDto, UpdateFeatureDto } from "../payloads/feature.payload";
+import { FastifyReply } from "fastify";
+import { FeatureService } from "../services/feature.service";
+import { ApiResponseService } from "@src/modules/common/services/api-response.service";
+import { HttpStatusCode } from "@src/modules/common/enum/httpStatusCode.enum";
+import { JwtAuthGuard } from "@src/modules/common/guards/jwt-auth.guard";
+/**
+ * Feature Controller
+ */
+@ApiBearerAuth()
+@ApiTags("feature")
+@Controller("api/feature")
+@UseGuards(JwtAuthGuard)
+export class FeatureController {
+ constructor(private readonly featureService: FeatureService) {}
+
+ @Post()
+ @ApiOperation({
+ summary: "Add a User",
+ description: "You can add a feature",
+ })
+ @ApiResponse({ status: 201, description: "Feature Added" })
+ @ApiResponse({ status: 400, description: "Failed to add feature" })
+ async addFeature(
+ @Body() addFeatureDto: AddFeatureDto,
+ @Res() res: FastifyReply,
+ ) {
+ await this.featureService.addFeature(addFeatureDto);
+ const feature = await this.featureService.getFeature(addFeatureDto.name);
+ const responseData = new ApiResponseService(
+ "Feature Added",
+ HttpStatusCode.CREATED,
+ feature,
+ );
+ return res.status(responseData.httpStatusCode).send(responseData);
+ }
+
+ @Get(":name")
+ @ApiOperation({
+ summary: "Get a Feature",
+ description: "This will retrieve a feature ",
+ })
+ @ApiResponse({
+ status: 200,
+ description: "Feature Received Successfullt",
+ })
+ @ApiResponse({ status: 400, description: "Failed to fetch Feature" })
+ async getFeature(@Param("name") name: string, @Res() res: FastifyReply) {
+ const feature = await this.featureService.getFeature(name);
+ const responseData = new ApiResponseService(
+ "Success",
+ HttpStatusCode.OK,
+ feature,
+ );
+ return res.status(responseData.httpStatusCode).send(responseData);
+ }
+
+ @Put(":name")
+ @ApiOperation({
+ summary: "Update a Feature",
+ description: "This will update a feature",
+ })
+ @ApiResponse({ status: 200, description: "Feature Updated Successfully" })
+ @ApiResponse({ status: 400, description: "Update Feature Failed" })
+ async updateFeature(
+ @Param("name") name: string,
+ @Body() updateFeatureDto: UpdateFeatureDto,
+ @Res() res: FastifyReply,
+ ) {
+ await this.featureService.updateFeature(name, updateFeatureDto);
+
+ const feature = await this.featureService.getFeature(name);
+ const responseData = new ApiResponseService(
+ "Success",
+ HttpStatusCode.OK,
+ feature,
+ );
+ return res.status(responseData.httpStatusCode).send(responseData);
+ }
+
+ @Delete(":name")
+ @ApiOperation({
+ summary: "Delete a Feature",
+ description: "This will delete a feature",
+ })
+ @ApiResponse({ status: 201, description: "Removed Feature Successfully" })
+ @ApiResponse({ status: 400, description: "Failed to remove Feature" })
+ async deleteFeature(@Param("name") name: string, @Res() res: FastifyReply) {
+ const feature = await this.featureService.deleteFeature(name);
+
+ const responseData = new ApiResponseService(
+ "Feature Removed",
+ HttpStatusCode.OK,
+ feature,
+ );
+ return res.status(responseData.httpStatusCode).send(responseData);
+ }
+}
diff --git a/src/modules/workspace/payloads/feature.payload.ts b/src/modules/workspace/payloads/feature.payload.ts
new file mode 100644
index 00000000..62b1a25b
--- /dev/null
+++ b/src/modules/workspace/payloads/feature.payload.ts
@@ -0,0 +1,16 @@
+import { IsString, IsNotEmpty, IsBoolean } from "class-validator";
+import { ApiProperty } from "@nestjs/swagger";
+
+export class AddFeatureDto {
+ @IsString()
+ @ApiProperty({ required: true, example: "Feature name" })
+ @IsNotEmpty()
+ name: string;
+}
+
+export class UpdateFeatureDto {
+ @IsBoolean()
+ @ApiProperty({ required: true, example: true })
+ @IsNotEmpty()
+ isEnabled: boolean;
+}
diff --git a/src/modules/workspace/repositories/feature.repository.ts b/src/modules/workspace/repositories/feature.repository.ts
new file mode 100644
index 00000000..5db8a324
--- /dev/null
+++ b/src/modules/workspace/repositories/feature.repository.ts
@@ -0,0 +1,60 @@
+import { Inject, Injectable } from "@nestjs/common";
+
+import {
+ Db,
+ DeleteResult,
+ InsertOneResult,
+ UpdateResult,
+ WithId,
+} from "mongodb";
+
+import { Collections } from "@src/modules/common/enum/database.collection.enum";
+import { ContextService } from "@src/modules/common/services/context.service";
+import { Feature } from "@src/modules/common/models/feature.model";
+import { UpdateFeatureDto } from "../payloads/feature.payload";
+
+@Injectable()
+export class FeatureRepository {
+ constructor(
+ @Inject("DATABASE_CONNECTION") private db: Db,
+ private readonly contextService: ContextService,
+ ) {}
+
+ async addFeature(feature: Feature): Promise> {
+ const response = await this.db
+ .collection(Collections.FEATURES)
+ .insertOne(feature);
+ return response;
+ }
+
+ async getFeatureByName(name: string): Promise> {
+ const data = await this.db
+ .collection(Collections.FEATURES)
+ .findOne({ name });
+ return data;
+ }
+
+ async deleteFeature(name: string): Promise {
+ const data = await this.db
+ .collection(Collections.FEATURES)
+ .deleteOne({ name });
+ return data;
+ }
+
+ async updateFeature(
+ name: string,
+ updateFeatureDto: UpdateFeatureDto,
+ ): Promise {
+ const defaultParams = {
+ updatedAt: new Date(),
+ updatedBy: this.contextService.get("user")._id,
+ };
+ const data = await this.db
+ .collection(Collections.FEATURES)
+ .updateOne(
+ { name: name },
+ { $set: { ...updateFeatureDto, ...defaultParams } },
+ );
+ return data;
+ }
+}
diff --git a/src/modules/workspace/services/feature.service.ts b/src/modules/workspace/services/feature.service.ts
new file mode 100644
index 00000000..4a73fa96
--- /dev/null
+++ b/src/modules/workspace/services/feature.service.ts
@@ -0,0 +1,66 @@
+import { BadRequestException, Injectable } from "@nestjs/common";
+import { DeleteResult, InsertOneResult, UpdateResult, WithId } from "mongodb";
+import { ContextService } from "@src/modules/common/services/context.service";
+import { AddFeatureDto, UpdateFeatureDto } from "../payloads/feature.payload";
+import { Feature } from "@src/modules/common/models/feature.model";
+import { FeatureRepository } from "../repositories/feature.repository";
+
+/**
+ * Feature Service
+ */
+
+@Injectable()
+export class FeatureService {
+ constructor(
+ private readonly contextService: ContextService,
+ private readonly featureRepository: FeatureRepository,
+ ) {}
+
+ async addFeature(
+ addFeatureDto: AddFeatureDto,
+ ): Promise> {
+ const user = this.contextService.get("user");
+ const featureData = await this.featureRepository.getFeatureByName(
+ addFeatureDto.name,
+ );
+ if (featureData) {
+ throw new BadRequestException(
+ "Feature with this name already exists. Please choose another one.",
+ );
+ }
+ const newFeature: Feature = {
+ name: addFeatureDto.name,
+ isEnabled: false,
+ createdBy: user._id,
+ updatedBy: user._id,
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ };
+ const feature = await this.featureRepository.addFeature(newFeature);
+ return feature;
+ }
+
+ async getFeature(name: string): Promise> {
+ const data = await this.featureRepository.getFeatureByName(name);
+ if (!data) {
+ throw new BadRequestException("Feature not found");
+ }
+ return data;
+ }
+
+ async deleteFeature(name: string): Promise {
+ const data = await this.featureRepository.deleteFeature(name);
+ return data;
+ }
+
+ async updateFeature(
+ name: string,
+ updateFeatureDto: UpdateFeatureDto,
+ ): Promise {
+ const data = await this.featureRepository.updateFeature(
+ name,
+ updateFeatureDto,
+ );
+ return data;
+ }
+}
diff --git a/src/modules/workspace/workspace.module.ts b/src/modules/workspace/workspace.module.ts
index a7af797f..5c9bf4ed 100644
--- a/src/modules/workspace/workspace.module.ts
+++ b/src/modules/workspace/workspace.module.ts
@@ -16,6 +16,9 @@ import { EnvironmentRepository } from "./repositories/environment.repository";
import { EnvironmentController } from "./controllers/environment.controller";
import { PromoteAdminHandler } from "./handlers/promoteAdmin.handlers";
import { DemoteAdminHandler } from "./handlers/demoteAdmin.handlers";
+import { FeatureController } from "./controllers/feature.controller";
+import { FeatureService } from "./services/feature.service";
+import { FeatureRepository } from "./repositories/feature.repository";
@Module({
imports: [IdentityModule],
providers: [
@@ -32,6 +35,8 @@ import { DemoteAdminHandler } from "./handlers/demoteAdmin.handlers";
CollectionRequestService,
EnvironmentService,
EnvironmentRepository,
+ FeatureService,
+ FeatureRepository,
],
exports: [
CollectionService,
@@ -39,11 +44,14 @@ import { DemoteAdminHandler } from "./handlers/demoteAdmin.handlers";
WorkspaceRepository,
EnvironmentService,
EnvironmentRepository,
+ FeatureService,
+ FeatureRepository,
],
controllers: [
WorkSpaceController,
collectionController,
EnvironmentController,
+ FeatureController,
],
})
export class WorkspaceModule {}
From a7dbc32671d762e1aaaa15a8507fa955f131dee9 Mon Sep 17 00:00:00 2001
From: Md Asif Raza
Date: Sat, 24 Feb 2024 22:39:45 +0530
Subject: [PATCH 08/17] feat: implement registered user status api [11]
Signed-off-by: Md Asif Raza
---
.../identity/controllers/user.controller.ts | 18 +++++++++++++
src/modules/identity/payloads/user.payload.ts | 5 ++++
src/modules/identity/services/user.service.ts | 26 ++++++++++++++++++-
3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/src/modules/identity/controllers/user.controller.ts b/src/modules/identity/controllers/user.controller.ts
index 0c4e86cd..e4866b7b 100644
--- a/src/modules/identity/controllers/user.controller.ts
+++ b/src/modules/identity/controllers/user.controller.ts
@@ -74,6 +74,24 @@ export class UserController {
return res.status(responseData.httpStatusCode).send(responseData);
}
+ @Get("email/:email")
+ @ApiOperation({
+ summary: "Retrieve User registration process",
+ description: "This will return registration status of a specific user",
+ })
+ async getUserByEmail(
+ @Param("email") email: string,
+ @Res() res: FastifyReply,
+ ) {
+ const data = await this.userService.getUserRegisterStatus(email);
+ const responseData = new ApiResponseService(
+ "Success",
+ HttpStatusCode.OK,
+ data,
+ );
+ return res.status(responseData.httpStatusCode).send(responseData);
+ }
+
@Put(":userId")
@ApiOperation({
summary: "Update a User",
diff --git a/src/modules/identity/payloads/user.payload.ts b/src/modules/identity/payloads/user.payload.ts
index 4d63cca2..6e623817 100644
--- a/src/modules/identity/payloads/user.payload.ts
+++ b/src/modules/identity/payloads/user.payload.ts
@@ -46,3 +46,8 @@ export class UserDto {
@ValidateNested({ each: true })
workspaces?: UserWorkspaceDto[];
}
+
+export class RegisteredWith {
+ @IsString()
+ registeredWith: string;
+}
diff --git a/src/modules/identity/services/user.service.ts b/src/modules/identity/services/user.service.ts
index 26e4b045..1544470c 100644
--- a/src/modules/identity/services/user.service.ts
+++ b/src/modules/identity/services/user.service.ts
@@ -3,7 +3,7 @@ import {
Injectable,
UnauthorizedException,
} from "@nestjs/common";
-import { UpdateUserDto } from "../payloads/user.payload";
+import { RegisteredWith, UpdateUserDto } from "../payloads/user.payload";
import { UserRepository } from "../repositories/user.repository";
import { RegisterPayload } from "../payloads/register.payload";
import { ConfigService } from "@nestjs/config";
@@ -59,6 +59,30 @@ export class UserService {
return await this.userRepository.getUserByEmail(email);
}
+ /**
+ * Fetches a user from database by username
+ * @param {string} email
+ * @returns {Promise} queried user data
+ */
+ async getUserRegisterStatus(email: string): Promise {
+ const user = await this.userRepository.getUserByEmail(email);
+ if (user?.authProviders) {
+ // Registered with google auth
+ return {
+ registeredWith: "google",
+ };
+ } else if (user?.email) {
+ // registered with email
+ return {
+ registeredWith: "email",
+ };
+ } else {
+ return {
+ registeredWith: "unknown",
+ };
+ }
+ }
+
/**
* Fetches a user by their email and hashed password
* @param {string} email
From 9df642e8722efd22f43b51bb923decad03238bd8 Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Sun, 25 Feb 2024 11:24:57 -0500
Subject: [PATCH 09/17] fix: google oauth[]
---
src/modules/common/config/configuration.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/common/config/configuration.ts b/src/modules/common/config/configuration.ts
index 72a46935..50198192 100644
--- a/src/modules/common/config/configuration.ts
+++ b/src/modules/common/config/configuration.ts
@@ -33,7 +33,7 @@ export default () => ({
google: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- appUrl: process.env.APP_URL,
+ appUrl: process.env.GOOGLE_APP_URL,
redirectUrl: process.env.LOGIN_REDIRECT_URL,
accessType: process.env.GOOGLE_ACCESS_TYPE,
},
From d873f53360b051b4d2d878b74b2bc06324fefeb3 Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Mon, 26 Feb 2024 14:56:25 -0500
Subject: [PATCH 10/17] feat: add activeSync body param[]
---
.github/workflows/development.yml | 8 +--
src/modules/common/services/parser.service.ts | 51 +++++++++++--------
.../controllers/workspace.controller.ts | 3 +-
.../workspace/payloads/collection.payload.ts | 8 +++
.../repositories/collection.repository.ts | 2 +-
5 files changed, 44 insertions(+), 28 deletions(-)
diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml
index 978b2399..4f820e3b 100644
--- a/.github/workflows/development.yml
+++ b/.github/workflows/development.yml
@@ -1,4 +1,4 @@
-name: Developement
+name: Development
on:
push:
branches:
@@ -12,13 +12,13 @@ jobs:
- uses: Azure/docker-login@v1
with:
- login-server: sparrowprod.azurecr.io
+ login-server: sparrowdev.azurecr.io
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- run: |
- docker build . -t sparrowprod.azurecr.io/sparrow-api:${{ github.run_number }}
- docker push sparrowprod.azurecr.io/sparrow-api:${{ github.run_number }}
+ docker build . -t sparrowdev.azurecr.io/sparrow-api:${{ github.run_number }}
+ docker push sparrowdev.azurecr.io/sparrow-api:${{ github.run_number }}
deploy:
needs: build
runs-on: ubuntu-latest
diff --git a/src/modules/common/services/parser.service.ts b/src/modules/common/services/parser.service.ts
index e5b12b81..dbd03f55 100644
--- a/src/modules/common/services/parser.service.ts
+++ b/src/modules/common/services/parser.service.ts
@@ -23,10 +23,13 @@ export class ParserService {
private readonly contextService: ContextService,
private readonly collectionService: CollectionService,
) {}
- async parse(file: string): Promise> {
+ async parse(
+ file: string,
+ activeSync?: boolean,
+ ): Promise> {
const openApiDocument = (await SwaggerParser.parse(file)) as OpenAPI303;
const baseUrl = this.getBaseUrl(openApiDocument);
-
+ let existingCollection: WithId | null = null;
const folderObjMap = new Map();
for (const [key, value] of Object.entries(openApiDocument.paths)) {
//key will be endpoints /put and values will its apis post ,put etc
@@ -112,26 +115,31 @@ export class ParserService {
});
const user = await this.contextService.get("user");
- let mergedFolderItems: CollectionItem[] = [];
- const existingCollection: WithId =
- await this.collectionService.getActiveSyncedCollection(
- openApiDocument.info.title,
- );
- if (existingCollection) {
- //check on folder level
- mergedFolderItems = this.compareAndMerge(existingCollection.items, items);
- for (let x = 0; x < existingCollection.items?.length; x++) {
- const newItem: CollectionItem[] = items.filter((item) => {
- return item.name === existingCollection.items[x].name;
- });
- //check on request level
- const mergedFolderRequests: CollectionItem[] = this.compareAndMerge(
- existingCollection.items[x].items,
- newItem[0]?.items || [],
+ if (activeSync) {
+ let mergedFolderItems: CollectionItem[] = [];
+ existingCollection =
+ await this.collectionService.getActiveSyncedCollection(
+ openApiDocument.info.title,
+ );
+ if (existingCollection) {
+ //check on folder level
+ mergedFolderItems = this.compareAndMerge(
+ existingCollection.items,
+ items,
);
- mergedFolderItems[x].items = mergedFolderRequests;
+ for (let x = 0; x < existingCollection.items?.length; x++) {
+ const newItem: CollectionItem[] = items.filter((item) => {
+ return item.name === existingCollection.items[x].name;
+ });
+ //check on request level
+ const mergedFolderRequests: CollectionItem[] = this.compareAndMerge(
+ existingCollection.items[x].items,
+ newItem[0]?.items || [],
+ );
+ mergedFolderItems[x].items = mergedFolderRequests;
+ }
+ items = mergedFolderItems;
}
- items = mergedFolderItems;
}
const newItems: CollectionItem[] = [];
for (let x = 0; x < items?.length; x++) {
@@ -163,7 +171,7 @@ export class ParserService {
uuid: openApiDocument.info.title,
createdBy: user.name,
updatedBy: user.name,
- activeSync: true,
+ activeSync,
createdAt: new Date(),
updatedAt: new Date(),
};
@@ -178,7 +186,6 @@ export class ParserService {
const newCollection = await this.collectionService.importCollection(
collection,
);
-
return {
id: newCollection.insertedId.toString(),
name: collection.name,
diff --git a/src/modules/workspace/controllers/workspace.controller.ts b/src/modules/workspace/controllers/workspace.controller.ts
index 19ffce03..51f2b3d0 100644
--- a/src/modules/workspace/controllers/workspace.controller.ts
+++ b/src/modules/workspace/controllers/workspace.controller.ts
@@ -357,6 +357,7 @@ export class WorkSpaceController {
@Res() res: FastifyReply,
@Body() importCollectionDto: ImportCollectionDto,
) {
+ const activeSync = importCollectionDto.activeSync ?? false;
const response = await axios.get(importCollectionDto.url);
const data = response.data;
const responseType = response.headers["content-type"];
@@ -364,7 +365,7 @@ export class WorkSpaceController {
? data
: yml.load(data);
- const collectionObj = await this.parserService.parse(dataObj);
+ const collectionObj = await this.parserService.parse(dataObj, activeSync);
await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
id: new ObjectId(collectionObj.id),
name: collectionObj.name,
diff --git a/src/modules/workspace/payloads/collection.payload.ts b/src/modules/workspace/payloads/collection.payload.ts
index c49f7361..baec2bc5 100644
--- a/src/modules/workspace/payloads/collection.payload.ts
+++ b/src/modules/workspace/payloads/collection.payload.ts
@@ -6,6 +6,7 @@ import {
IsArray,
IsEnum,
ValidateNested,
+ IsBoolean,
} from "class-validator";
import { ApiProperty } from "@nestjs/swagger";
import {
@@ -117,4 +118,11 @@ export class ImportCollectionDto {
@IsString()
@IsNotEmpty()
url: string;
+
+ @ApiProperty({
+ required: false,
+ example: false,
+ })
+ @IsBoolean()
+ activeSync?: boolean;
}
diff --git a/src/modules/workspace/repositories/collection.repository.ts b/src/modules/workspace/repositories/collection.repository.ts
index d90e8fea..9a7ef16a 100644
--- a/src/modules/workspace/repositories/collection.repository.ts
+++ b/src/modules/workspace/repositories/collection.repository.ts
@@ -252,7 +252,7 @@ export class CollectionRepository {
if (workspaceDetails) {
const data = await this.db
.collection(Collections.COLLECTION)
- .findOne({ _id: workspaceDetails.collection[0].id });
+ .findOne({ _id: workspaceDetails.collection[0].id, activeSync: true });
return data;
}
}
From fd3e78ccc1e1e46acb56458c8974fd370f245b0f Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Tue, 27 Feb 2024 12:12:59 +0530
Subject: [PATCH 11/17] build: fix development yaml[]
---
.github/workflows/development.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml
index 4f820e3b..88d0ff2b 100644
--- a/.github/workflows/development.yml
+++ b/.github/workflows/development.yml
@@ -12,13 +12,13 @@ jobs:
- uses: Azure/docker-login@v1
with:
- login-server: sparrowdev.azurecr.io
+ login-server: sparrowprod.azurecr.io
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- run: |
- docker build . -t sparrowdev.azurecr.io/sparrow-api:${{ github.run_number }}
- docker push sparrowdev.azurecr.io/sparrow-api:${{ github.run_number }}
+ docker build . -t sparrowprod.azurecr.io/sparrow-api:${{ github.run_number }}
+ docker push sparrowprod.azurecr.io/sparrow-api:${{ github.run_number }}
deploy:
needs: build
runs-on: ubuntu-latest
From a57d26f7d18aa6067ff2175069f1c6b56ad86466 Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Tue, 27 Feb 2024 18:08:07 +0530
Subject: [PATCH 12/17] feat: add activeSyncUrl[]
---
src/modules/app/app.controller.ts | 2 +-
src/modules/common/models/collection.model.ts | 10 ++++++++++
src/modules/common/services/parser.service.ts | 19 +++++++++++++------
.../controllers/workspace.controller.ts | 18 ++++++++++++------
.../repositories/collection.repository.ts | 11 +++++++++--
.../repositories/workspace.repository.ts | 18 ++++++++++++------
.../workspace/services/collection.service.ts | 10 ++++++++--
7 files changed, 65 insertions(+), 23 deletions(-)
diff --git a/src/modules/app/app.controller.ts b/src/modules/app/app.controller.ts
index 5358e9d1..b687dfc9 100644
--- a/src/modules/app/app.controller.ts
+++ b/src/modules/app/app.controller.ts
@@ -10,7 +10,7 @@ import { AppService } from "./app.service";
export class AppController {
constructor(private appService: AppService) {}
- @Get("updater/:target/:arch/:currentVersion")
+ @Get("updater/:target/:arch/:currentVersion1")
@ApiOperation({
summary: "Updater Details",
description: "Fetch app updater json",
diff --git a/src/modules/common/models/collection.model.ts b/src/modules/common/models/collection.model.ts
index ba8bf084..dfda661f 100644
--- a/src/modules/common/models/collection.model.ts
+++ b/src/modules/common/models/collection.model.ts
@@ -254,6 +254,11 @@ export class Collection {
@IsOptional()
activeSync?: boolean;
+ @ApiProperty()
+ @IsString()
+ @IsOptional()
+ activeSyncUrl?: string;
+
@IsOptional()
@IsDateString()
createdAt?: Date;
@@ -279,4 +284,9 @@ export class CollectionDto {
@IsString()
@IsNotEmpty()
name: string;
+
+ @ApiProperty()
+ @IsBoolean()
+ @IsOptional()
+ activeSync?: boolean;
}
diff --git a/src/modules/common/services/parser.service.ts b/src/modules/common/services/parser.service.ts
index dbd03f55..8c103854 100644
--- a/src/modules/common/services/parser.service.ts
+++ b/src/modules/common/services/parser.service.ts
@@ -26,7 +26,9 @@ export class ParserService {
async parse(
file: string,
activeSync?: boolean,
- ): Promise> {
+ workspaceId?: string,
+ activeSyncUrl?: string,
+ ): Promise> {
const openApiDocument = (await SwaggerParser.parse(file)) as OpenAPI303;
const baseUrl = this.getBaseUrl(openApiDocument);
let existingCollection: WithId | null = null;
@@ -120,6 +122,7 @@ export class ParserService {
existingCollection =
await this.collectionService.getActiveSyncedCollection(
openApiDocument.info.title,
+ workspaceId,
);
if (existingCollection) {
//check on folder level
@@ -172,6 +175,7 @@ export class ParserService {
createdBy: user.name,
updatedBy: user.name,
activeSync,
+ activeSyncUrl: activeSyncUrl ?? "",
createdAt: new Date(),
updatedAt: new Date(),
};
@@ -181,15 +185,18 @@ export class ParserService {
existingCollection._id.toString(),
collection,
);
- return { id: existingCollection._id.toString(), name: collection.name };
+ const updatedCollection = await this.collectionService.getCollection(
+ existingCollection._id.toString(),
+ );
+ return updatedCollection;
} else {
const newCollection = await this.collectionService.importCollection(
collection,
);
- return {
- id: newCollection.insertedId.toString(),
- name: collection.name,
- };
+ const collectionDetails = await this.collectionService.getCollection(
+ newCollection.insertedId.toString(),
+ );
+ return collectionDetails;
}
}
handleCircularReference(obj: CollectionItem) {
diff --git a/src/modules/workspace/controllers/workspace.controller.ts b/src/modules/workspace/controllers/workspace.controller.ts
index 51f2b3d0..a2f99939 100644
--- a/src/modules/workspace/controllers/workspace.controller.ts
+++ b/src/modules/workspace/controllers/workspace.controller.ts
@@ -331,11 +331,11 @@ export class WorkSpaceController {
: yml.load(dataString);
const collectionObj = await this.parserService.parse(dataObj);
await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
- id: new ObjectId(collectionObj.id),
+ id: new ObjectId(collectionObj._id),
name: collectionObj.name,
});
const collection = await this.collectionService.getCollection(
- collectionObj.id,
+ collectionObj._id.toString(),
);
const responseData = new ApiResponseService(
"Collection Imported",
@@ -365,10 +365,16 @@ export class WorkSpaceController {
? data
: yml.load(data);
- const collectionObj = await this.parserService.parse(dataObj, activeSync);
+ const collectionObj = await this.parserService.parse(
+ dataObj,
+ activeSync,
+ workspaceId,
+ importCollectionDto.url,
+ );
await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
- id: new ObjectId(collectionObj.id),
+ id: new ObjectId(collectionObj._id),
name: collectionObj.name,
+ activeSync: collectionObj.activeSync,
});
const responseData = new ApiResponseService(
"Collection Imported",
@@ -401,12 +407,12 @@ export class WorkSpaceController {
: (yml.load(jsonObj) as string);
const collectionObj = await this.parserService.parse(dataObj);
await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
- id: new ObjectId(collectionObj.id),
+ id: new ObjectId(collectionObj._id),
name: collectionObj.name,
});
const collection = await this.collectionService.getCollection(
- collectionObj.id,
+ collectionObj._id.toString(),
);
const responseData = new ApiResponseService(
"Collection Imported",
diff --git a/src/modules/workspace/repositories/collection.repository.ts b/src/modules/workspace/repositories/collection.repository.ts
index 9a7ef16a..795f74cd 100644
--- a/src/modules/workspace/repositories/collection.repository.ts
+++ b/src/modules/workspace/repositories/collection.repository.ts
@@ -242,11 +242,18 @@ export class CollectionRepository {
}
}
- async getActiveSyncedCollection(title: string): Promise> {
+ async getActiveSyncedCollection(
+ title: string,
+ workspaceId: string,
+ ): Promise> {
const workspaceDetails = await this.db
.collection(Collections.WORKSPACE)
.findOne(
- { "collection.name": title },
+ {
+ "collection.name": title,
+ "collection.activeSync": true,
+ _id: new ObjectId(workspaceId),
+ },
{ projection: { "collection.$": 1 } },
);
if (workspaceDetails) {
diff --git a/src/modules/workspace/repositories/workspace.repository.ts b/src/modules/workspace/repositories/workspace.repository.ts
index 30813f89..0f13259f 100644
--- a/src/modules/workspace/repositories/workspace.repository.ts
+++ b/src/modules/workspace/repositories/workspace.repository.ts
@@ -115,12 +115,18 @@ export class WorkspaceRepository {
collection: CollectionDto,
): Promise {
const _id = new ObjectId(workspaceId);
- return await this.db
- .collection(Collections.WORKSPACE)
- .updateOne(
- { _id },
- { $push: { collection: { id: collection.id, name: collection.name } } },
- );
+ return await this.db.collection(Collections.WORKSPACE).updateOne(
+ { _id },
+ {
+ $push: {
+ collection: {
+ id: collection.id,
+ name: collection.name,
+ activeSync: collection.activeSync,
+ },
+ },
+ },
+ );
}
async updateCollectioninWorkspace(
diff --git a/src/modules/workspace/services/collection.service.ts b/src/modules/workspace/services/collection.service.ts
index 33be370d..6138db33 100644
--- a/src/modules/workspace/services/collection.service.ts
+++ b/src/modules/workspace/services/collection.service.ts
@@ -70,8 +70,14 @@ export class CollectionService {
return collections;
}
- async getActiveSyncedCollection(title: string): Promise> {
- return await this.collectionReposistory.getActiveSyncedCollection(title);
+ async getActiveSyncedCollection(
+ title: string,
+ workspaceId: string,
+ ): Promise> {
+ return await this.collectionReposistory.getActiveSyncedCollection(
+ title,
+ workspaceId,
+ );
}
async checkPermission(workspaceId: string, userid: ObjectId): Promise {
From ff62c641bdc108124703ffa3a3e11f4438d1ff7e Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Tue, 27 Feb 2024 18:09:48 +0530
Subject: [PATCH 13/17] feat: add activeSyncUrl[]
---
src/modules/app/app.controller.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/app/app.controller.ts b/src/modules/app/app.controller.ts
index b687dfc9..5358e9d1 100644
--- a/src/modules/app/app.controller.ts
+++ b/src/modules/app/app.controller.ts
@@ -10,7 +10,7 @@ import { AppService } from "./app.service";
export class AppController {
constructor(private appService: AppService) {}
- @Get("updater/:target/:arch/:currentVersion1")
+ @Get("updater/:target/:arch/:currentVersion")
@ApiOperation({
summary: "Updater Details",
description: "Fetch app updater json",
From 8c7e6220b3d6900f5afaab754f46c4b583dcc73d Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Wed, 28 Feb 2024 13:51:29 +0530
Subject: [PATCH 14/17] fix: featch activeSync Collection[]
---
src/modules/common/services/parser.service.ts | 16 +++++++++---
.../controllers/workspace.controller.ts | 25 +++++++++++--------
.../repositories/collection.repository.ts | 13 ++++++----
3 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/src/modules/common/services/parser.service.ts b/src/modules/common/services/parser.service.ts
index 8c103854..47f9a4ca 100644
--- a/src/modules/common/services/parser.service.ts
+++ b/src/modules/common/services/parser.service.ts
@@ -28,7 +28,10 @@ export class ParserService {
activeSync?: boolean,
workspaceId?: string,
activeSyncUrl?: string,
- ): Promise> {
+ ): Promise<{
+ collection: WithId;
+ existingCollection: boolean;
+ }> {
const openApiDocument = (await SwaggerParser.parse(file)) as OpenAPI303;
const baseUrl = this.getBaseUrl(openApiDocument);
let existingCollection: WithId | null = null;
@@ -188,7 +191,10 @@ export class ParserService {
const updatedCollection = await this.collectionService.getCollection(
existingCollection._id.toString(),
);
- return updatedCollection;
+ return {
+ collection: updatedCollection,
+ existingCollection: true,
+ };
} else {
const newCollection = await this.collectionService.importCollection(
collection,
@@ -196,7 +202,11 @@ export class ParserService {
const collectionDetails = await this.collectionService.getCollection(
newCollection.insertedId.toString(),
);
- return collectionDetails;
+ collectionDetails;
+ return {
+ collection: collectionDetails,
+ existingCollection: false,
+ };
}
}
handleCircularReference(obj: CollectionItem) {
diff --git a/src/modules/workspace/controllers/workspace.controller.ts b/src/modules/workspace/controllers/workspace.controller.ts
index a2f99939..72df9bcb 100644
--- a/src/modules/workspace/controllers/workspace.controller.ts
+++ b/src/modules/workspace/controllers/workspace.controller.ts
@@ -330,12 +330,13 @@ export class WorkSpaceController {
? JSON.parse(dataString)
: yml.load(dataString);
const collectionObj = await this.parserService.parse(dataObj);
+
await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
- id: new ObjectId(collectionObj._id),
- name: collectionObj.name,
+ id: new ObjectId(collectionObj.collection._id),
+ name: collectionObj.collection.name,
});
const collection = await this.collectionService.getCollection(
- collectionObj._id.toString(),
+ collectionObj.collection._id.toString(),
);
const responseData = new ApiResponseService(
"Collection Imported",
@@ -371,11 +372,13 @@ export class WorkSpaceController {
workspaceId,
importCollectionDto.url,
);
- await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
- id: new ObjectId(collectionObj._id),
- name: collectionObj.name,
- activeSync: collectionObj.activeSync,
- });
+ if (!collectionObj.existingCollection) {
+ await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
+ id: new ObjectId(collectionObj.collection._id),
+ name: collectionObj.collection.name,
+ activeSync: collectionObj.collection.activeSync,
+ });
+ }
const responseData = new ApiResponseService(
"Collection Imported",
HttpStatusCode.OK,
@@ -407,12 +410,12 @@ export class WorkSpaceController {
: (yml.load(jsonObj) as string);
const collectionObj = await this.parserService.parse(dataObj);
await this.workspaceService.addCollectionInWorkSpace(workspaceId, {
- id: new ObjectId(collectionObj._id),
- name: collectionObj.name,
+ id: new ObjectId(collectionObj.collection._id),
+ name: collectionObj.collection.name,
});
const collection = await this.collectionService.getCollection(
- collectionObj._id.toString(),
+ collectionObj.collection._id.toString(),
);
const responseData = new ApiResponseService(
"Collection Imported",
diff --git a/src/modules/workspace/repositories/collection.repository.ts b/src/modules/workspace/repositories/collection.repository.ts
index 795f74cd..d19a1f68 100644
--- a/src/modules/workspace/repositories/collection.repository.ts
+++ b/src/modules/workspace/repositories/collection.repository.ts
@@ -250,16 +250,19 @@ export class CollectionRepository {
.collection(Collections.WORKSPACE)
.findOne(
{
- "collection.name": title,
- "collection.activeSync": true,
_id: new ObjectId(workspaceId),
},
- { projection: { "collection.$": 1 } },
+ { projection: { collection: 1 } },
+ );
+
+ if (workspaceDetails && workspaceDetails.collection) {
+ const activeCollection = workspaceDetails.collection.find(
+ (collection) =>
+ collection.activeSync === true && collection.name === title,
);
- if (workspaceDetails) {
const data = await this.db
.collection(Collections.COLLECTION)
- .findOne({ _id: workspaceDetails.collection[0].id, activeSync: true });
+ .findOne({ _id: activeCollection.id, activeSync: true });
return data;
}
}
From f414143d5ffdb3e8b9ef5b2335beb6b088bbc579 Mon Sep 17 00:00:00 2001
From: Nayan Lakhwani
Date: Wed, 28 Feb 2024 16:57:23 +0530
Subject: [PATCH 15/17] fix: remove refresh token limit check[]
---
src/modules/identity/controllers/auth.controller.ts | 7 ++++---
.../identity/controllers/test/auth.controller.spec.ts | 2 +-
src/modules/identity/repositories/user.repository.ts | 5 +++--
src/modules/identity/services/auth.service.ts | 2 +-
4 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/modules/identity/controllers/auth.controller.ts b/src/modules/identity/controllers/auth.controller.ts
index da397617..dec6ccb6 100644
--- a/src/modules/identity/controllers/auth.controller.ts
+++ b/src/modules/identity/controllers/auth.controller.ts
@@ -62,8 +62,8 @@ export class AuthController {
@ApiResponse({ status: 401, description: "Unauthorized" })
async login(@Body() payload: LoginPayload, @Res() res: FastifyReply) {
const user = await this.authService.validateUser(payload);
-
- await this.authService.checkRefreshTokenSize(user);
+ // Removing refresh token limit check until refresh token flow is fixed - Nayan (Feb 28, 2024)
+ // await this.authService.checkRefreshTokenLimit(user);
const tokenPromises = [
this.authService.createToken(user._id),
@@ -136,7 +136,8 @@ export class AuthController {
if (isUserExists) {
id = isUserExists._id;
this.contextService.set("user", isUserExists);
- await this.authService.checkRefreshTokenSize(isUserExists);
+ // Removing refresh token limit check until refresh token flow is fixed - Nayan (Feb 28, 2024)
+ // await this.authService.checkRefreshTokenLimit(isUserExists);
} else {
const user = await this.userService.createGoogleAuthUser(
oAuthId,
diff --git a/src/modules/identity/controllers/test/auth.controller.spec.ts b/src/modules/identity/controllers/test/auth.controller.spec.ts
index 229ecee8..05659b28 100644
--- a/src/modules/identity/controllers/test/auth.controller.spec.ts
+++ b/src/modules/identity/controllers/test/auth.controller.spec.ts
@@ -63,7 +63,7 @@ describe("AuthController", () => {
let mockFastifyReply: FastifyReply;
const authServiceMock = {
validateUser: jest.fn().mockResolvedValue(UserDetails),
- checkRefreshTokenSize: jest.fn().mockResolvedValue(null),
+ checkRefreshTokenLimit: jest.fn().mockResolvedValue(null),
createToken: jest.fn().mockResolvedValue(TokenResponse),
createRefreshToken: jest.fn().mockResolvedValue(TokenResponse),
validateRefreshToken: jest.fn().mockResolvedValue(TokenResponse),
diff --git a/src/modules/identity/repositories/user.repository.ts b/src/modules/identity/repositories/user.repository.ts
index 855b8c89..62973f1f 100644
--- a/src/modules/identity/repositories/user.repository.ts
+++ b/src/modules/identity/repositories/user.repository.ts
@@ -160,11 +160,12 @@ export class UserRepository {
_id: ObjectId,
refreshToken: string,
): Promise {
+ // Replacing old refresh tokens with the new token until refresh token flow is fixed. - Nayan (Feb 28,2024)
await this.db.collection(Collections.USER).findOneAndUpdate(
{ _id },
{
- $push: {
- refresh_tokens: refreshToken,
+ $set: {
+ refresh_tokens: [refreshToken],
},
},
);
diff --git a/src/modules/identity/services/auth.service.ts b/src/modules/identity/services/auth.service.ts
index c036cf89..8a9aee5c 100644
--- a/src/modules/identity/services/auth.service.ts
+++ b/src/modules/identity/services/auth.service.ts
@@ -198,7 +198,7 @@ export class AuthService {
};
}
- async checkRefreshTokenSize(user: User): Promise {
+ async checkRefreshTokenLimit(user: User): Promise {
if (user.refresh_tokens.length === this.refreshTokenMaxLimit) {
throw new BadRequestException("Maximum request limit reached");
}
From db8e27642661815189bfcc63bb479a4d1be23a9e Mon Sep 17 00:00:00 2001
From: Md Asif Raza
Date: Fri, 1 Mar 2024 11:57:55 +0530
Subject: [PATCH 16/17] feat: add sparrow email env [11]
Signed-off-by: Md Asif Raza
---
src/modules/common/config/configuration.ts | 3 +++
src/modules/identity/services/team-user.service.ts | 1 +
src/modules/identity/services/user.service.ts | 1 +
src/modules/views/inviteTeamEmail.handlebars | 5 +++--
src/modules/views/inviteWorkspaceEmail.handlebars | 5 +++--
src/modules/views/verifyEmail.handlebars | 2 +-
src/modules/workspace/services/workspace.service.ts | 1 +
7 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/modules/common/config/configuration.ts b/src/modules/common/config/configuration.ts
index 72a46935..f1853547 100644
--- a/src/modules/common/config/configuration.ts
+++ b/src/modules/common/config/configuration.ts
@@ -57,4 +57,7 @@ export default () => ({
appUrl: process.env.MAC_INTEL_APP_URL,
},
},
+ support: {
+ sparrowEmail: process.env.SPARROW_EMAIL,
+ },
});
diff --git a/src/modules/identity/services/team-user.service.ts b/src/modules/identity/services/team-user.service.ts
index ae7ee63f..ce2dd244 100644
--- a/src/modules/identity/services/team-user.service.ts
+++ b/src/modules/identity/services/team-user.service.ts
@@ -97,6 +97,7 @@ export class TeamUserService {
firstname: user.name,
username: currentUser.name,
teamname: payload.teamName,
+ sparrowEmail: this.configService.get("support.sparrowEmail"),
},
subject: `${currentUser.name} has invited you to the team "${payload.teamName}"`,
};
diff --git a/src/modules/identity/services/user.service.ts b/src/modules/identity/services/user.service.ts
index 4e972850..7f7c975b 100644
--- a/src/modules/identity/services/user.service.ts
+++ b/src/modules/identity/services/user.service.ts
@@ -181,6 +181,7 @@ export class UserService {
context: {
name: userDetails.name,
verificationCode,
+ sparrowEmail: this.configService.get("support.sparrowEmail"),
},
subject: `Reset Your Sparrow Account Password`,
};
diff --git a/src/modules/views/inviteTeamEmail.handlebars b/src/modules/views/inviteTeamEmail.handlebars
index 5e68f01d..6898690c 100644
--- a/src/modules/views/inviteTeamEmail.handlebars
+++ b/src/modules/views/inviteTeamEmail.handlebars
@@ -99,7 +99,8 @@ line-height: 150%; /* 21px */
"
>
If you need additional assistance please contact us at
- help@sparrow.com
+ >{{sparrowEmail}}
diff --git a/src/modules/views/inviteWorkspaceEmail.handlebars b/src/modules/views/inviteWorkspaceEmail.handlebars
index 7b24b6d1..0f516bfb 100644
--- a/src/modules/views/inviteWorkspaceEmail.handlebars
+++ b/src/modules/views/inviteWorkspaceEmail.handlebars
@@ -99,7 +99,8 @@ line-height: 150%; /* 21px */
"
>
If you need additional assistance please contact us at
- help@sparrow.com
+ >{{sparrowEmail}}
diff --git a/src/modules/views/verifyEmail.handlebars b/src/modules/views/verifyEmail.handlebars
index 7f58b8f7..03fe693c 100644
--- a/src/modules/views/verifyEmail.handlebars
+++ b/src/modules/views/verifyEmail.handlebars
@@ -14,6 +14,6 @@
font-size: 20px; ">{{verificationCode}}
The verification code is valid for 1 min
Please do not share verification code
-
If you need additional assistance or you did not make this change, please contact us at help@sparrow.com
+
If you need additional assistance or you did not make this change, please contact us at {{sparrowEmail}}