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}}

\ No newline at end of file diff --git a/src/modules/workspace/services/workspace.service.ts b/src/modules/workspace/services/workspace.service.ts index 3ce8d792..f8b327e2 100644 --- a/src/modules/workspace/services/workspace.service.ts +++ b/src/modules/workspace/services/workspace.service.ts @@ -539,6 +539,7 @@ export class WorkspaceService { firstname: user.name, username: currentUser.name, workspacename: payload.workspaceName, + sparrowEmail: this.configService.get("support.sparrowEmail"), }, subject: `${currentUser.name} has invited you to the workspace "${payload.workspaceName}"`, }; From 6f60bad4506f356688b82f8001ba87e59b59832b Mon Sep 17 00:00:00 2001 From: Md Asif Raza Date: Fri, 1 Mar 2024 12:10:16 +0530 Subject: [PATCH 17/17] feat: add sparrow email env [11] Signed-off-by: Md Asif Raza --- .env.example | 5 +- deploymentManifests/deployment.yml | 339 +++++++++++++++-------------- 2 files changed, 176 insertions(+), 168 deletions(-) diff --git a/.env.example b/.env.example index 3a20286f..b8c012e4 100755 --- a/.env.example +++ b/.env.example @@ -44,4 +44,7 @@ REFRESH_TOKEN_MAX_LIMIT=50 MAC_APPLE_SILICON_APP_SIGNATURE= MAC_APPLE_SILICON_APP_URL= MAC_INTEL_APP_SIGNATURE= - MAC_INTEL_APP_URL= \ No newline at end of file + MAC_INTEL_APP_URL= + +# SUPPORT + SPARROW_EMAIL=contactus@sparrowapp.dev \ No newline at end of file diff --git a/deploymentManifests/deployment.yml b/deploymentManifests/deployment.yml index 86d1350c..2a923026 100644 --- a/deploymentManifests/deployment.yml +++ b/deploymentManifests/deployment.yml @@ -17,174 +17,179 @@ spec: app: sparrow-api spec: containers: - - image: sparrowprod.azurecr.io/sparrow-api:_BUILD__ID_ - name: sparrow-api - imagePullPolicy: Always - resources: {} - ports: - - containerPort: 80 - env: - - name: PORT - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: PORT - - name: APP_ENV - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: APP_ENV - - name: APP_URL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: APP_URL - - name: JWT_SECRET_KEY - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: JWT_SECRET_KEY - - name: EMAIL_VALIDATION_CODE_EXPIRY_TIME - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: EMAIL_VALIDATION_CODE_EXPIRY_TIME - - name: JWT_EXPIRATION_TIME - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: JWT_EXPIRATION_TIME - - name: DB_URL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: DB_URL - - name: AZURE_CONNECTION_STRING - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: AZURE_CONNECTION_STRING - - name: REFRESH_TOKEN_SECRET_KEY - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: REFRESH_TOKEN_SECRET_KEY - - name: REFRESH_TOKEN_EXPIRATION_TIME - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: REFRESH_TOKEN_EXPIRATION_TIME - - name: REFRESH_TOKEN_MAX_LIMIT - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: REFRESH_TOKEN_MAX_LIMIT - - name: SMTP_SENDER_EMAIL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: SMTP_SENDER_EMAIL - - name: SMTP_SENDER_PASSWORD - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: SMTP_SENDER_PASSWORD - - name: SMTP_MAIL_HOST - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: SMTP_MAIL_HOST - - name: SMTP_MAIL_PORT - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: SMTP_MAIL_PORT - - name: SMTP_MAIL_SECURE - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: SMTP_MAIL_SECURE - - name: SMTP_USER_NAME - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: SMTP_USER_NAME - - name: LOGIN_REDIRECT_URL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: LOGIN_REDIRECT_URL - - name: GOOGLE_APP_URL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: GOOGLE_APP_URL - - name: GOOGLE_ACCESS_TYPE - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: GOOGLE_ACCESS_TYPE - - name: GOOGLE_CLIENT_ID - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: GOOGLE_CLIENT_ID - - name: GOOGLE_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: GOOGLE_CLIENT_SECRET - - name: KAFKA_BROKER - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: KAFKA_BROKER - - name: REFRESH_TOKEN_MAX_LIMIT - valueFrom: - secretKeyRef: - name: sparrow-api-secret - - name: APP_UPDATE_AVAILABLE - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: APP_UPDATE_AVAILABLE - - name: APP_VERSION - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: APP_VERSION - - name: WINDOWS_APP_SIGNATURE - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: WINDOWS_APP_SIGNATURE - - name: WINDOWS_APP_URL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: WINDOWS_APP_URL - - name: MAC_APPLE_SILICON_APP_SIGNATURE - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: MAC_APPLE_SILICON_APP_SIGNATURE - - name: MAC_APPLE_SILICON_APP_URL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: MAC_APPLE_SILICON_APP_URL - - name: MAC_INTEL_APP_SIGNATURE - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: MAC_INTEL_APP_SIGNATURE - - name: MAC_INTEL_APP_URL - valueFrom: - secretKeyRef: - name: sparrow-api-secret - key: MAC_INTEL_APP_URL ---- + - image: sparrowprod.azurecr.io/sparrow-api:_BUILD__ID_ + name: sparrow-api + imagePullPolicy: Always + resources: {} + ports: + - containerPort: 80 + env: + - name: PORT + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: PORT + - name: APP_ENV + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: APP_ENV + - name: APP_URL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: APP_URL + - name: JWT_SECRET_KEY + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: JWT_SECRET_KEY + - name: EMAIL_VALIDATION_CODE_EXPIRY_TIME + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: EMAIL_VALIDATION_CODE_EXPIRY_TIME + - name: JWT_EXPIRATION_TIME + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: JWT_EXPIRATION_TIME + - name: DB_URL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: DB_URL + - name: AZURE_CONNECTION_STRING + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: AZURE_CONNECTION_STRING + - name: REFRESH_TOKEN_SECRET_KEY + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: REFRESH_TOKEN_SECRET_KEY + - name: REFRESH_TOKEN_EXPIRATION_TIME + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: REFRESH_TOKEN_EXPIRATION_TIME + - name: REFRESH_TOKEN_MAX_LIMIT + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: REFRESH_TOKEN_MAX_LIMIT + - name: SMTP_SENDER_EMAIL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: SMTP_SENDER_EMAIL + - name: SMTP_SENDER_PASSWORD + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: SMTP_SENDER_PASSWORD + - name: SMTP_MAIL_HOST + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: SMTP_MAIL_HOST + - name: SMTP_MAIL_PORT + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: SMTP_MAIL_PORT + - name: SMTP_MAIL_SECURE + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: SMTP_MAIL_SECURE + - name: SMTP_USER_NAME + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: SMTP_USER_NAME + - name: LOGIN_REDIRECT_URL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: LOGIN_REDIRECT_URL + - name: GOOGLE_APP_URL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: GOOGLE_APP_URL + - name: GOOGLE_ACCESS_TYPE + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: GOOGLE_ACCESS_TYPE + - name: GOOGLE_CLIENT_ID + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: GOOGLE_CLIENT_ID + - name: GOOGLE_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: GOOGLE_CLIENT_SECRET + - name: KAFKA_BROKER + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: KAFKA_BROKER + - name: REFRESH_TOKEN_MAX_LIMIT + valueFrom: + secretKeyRef: + name: sparrow-api-secret + - name: APP_UPDATE_AVAILABLE + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: APP_UPDATE_AVAILABLE + - name: APP_VERSION + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: APP_VERSION + - name: WINDOWS_APP_SIGNATURE + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: WINDOWS_APP_SIGNATURE + - name: WINDOWS_APP_URL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: WINDOWS_APP_URL + - name: MAC_APPLE_SILICON_APP_SIGNATURE + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: MAC_APPLE_SILICON_APP_SIGNATURE + - name: MAC_APPLE_SILICON_APP_URL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: MAC_APPLE_SILICON_APP_URL + - name: MAC_INTEL_APP_SIGNATURE + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: MAC_INTEL_APP_SIGNATURE + - name: MAC_INTEL_APP_URL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: MAC_INTEL_APP_URL + - name: SPARROW_EMAIL + valueFrom: + secretKeyRef: + name: sparrow-api-secret + key: SPARROW_EMAIL +--- apiVersion: v1 kind: Service metadata: