Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ workflows:
only:
- develop
- hotfix/deploy
- pm-2456
- pm-2539

# Production builds are exectuted only on tagged commits to the testing
# master branch.
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/trivy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Trivy Scanner

permissions:
contents: read
security-events: write
on:
push:
branches:
- main
- dev
pull_request:
jobs:
trivy-scan:
name: Use Trivy
runs-on: ubuntu-24.04

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
Consider using a stable version of the runner, such as ubuntu-latest, instead of ubuntu-24.04 to ensure compatibility and reduce maintenance overhead when new Ubuntu versions are released.

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Run Trivy scanner in repo mode
uses: aquasecurity/trivy-action@0.33.1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
The Trivy action version 0.33.1 is quite specific. Consider using a more flexible versioning approach, such as v0, to automatically receive minor updates and patches, which can include important security and performance improvements.

with:
scan-type: "fs"
ignore-unfixed: true
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH,UNKNOWN"
scanners: vuln,secret,misconfig,license
github-pat: ${{ secrets.GITHUB_TOKEN }}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ security]
Ensure that the GITHUB_TOKEN used here has the necessary permissions for the actions being performed, especially since it is being used to write security events.


- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: "trivy-results.sarif"
3 changes: 2 additions & 1 deletion config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ module.exports = {
},

AUTOMATED_TESTING_NAME_PREFIX: process.env.AUTOMATED_TESTING_NAME_PREFIX || 'POSTMANE2E-',
TOPCROWD_CHALLENGE_TEMPLATE_ID: process.env.TOPCROWD_CHALLENGE_TEMPLATE_ID || '517e76b0-8824-4e72-9b48-a1ebde1793a8'
TOPCROWD_CHALLENGE_TEMPLATE_ID: process.env.TOPCROWD_CHALLENGE_TEMPLATE_ID || '517e76b0-8824-4e72-9b48-a1ebde1793a8',
RESOURCE_SERVICE_PRISMA_TIMEOUT: process.env.RESOURCE_SERVICE_PRISMA_TIMEOUT ? parseInt(process.env.RESOURCE_SERVICE_PRISMA_TIMEOUT, 10) : 10000

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Consider using Number() instead of parseInt() for parsing RESOURCE_SERVICE_PRISMA_TIMEOUT. parseInt() can produce unexpected results when the environment variable is not a valid integer, as it parses until a non-numeric character is encountered. Number() will return NaN for invalid inputs, which might be safer depending on how this value is used.

}
3 changes: 2 additions & 1 deletion config/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ module.exports = {
COPILOT_CREDENTIALS_PASSWORD: process.env.COPILOT_CREDENTIALS_PASSWORD || '',
USER_CREDENTIALS_USERNAME: process.env.USER_CREDENTIALS_USERNAME || '',
USER_CREDENTIALS_PASSWORD: process.env.USER_CREDENTIALS_PASSWORD || '',
AUTOMATED_TESTING_REPORTERS_FORMAT: process.env.AUTOMATED_TESTING_REPORTERS_FORMAT || ['cli', 'html']
AUTOMATED_TESTING_REPORTERS_FORMAT: process.env.AUTOMATED_TESTING_REPORTERS_FORMAT || ['cli', 'html'],
RESOURCE_SERVICE_PRISMA_TIMEOUT: process.env.RESOURCE_SERVICE_PRISMA_TIMEOUT ? parseInt(process.env.RESOURCE_SERVICE_PRISMA_TIMEOUT, 10) : 10000

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Consider using Number() instead of parseInt() for parsing RESOURCE_SERVICE_PRISMA_TIMEOUT to ensure the entire string is converted to a number. parseInt() can produce unexpected results if the environment variable contains non-numeric characters.

}
2 changes: 2 additions & 0 deletions env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ export DATABASE_URL="postgresql://johndoe:mypassword@localhost:5532/resourceapi?
export MEMBER_DB_URL="postgresql://johndoe:mypassword@localhost:5632/memberdb"

export CHALLENGE_DB_URL="postgresql://johndoe:mypassword@localhost:5732/challengedb"

export RESOURCE_SERVICE_PRISMA_TIMEOUT=10000

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 style]
Consider adding a newline at the end of the file. While this is not a correctness issue, it is a common convention that can prevent potential issues with certain tools or version control systems.

7 changes: 6 additions & 1 deletion migrator/src/clients/prismaClient.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
const { PrismaClient } = require('@prisma/client');
const config = require('config')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
The config module is imported without specifying which configuration file or environment it is loading from. Ensure that the configuration is correctly set up for different environments (e.g., development, production) to avoid runtime issues.


const prisma = new PrismaClient();
const prisma = new PrismaClient({
transactionOptions: {
timeout: config.MEMBER_SERVICE_PRISMA_TIMEOUT,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Ensure that config.MEMBER_SERVICE_PRISMA_TIMEOUT is defined and has a sensible default value. If this value is not set or is incorrect, it could lead to unexpected behavior in the application.

},
});

module.exports = prisma;

14 changes: 14 additions & 0 deletions prisma/migrations/20251023102730_performance_indices/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- CreateIndex
CREATE INDEX "resource-roleId-index" ON "resources"."Resource"("roleId");

-- CreateIndex
CREATE INDEX "resource-memberIdChallengeId-index" ON "resources"."Resource"("memberId", "challengeId");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
Consider the order of columns in the index resource-memberIdChallengeId-index. If queries often filter or sort by challengeId alone, it might be beneficial to reverse the order of columns to optimize those queries.


-- CreateIndex
CREATE INDEX "resourcerole-isActive-index" ON "resources"."ResourceRole"("isActive");

-- CreateIndex
CREATE INDEX "resourcerole-isActiveSelfObtainable-index" ON "resources"."ResourceRole"("isActive", "selfObtainable");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
Ensure that the combination of isActive and selfObtainable in the index resourcerole-isActiveSelfObtainable-index aligns with the query patterns. If queries frequently filter by selfObtainable alone, consider the impact on performance.


-- CreateIndex
CREATE INDEX "resourcerolephasedependency-resourceRoleId-index" ON "resources"."ResourceRolePhaseDependency"("resourceRoleId");
7 changes: 6 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ model ResourceRole {
resources Resource[]
resourceRolePhaseDependencies ResourceRolePhaseDependency[]

// Index for faster search
// Indexes for faster search
@@index([nameLower], map: "resourcerole-nameLower-index")
@@index([isActive], map: "resourcerole-isActive-index")
@@index([isActive, selfObtainable], map: "resourcerole-isActiveSelfObtainable-index")
}

model Resource {
Expand All @@ -46,6 +48,8 @@ model Resource {
// Indexes for faster searches
@@index([challengeId, memberId], map: "resource-challengeIdMemberId-index")
@@index([memberId, roleId], map: "resource-memberIdRoleId-index")
@@index([roleId], map: "resource-roleId-index")
@@index([memberId, challengeId], map: "resource-memberIdChallengeId-index")
}

model ResourceRolePhaseDependency {
Expand All @@ -60,4 +64,5 @@ model ResourceRolePhaseDependency {
resourceRole ResourceRole @relation(fields: [resourceRoleId], references: [id])

@@unique([phaseId, resourceRoleId], map: "resourcerolephase-phaseId-resourceRoleId-unique")
@@index([resourceRoleId], map: "resourcerolephasedependency-resourceRoleId-index")
}