Skip to content

Commit bb960f9

Browse files
Merge branch 'development' into feat-Generate-Variables-Collection-Page
2 parents 566890b + fc749a7 commit bb960f9

File tree

14 files changed

+489
-70
lines changed

14 files changed

+489
-70
lines changed

.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,5 @@ STRIPE_SECRET_KEY= # Stripe secret key (backend - KEEP SECURE!)
121121

122122
# [Sparrow Admin]
123123
SPARROW_ADMIN_KEY= # Sparrow admin key for privileged operations specific to Sparrow team
124-
ADMIN_BASE_URL= # Base URL for Sparrow admin operations
124+
ADMIN_BASE_URL= # Base URL for Sparrow admin operations
125+
STAKEHOLDERS_EMAIL_LIST= # Comma-separated list of sparrow admin emails

deploymentManifests/deployment.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ spec:
340340
valueFrom:
341341
secretKeyRef:
342342
name: sparrow-api-secret
343-
key: DEEPSEEK_API_MODEL
343+
key: DEEPSEEK_API_MODEL
344344
- name: DB_NAME
345345
valueFrom:
346346
secretKeyRef:
@@ -381,6 +381,11 @@ spec:
381381
secretKeyRef:
382382
name: sparrow-api-secret
383383
key: ADMIN_BASE_URL
384+
- name: STAKEHOLDERS_EMAIL_LIST
385+
valueFrom:
386+
secretKeyRef:
387+
name: sparrow-api-secret
388+
key: STAKEHOLDERS_EMAIL_LIST
384389

385390
---
386391
apiVersion: v1

deploymentManifests/release-v2.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ spec:
309309
valueFrom:
310310
secretKeyRef:
311311
name: release-api-v2-secret
312-
key: DEEPSEEK_API_MODEL
312+
key: DEEPSEEK_API_MODEL
313313
- name: DB_NAME
314314
valueFrom:
315315
secretKeyRef:
@@ -350,6 +350,11 @@ spec:
350350
secretKeyRef:
351351
name: release-api-v2-secret
352352
key: ADMIN_BASE_URL
353+
- name: STAKEHOLDERS_EMAIL_LIST
354+
valueFrom:
355+
secretKeyRef:
356+
name: release-api-v2-secret
357+
key: STAKEHOLDERS_EMAIL_LIST
353358

354359
---
355360
apiVersion: v1

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
"start:upgrade-plan": "ts-node -r tsconfig-paths/register src/upgrade-plan.ts",
3434
"start:migration-mock-url": "ts-node -r tsconfig-paths/register src/migrationMockRequestUrl.ts",
3535
"start:migration-hub-billing": "ts-node -r tsconfig-paths/register src/migrationHubBilling.ts",
36-
"start:migration-superadmin": "ts-node -r tsconfig-paths/register src/migration-superadmin.ts"
36+
"start:migration-superadmin": "ts-node -r tsconfig-paths/register src/migration-superadmin.ts",
37+
"start:migration-email": "ts-node -r tsconfig-paths/register src/migration-emailId.ts"
3738
},
3839
"dependencies": {
3940
"@anthropic-ai/sdk": "^0.54.0",
@@ -84,6 +85,7 @@
8485
"husky": "^8.0.3",
8586
"install": "^0.13.0",
8687
"js-yaml": "^4.1.0",
88+
"json2csv": "6.0.0-alpha.2",
8789
"jsonwebtoken": "^9.0.2",
8890
"mongodb": "^5.7.0",
8991
"nest-access-control": "2.2.0",
@@ -117,6 +119,7 @@
117119
"@types/gravatar": "1.8.3",
118120
"@types/jest": "^29.5.3",
119121
"@types/js-yaml": "^4.0.7",
122+
"@types/json2csv": "^5.0.7",
120123
"@types/jsonwebtoken": "^9.0.9",
121124
"@types/mime-types": "^3.0.1",
122125
"@types/node": "16.11.56",

pnpm-lock.yaml

Lines changed: 61 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/modules/common/config/configuration.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export default () => ({
9898
conversationLimit: 30,
9999
conversationConatiner: process.env.AI_CONVERSATION_BLOB_CONTAINER,
100100
encryptionSecret: process.env.ENCRYPTION_SECRET,
101-
deepseekModel: process.env.DEEPSEEK_API_MODEL
101+
deepseekModel: process.env.DEEPSEEK_API_MODEL,
102102
},
103103
hubspot: {
104104
hubspotEnabled: process.env.HUBSPOT_INTEGRATION_ENABLED,
@@ -128,6 +128,7 @@ export default () => ({
128128
},
129129
sparrowAdmin: {
130130
adminKey: process.env.SPARROW_ADMIN_KEY,
131+
stakeholdersEmailList: process.env.STAKEHOLDERS_EMAIL_LIST,
131132
},
132133
admin: {
133134
baseURL: process.env.ADMIN_BASE_URL,

src/modules/common/services/email.service.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,22 @@ interface MailOptions {
99
from: string;
1010
to: string;
1111
text?: string;
12-
template: string;
12+
template?: string;
1313
context?: {
1414
[key: string]: any;
1515
};
1616
subject: string;
17+
attachments?: {
18+
filename: string;
19+
content: any;
20+
}[];
1721
}
1822

1923
@Injectable()
2024
export class EmailService {
2125
constructor(private configService: ConfigService) {}
2226

23-
createTransporter() {
27+
createTransporter(useTemplate = true) {
2428
const transporter = nodemailer.createTransport({
2529
host: this.configService.get("app.mailHost"),
2630
port: this.configService.get("app.mailPort"),
@@ -31,23 +35,25 @@ export class EmailService {
3135
},
3236
});
3337

34-
const handlebarOptions = {
35-
viewEngine: {
36-
extname: ".handlebars",
37-
partialsDir: path.resolve(__dirname, "..", "..", "views", "partials"),
38-
layoutsDir: path.resolve(__dirname, "..", "..", "views", "layouts"),
39-
defaultLayout: "main",
40-
helpers: {
41-
linkedinUrl: () => this.configService.get("social.linkedinUrl"),
42-
githubUrl: () => this.configService.get("social.githubUrl"),
43-
discordUrl: () => this.configService.get("social.discordUrl"),
38+
if (useTemplate) {
39+
const handlebarOptions = {
40+
viewEngine: {
41+
extname: ".handlebars",
42+
partialsDir: path.resolve(__dirname, "..", "..", "views", "partials"),
43+
layoutsDir: path.resolve(__dirname, "..", "..", "views", "layouts"),
44+
defaultLayout: "main",
45+
helpers: {
46+
linkedinUrl: () => this.configService.get("social.linkedinUrl"),
47+
githubUrl: () => this.configService.get("social.githubUrl"),
48+
discordUrl: () => this.configService.get("social.discordUrl"),
49+
},
4450
},
45-
},
46-
viewPath: path.resolve(__dirname, "..", "..", "views"),
47-
extName: ".handlebars",
48-
};
51+
viewPath: path.resolve(__dirname, "..", "..", "views"),
52+
extName: ".handlebars",
53+
};
4954

50-
transporter.use("compile", hbs(handlebarOptions));
55+
transporter.use("compile", hbs(handlebarOptions));
56+
}
5157

5258
return transporter;
5359
}

src/modules/workspace/controllers/collection.controller.ts

Lines changed: 88 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
CreateCollectionDto,
2323
UpdateCollectionDto,
2424
UpdateMockCollectionStatusDto,
25-
AuthCollection
25+
AuthCollection,
2626
} from "../payloads/collection.payload";
2727
import { FastifyReply } from "fastify";
2828
import { CollectionService } from "../services/collection.service";
@@ -32,6 +32,7 @@ import { WorkspaceService } from "../services/workspace.service";
3232
import {
3333
BranchChangeDto,
3434
CollectionAiRequestDto,
35+
CollectionGeneratedVariableDto,
3536
CollectionGraphQLDto,
3637
CollectionMockRequestResponseDto,
3738
CollectionRequestDto,
@@ -168,7 +169,6 @@ export class collectionController {
168169
return res.status(responseData.httpStatusCode).send(responseData);
169170
}
170171

171-
172172
@Put(":collectionId/workspace/:workspaceId")
173173
@ApiOperation({
174174
summary: "Update A Collections",
@@ -207,24 +207,27 @@ export class collectionController {
207207
return res.status(responseData.httpStatusCode).send(responseData);
208208
}
209209

210-
@Get('auth-profiles/:collectionId')
210+
@Get("auth-profiles/:collectionId")
211211
@ApiOperation({
212-
summary: 'Get all auth profiles for a collection',
213-
description: 'Fetches all auth profiles stored in the given collection.',
212+
summary: "Get all auth profiles for a collection",
213+
description: "Fetches all auth profiles stored in the given collection.",
214214
})
215215
@UseGuards(JwtAuthGuard)
216-
@ApiResponse({ status: 200, description: 'List of auth profiles returned' })
217-
@ApiResponse({ status: 404, description: 'Collection not found' })
216+
@ApiResponse({ status: 200, description: "List of auth profiles returned" })
217+
@ApiResponse({ status: 404, description: "Collection not found" })
218218
async getAuthProfiles(
219-
@Param('collectionId') collectionId: string,
219+
@Param("collectionId") collectionId: string,
220220
@Res() res: FastifyReply,
221221
@Req() req: ExtendedFastifyRequest,
222222
) {
223223
const user = req.user;
224-
const authProfiles = await this.collectionService.getAuthProfiles(collectionId, user);
224+
const authProfiles = await this.collectionService.getAuthProfiles(
225+
collectionId,
226+
user,
227+
);
225228

226229
const responseData = new ApiResponseService(
227-
'Success',
230+
"Success",
228231
HttpStatusCode.OK,
229232
authProfiles,
230233
);
@@ -240,9 +243,16 @@ export class collectionController {
240243
@UseGuards(JwtAuthGuard)
241244
@ApiResponse({ status: 200, description: "Auth profile Added Successfully" })
242245
@ApiResponse({ status: 400, description: "Adding operation Failed" })
243-
async addAuthProfiles(@Body() updateCollectionDto: Partial<UpdateCollectionDto>, @Res() res: FastifyReply, @Req() request: ExtendedFastifyRequest) {
246+
async addAuthProfiles(
247+
@Body() updateCollectionDto: Partial<UpdateCollectionDto>,
248+
@Res() res: FastifyReply,
249+
@Req() request: ExtendedFastifyRequest,
250+
) {
244251
const user = request.user;
245-
const message = await this.collectionService.addAuthProfile(updateCollectionDto, user);
252+
const message = await this.collectionService.addAuthProfile(
253+
updateCollectionDto,
254+
user,
255+
);
246256
const responseData = new ApiResponseService(
247257
"Success",
248258
HttpStatusCode.OK,
@@ -258,11 +268,21 @@ export class collectionController {
258268
description: "This will update an auth profile ",
259269
})
260270
@UseGuards(JwtAuthGuard)
261-
@ApiResponse({ status: 200, description: "Auth profile Updated Successfully" })
271+
@ApiResponse({
272+
status: 200,
273+
description: "Auth profile Updated Successfully",
274+
})
262275
@ApiResponse({ status: 400, description: "Update operation Failed" })
263-
async updateAuthProfiles(@Body() payload: AuthCollection, @Res() res: FastifyReply, @Req() request: ExtendedFastifyRequest) {
276+
async updateAuthProfiles(
277+
@Body() payload: AuthCollection,
278+
@Res() res: FastifyReply,
279+
@Req() request: ExtendedFastifyRequest,
280+
) {
264281
const user = request.user;
265-
const message = await this.collectionService.updateAuthProfile(payload, user);
282+
const message = await this.collectionService.updateAuthProfile(
283+
payload,
284+
user,
285+
);
266286
const responseData = new ApiResponseService(
267287
"Success",
268288
HttpStatusCode.OK,
@@ -278,11 +298,21 @@ export class collectionController {
278298
description: "This will delete an auth profile ",
279299
})
280300
@UseGuards(JwtAuthGuard)
281-
@ApiResponse({ status: 200, description: "Auth profile Updated Successfully" })
301+
@ApiResponse({
302+
status: 200,
303+
description: "Auth profile Updated Successfully",
304+
})
282305
@ApiResponse({ status: 400, description: "Deletion operation Failed" })
283-
async deleteAuthProfiles(@Body() payload: AuthCollection, @Res() res: FastifyReply, @Req() request: ExtendedFastifyRequest) {
306+
async deleteAuthProfiles(
307+
@Body() payload: AuthCollection,
308+
@Res() res: FastifyReply,
309+
@Req() request: ExtendedFastifyRequest,
310+
) {
284311
const user = request.user;
285-
const message = await this.collectionService.deleteAuthProfile(payload, user);
312+
const message = await this.collectionService.deleteAuthProfile(
313+
payload,
314+
user,
315+
);
286316
const responseData = new ApiResponseService(
287317
"Success",
288318
HttpStatusCode.OK,
@@ -1599,7 +1629,46 @@ export class collectionController {
15991629
const responseData = new ApiResponseService(
16001630
"Success",
16011631
HttpStatusCode.OK,
1602-
collectionVariables,
1632+
collectionVariables);
1633+
};
1634+
/**
1635+
* Endpoint to update all the New generated Variables in requests.
1636+
*
1637+
* @param collectionId The collectionId.
1638+
* @param KeyValuePairs[] The collectionId.
1639+
* @returns The response object with status and data.
1640+
*/
1641+
@Post("generate-variables/insert")
1642+
@ApiOperation({
1643+
summary: "Insert Generated Variables into Collection",
1644+
description:
1645+
"Updates each request in the collection by replacing the content field with its corresponding generated variable key.",
1646+
})
1647+
@UseGuards(JwtAuthGuard)
1648+
@ApiResponse({
1649+
status: 200,
1650+
description: "Generated Variables Added Successfully",
1651+
})
1652+
@ApiResponse({
1653+
status: 400,
1654+
description: "Failed to add a Generate Variables.",
1655+
})
1656+
async addGeneratedVariables(
1657+
@Body() content: CollectionGeneratedVariableDto,
1658+
@Res() res: FastifyReply,
1659+
@Req() request: ExtendedFastifyRequest,
1660+
) {
1661+
const user = request.user;
1662+
const response = await this.collectionService.insertGeneratedVariables(
1663+
content.collectionId,
1664+
content.generatedeVariables,
1665+
content.workspaceId,
1666+
user,
1667+
);
1668+
const responseData = new ApiResponseService(
1669+
"Generated Variables Inserted Successfully",
1670+
HttpStatusCode.OK,
1671+
response,
16031672
);
16041673
return res.status(responseData.httpStatusCode).send(responseData);
16051674
}

src/modules/workspace/payloads/collectionRequest.payload.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import {
3434
} from "@src/modules/common/models/collection.rxdb.model";
3535
import { IsObject } from 'class-validator';
3636

37+
import { VariableDto } from "@src/modules/common/models/environment.model";
38+
3739
// eslint-disable-next-line @typescript-eslint/no-unused-vars
3840

3941
export class CollectionRequestBody {
@@ -950,3 +952,30 @@ export class GeneratedVariablesDto {
950952
@IsObject()
951953
headers: Record<string, string>;
952954
}
955+
956+
export class CollectionGeneratedVariableDto {
957+
@ApiProperty({ example: "6538e910aa77d958912371f5" })
958+
@IsString()
959+
@IsNotEmpty()
960+
collectionId: string;
961+
962+
@ApiProperty({ example: "6538e910aa77d958912371f5" })
963+
@IsString()
964+
@IsNotEmpty()
965+
workspaceId: string;
966+
967+
@ApiProperty({
968+
required: true,
969+
example: [
970+
{
971+
key: "key",
972+
value: "value",
973+
checked: true,
974+
},
975+
],
976+
})
977+
@IsArray()
978+
@Type(() => VariableDto)
979+
@ValidateNested({ each: true })
980+
generatedeVariables: VariableDto[];
981+
}

0 commit comments

Comments
 (0)