-
Notifications
You must be signed in to change notification settings - Fork 6
[PROD RELEASE] - Updates & fixes #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ing or encoding Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Potential fix for code scanning alert no. 72: Incomplete string escaping or encoding
PM-2614 - Module updates -> dev
drop yarn -> develop
PS-441 Fix for processing phases in challenge update
Master -> develop sync
Automate migrations
| if (suspiciousReason) { | ||
| if (invalidDateBehavior.warn) { | ||
| console.warn(`${fileName}: record ${recordIdentifier} has ${suspiciousReason.replace('|', ' & ')} (${parsedDate.toISOString()}); strategy=${invalidDateBehavior.strategy}`); | ||
| console.warn(`${fileName}: record ${recordIdentifier} has ${suspiciousReason.replace(/\|/g, ' & ')} (${parsedDate.toISOString()}); strategy=${invalidDateBehavior.strategy}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[correctness]
The change from suspiciousReason.replace('|', ' & ') to suspiciousReason.replace(/\|/g, ' & ') is correct as it ensures all occurrences of the pipe character are replaced. However, consider verifying that suspiciousReason is always a string to avoid potential runtime errors if it is unexpectedly not a string.
|
|
||
| CMD ["node","/challenge-api/app.js"] | ||
| # Copy entrypoint script and make it executable | ||
| COPY docker/entrypoint.sh /entrypoint.sh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[security]
Consider verifying the integrity of entrypoint.sh after copying it into the image. This can help ensure that the script has not been tampered with and is safe to execute.
|
|
||
| # Use entrypoint to run migrations at startup (not build time) | ||
| # Prisma uses PostgreSQL advisory locks to prevent concurrent migrations | ||
| ENTRYPOINT ["/entrypoint.sh"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[correctness]
Using an entrypoint script to run migrations at startup can be risky if the script fails or if the database is not ready. Consider adding error handling or retry logic within entrypoint.sh to handle such cases gracefully.
Pm 2206 2nd fix
| -- Improve search responsiveness for group-constrained queries | ||
| CREATE INDEX IF NOT EXISTS "challenge_groups_gin_idx" | ||
| ON "challenges"."Challenge" | ||
| USING GIN ("groups"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
Ensure that the groups column is of a suitable data type for a GIN index, such as jsonb or array. Using GIN on unsupported types may lead to unexpected behavior or performance issues.
| @@index([updatedAt]) | ||
| @@index([typeId]) | ||
| @@index([trackId]) | ||
| @@index([groups], type: Gin, map: "challenge_groups_gin_idx") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[performance]
The use of a GIN index on the groups array field is appropriate for efficient querying of array data types in PostgreSQL. Ensure that the queries taking advantage of this index are optimized to benefit from the GIN index, as not all operations on array fields will automatically leverage it.
master -> dev - Merge pull request #39 from topcoder-platform/PM-2206-2nd-fix
feat(PM-2540): added ai workflow id to default reviewer
| /* | ||
| Warnings: | ||
| - You are about to drop the column `isAIReviewer` on the `DefaultChallengeReviewer` table. All the data in the column will be lost. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
Dropping the isAIReviewer column will result in data loss. Ensure that this data is either backed up or is no longer needed.
| */ | ||
| -- AlterTable | ||
| ALTER TABLE "DefaultChallengeReviewer" DROP COLUMN "isAIReviewer", | ||
| ADD COLUMN "aiWorkflowId" VARCHAR(14), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[maintainability]
Consider specifying a default value for the new aiWorkflowId column to avoid potential issues with null values.
| -- AlterTable | ||
| ALTER TABLE "DefaultChallengeReviewer" DROP COLUMN "isAIReviewer", | ||
| ADD COLUMN "aiWorkflowId" VARCHAR(14), | ||
| ALTER COLUMN "scorecardId" DROP NOT NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
Dropping the NOT NULL constraint on scorecardId may lead to null values being inserted, which could affect application logic. Verify that the application can handle null scorecardId values.
| timelineTemplateId String? | ||
| // Reviewer configuration (mirrors ChallengeReviewer) | ||
| scorecardId String | ||
| scorecardId String? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
Changing scorecardId from String to String? (nullable) could impact logic that assumes this field is always present. Ensure that any code relying on scorecardId being non-null is updated to handle null values appropriately.
| incrementalCoefficient Float? | ||
| opportunityType ReviewOpportunityTypeEnum? | ||
| isAIReviewer Boolean | ||
| aiWorkflowId String? @db.VarChar(14) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
The change from isAIReviewer to aiWorkflowId introduces a new field with a specific length constraint (@db.VarChar(14)). Ensure that any existing data migration scripts or database constraints are updated to accommodate this change, and verify that the application logic correctly handles the new field.
| @@index([timelineTemplateId]) | ||
| @@index([timelineTemplateId, phaseId]) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[💡 style]
The absence of a newline at the end of the file may cause issues with some tools that expect a newline. Consider adding a newline to maintain consistency and avoid potential issues.
| trackId: Joi.id().required(), | ||
| timelineTemplateId: Joi.optionalId().allow(null), | ||
| scorecardId: Joi.string().required(), | ||
| scorecardId: Joi.string().optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
Changing scorecardId from required to optional could lead to potential issues if the system relies on this field being present. Ensure that the rest of the codebase can handle scorecardId being undefined or null.
| trackId: Joi.id().required(), | ||
| timelineTemplateId: Joi.optionalId().allow(null), | ||
| scorecardId: Joi.string().required(), | ||
| scorecardId: Joi.string().optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
Changing scorecardId from required to optional could lead to potential issues if the system relies on this field being present. Ensure that the rest of the codebase can handle scorecardId being undefined or null.
| .insensitive() | ||
| .allow(null), | ||
| isAIReviewer: Joi.boolean(), | ||
| aiWorkflowId: Joi.string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[maintainability]
The aiWorkflowId is now a simple string without any conditional requirements. Consider whether this field should have validation similar to the other schemas to ensure consistency and prevent potential errors.
…-v6 into security
…thorization flows.
Security fixes and debug logging
| }; | ||
| const authMw = authenticator(_.pick(config, ["AUTH_SECRET", "VALID_ISSUERS"])); | ||
| let finished = false; | ||
| const bailoutTimer = setTimeout(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[design]
The use of a hardcoded timeout value (8000ms) for the bailoutTimer could lead to unexpected behavior if the authentication process takes longer than expected. Consider making this configurable or ensuring it aligns with expected response times.
| logger.info(`[${getSignature(req)}] Invoking ${def.controller}.${def.method}`); | ||
| try { | ||
| const resultPromise = method(req, res, next); | ||
| if (resultPromise && typeof resultPromise.then === "function") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[💡 maintainability]
The method invocation is wrapped in a try-catch block, but the error handling only logs the error and rethrows it. Consider providing more context or handling specific error types to improve error traceability and recovery.
| const app = express(); | ||
|
|
||
| // Use extended query parsing so bracket syntax like types[]=F2F is handled as arrays | ||
| app.set("query parser", "extended"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ security]
Using the 'extended' query parser can introduce security risks if not handled properly, as it allows for more complex query string parsing. Ensure that input validation and sanitization are robust to prevent potential injection attacks.
Additional checks for reviewer setup before allowing activation (PM-3…
| RESOURCE_ROLES_API_URL: | ||
| process.env.RESOURCE_ROLES_API_URL || "http://api.topcoder-dev.com/v5/resource-roles", | ||
| GROUPS_API_URL: process.env.GROUPS_API_URL || "http://localhost:4000/v5/groups", | ||
| GROUPS_API_URL: process.env.GROUPS_API_URL || "http://localhost:4000/v6/groups", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
The version change in the GROUPS_API_URL from /v5/groups to /v6/groups should be verified to ensure compatibility with the new API version. Ensure that the application logic is updated accordingly to handle any changes in the API response or behavior.
|
|
||
| describe('update challenge tests', () => { | ||
| const ensureSkipTimelineTemplate = async () => { | ||
| const templateId = config.SKIP_PROJECT_ID_BY_TIMLINE_TEMPLATE_ID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[correctness]
The variable templateId is assigned from config.SKIP_PROJECT_ID_BY_TIMLINE_TEMPLATE_ID. Ensure that this configuration value is correctly set and validated before use to avoid potential runtime errors.
| }) | ||
| const existingPhaseIds = new Set(existingPhases.map(p => p.phaseId)) | ||
| const phaseRows = [] | ||
| if (!existingPhaseIds.has(data.phase.id)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
The variable data.phase.id is used without being defined within the function scope. Ensure that data is properly initialized and accessible in this context to avoid potential reference errors.
| updatedBy: 'activation-test' | ||
| }) | ||
| } | ||
| if (!existingPhaseIds.has(data.phase2.id)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
The variable data.phase2.id is used without being defined within the function scope. Ensure that data is properly initialized and accessible in this context to avoid potential reference errors.
| id: uuid(), | ||
| name: `Activation coverage ${Date.now()}`, | ||
| description: 'Activation coverage test', | ||
| typeId: data.challenge.typeId, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗ correctness]
The typeId and trackId are set using data.challenge.typeId and data.challenge.trackId. Ensure that data.challenge is properly initialized and accessible in this context to avoid potential reference errors.
| } | ||
|
|
||
| const createActivationChallenge = async (status = ChallengeStatusEnum.NEW) => { | ||
| const timelineTemplateId = await ensureSkipTimelineTemplate() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[💡 design]
The status parameter defaults to ChallengeStatusEnum.NEW. Ensure that this default value is appropriate for all use cases of createActivationChallenge.
| status: ChallengeStatusEnum.ACTIVE | ||
| }) | ||
| } catch (e) { | ||
| should.equal(e.message.indexOf('reviewer configured') >= 0, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[maintainability]
The error message check e.message.indexOf('reviewer configured') >= 0 is a bit fragile. Consider using a more robust error handling mechanism or error codes to ensure the correct error is caught.
| } | ||
| ) | ||
| } catch (e) { | ||
| should.equal(e.message.indexOf('missing reviewers for phase(s): Review') >= 0, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[maintainability]
The error message check e.message.indexOf('missing reviewers for phase(s): Review') >= 0 is a bit fragile. Consider using a more robust error handling mechanism or error codes to ensure the correct error is caught.
Add scorecard and phase ID checks to the reviewer checks
| should.equal(e.message.indexOf('reviewers are missing required fields') >= 0, true) | ||
| return | ||
| } finally { | ||
| await prisma.challenge.delete({ where: { id: activationChallenge.id } }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[correctness]
The finally block deletes the challenge regardless of whether an error occurred. If the deletion fails, it could mask the original error. Consider moving the deletion to a separate try-catch block after handling the error to ensure the original error is not lost.
https://topcoder.atlassian.net/browse/PM-2614