Skip to content

Comments

[PROD RELASE] - Access & fixes#1470

Merged
kkartunov merged 21 commits intomasterfrom
dev
Feb 13, 2026
Merged

[PROD RELASE] - Access & fixes#1470
kkartunov merged 21 commits intomasterfrom
dev

Conversation

@kkartunov
Copy link
Collaborator

@kkartunov kkartunov commented Feb 12, 2026

@kkartunov kkartunov requested a review from jmgasper as a code owner February 12, 2026 16:27

if (authProfile
.roles?.some(
role => EMAIL_VIEW_ROLES.some(allowed => role.toLowerCase() === allowed.toLowerCase()),

Choose a reason for hiding this comment

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

[💡 performance]
Consider using includes instead of some for checking role membership, as it can improve readability and performance slightly when checking for a single role match.

const Phones: FC<PhonesProps> = (props: PhonesProps) => {
const canEdit: boolean = props.authProfile?.handle === props.profile.handle
const canSeePhonesValue: boolean = canSeePhones(props.authProfile, props.profile)
const canSeeEmailValue: boolean = canSeeEmail(props.authProfile, props.profile)

Choose a reason for hiding this comment

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

[❗❗ security]
The canSeeEmail function is newly introduced here. Ensure that this function is properly tested to verify that it correctly determines email visibility based on the provided profiles. This is important to prevent unauthorized access to sensitive information.

const cannotDownloadSubmission = (
!canViewSubmissions && String(submission.memberId) === String(loginUserInfo?.userId)
)
const isRestricted = isRestrictedBase || failedScan || !cannotDownloadSubmission

Choose a reason for hiding this comment

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

[❗❗ correctness]
The logic for isRestricted seems incorrect. The condition !cannotDownloadSubmission should be cannotDownloadSubmission to ensure that the restriction is applied when the user cannot download the submission.


const { canViewAllSubmissions }: UseRolePermissionsResult = useRolePermissions()

const isCompletedDesignChallenge = useMemo(() => {

Choose a reason for hiding this comment

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

[💡 readability]
The isCompletedDesignChallenge function could be simplified by directly returning the boolean expression without the if statement. This would improve readability.

)
}, [challengeInfo])

const isSubmissionsViewable = useMemo(() => {

Choose a reason for hiding this comment

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

[⚠️ correctness]
The isSubmissionsViewable function uses some to check metadata, which is efficient. However, ensure that metadata is always an array to avoid potential runtime errors.

return true
}, [isCompletedDesignChallenge, isSubmissionsViewable, canViewAllSubmissions])

const isSubmissionNotViewable = (submission: SubmissionRow): boolean => (

Choose a reason for hiding this comment

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

[⚠️ correctness]
The isSubmissionNotViewable function compares memberId and userId as strings. Ensure these values are always strings to prevent unexpected behavior.

getRestrictionMessageForMember,
}: UseSubmissionDownloadAccessResult = useSubmissionDownloadAccess()

const isCompletedDesignChallenge = useMemo(() => {

Choose a reason for hiding this comment

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

[⚠️ performance]
The use of useMemo here is appropriate for optimizing performance by memoizing the result of the computation. However, ensure that challengeInfo is a stable reference or consider using a deep comparison to avoid unnecessary recalculations.

)
}, [challengeInfo])

const isSubmissionsViewable = useMemo(() => {

Choose a reason for hiding this comment

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

[⚠️ performance]
The useMemo hook is used to memoize the result of checking if submissions are viewable. Ensure that challengeInfo.metadata is a stable reference or consider using a deep comparison to avoid unnecessary recalculations.

.toLowerCase() === 'true')
}, [challengeInfo])

const canViewSubmissions = useMemo(() => {

Choose a reason for hiding this comment

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

[⚠️ performance]
The useMemo hook is used to determine if submissions can be viewed. Ensure that all dependencies (isCompletedDesignChallenge, isSubmissionsViewable, canViewAllSubmissions) are stable references or consider using a deep comparison to avoid unnecessary recalculations.

const isRestrictedForRow = isRestrictedBase || failedScan
const tooltipMessage = failedScan
const isDownloadDisabled = (
!canViewSubmissions && String(data.memberId) !== String(loginUserInfo?.userId)

Choose a reason for hiding this comment

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

[💡 readability]
The condition String(data.memberId) !== String(loginUserInfo?.userId) could be simplified by ensuring data.memberId and loginUserInfo?.userId are of the same type before comparison, which would improve readability and potentially avoid unnecessary type conversion.

)
}, [challengeInfo])

const isSubmissionsViewable = useMemo(() => {

Choose a reason for hiding this comment

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

[⚠️ correctness]
The isSubmissionsViewable function uses challengeInfo.metadata.some() to check for a specific metadata entry. Ensure that metadata is always an array to avoid potential runtime errors. Consider adding a type guard or defaulting to an empty array if metadata might be undefined.

.toLowerCase() === 'true')
}, [challengeInfo])

const canViewSubmissions = useMemo(() => {

Choose a reason for hiding this comment

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

[⚠️ design]
The canViewSubmissions logic assumes that if a challenge is not a completed design challenge, submissions are always viewable. Verify that this assumption aligns with the intended business logic, as it might lead to unintended access if the conditions change.

: data.virusScan
const failedScan = normalizedVirusScan === false
const isDownloadDisabled = (
!canViewSubmissions && String(data.memberId) !== String(loginUserInfo?.userId)

Choose a reason for hiding this comment

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

[⚠️ correctness]
The isDownloadDisabled condition checks if data.memberId is not equal to loginUserInfo?.userId. Ensure that both memberId and userId are consistently formatted (e.g., trimmed, lowercased) to avoid false negatives due to formatting differences.

}, [challengeInfo])

const canViewSubmissions = useMemo(() => {
if (isCompletedDesignChallenge) {

Choose a reason for hiding this comment

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

[💡 maintainability]
The canViewSubmissions logic could be simplified by returning canViewAllSubmissions || isSubmissionsViewable directly, as the isCompletedDesignChallenge check is redundant when canViewAllSubmissions or isSubmissionsViewable is true.

}, [isCompletedDesignChallenge, isSubmissionsViewable, canViewAllSubmissions])

const isSubmissionNotViewable = (submission: SubmissionRow): boolean => (
!canViewSubmissions && String(submission.memberId) !== String(loginUserInfo?.userId)

Choose a reason for hiding this comment

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

[⚠️ correctness]
The function isSubmissionNotViewable uses String(submission.memberId) !== String(loginUserInfo?.userId), which could potentially lead to incorrect comparisons if memberId or userId are not strings. Consider ensuring these values are always strings before comparison.

!canViewSubmissions && String(submission.memberId) !== String(loginUserInfo?.userId)
)

const aggregatedSubmissionRows = useMemo<SubmissionRow[]>(

Choose a reason for hiding this comment

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

[❗❗ correctness]
The isSubmissionNotViewable function is defined but not used in the aggregatedSubmissionRows computation. Ensure that the logic for filtering submissions based on viewability is correctly integrated, as this might affect the correctness of the displayed data.

}))),
[aggregatedRows, filterFunc, canViewSubmissions, loginUserInfo?.userId],
})),
[aggregatedRows],

Choose a reason for hiding this comment

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

[❗❗ correctness]
The dependency array for aggregatedSubmissionRows is missing dependencies related to submission viewability logic, such as canViewSubmissions and loginUserInfo?.userId. This could lead to stale data being used if these values change.

)

const isSubmissionNotViewable = (submission: Screening): boolean => (
!canViewSubmissions && String(submission.memberId) !== String(loginUserInfo?.userId)

Choose a reason for hiding this comment

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

[⚠️ correctness]
The function isSubmissionNotViewable checks if submission.memberId is not equal to loginUserInfo?.userId. Ensure that both submission.memberId and loginUserInfo?.userId are always defined and of the same type to avoid unexpected behavior. Consider adding type checks or default values if necessary.

}, [challengeInfo])

const canViewSubmissions = useMemo(() => {
if (isCompletedDesignChallenge) {

Choose a reason for hiding this comment

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

[⚠️ correctness]
In the canViewSubmissions useMemo hook, the logic checks isCompletedDesignChallenge and isSubmissionsViewable to determine the return value. Ensure that these conditions cover all possible states of challengeInfo to avoid returning incorrect permissions.

* Table Winners.
*/
import { FC, useCallback, useContext, useMemo } from 'react'
import { FC, useContext, useMemo } from 'react'

Choose a reason for hiding this comment

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

[⚠️ maintainability]
The useCallback import has been removed, but the filterFunc function that used it has also been removed. Ensure that this change is intentional and that filterFunc is no longer needed.

@@ -310,11 +308,11 @@ export const TableWinners: FC<Props> = (props: Props) => {
)}
>
{isTablet ? (

Choose a reason for hiding this comment

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

[❗❗ correctness]
The winnerData variable has been removed and replaced with datas directly in the TableMobile and Table components. Ensure that the filtering logic previously applied by filterFunc is no longer required, as this could affect the data displayed in the table.

? ownedMemberIds.has(submission.memberId)
: false
const isOwnershipRestricted = shouldRestrictSubmitterToOwnSubmission && !isOwnedSubmission
const isSubmissionNotAllowedToView = (isSubmissionNotViewable && isSubmissionNotViewable(submission))

Choose a reason for hiding this comment

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

[❗❗ correctness]
The function isSubmissionNotViewable is used as both a boolean and a function. Ensure that isSubmissionNotViewable is indeed a function and not a boolean value to avoid runtime errors.

? downloadOwnSubmissionTooltip
: (isSubmissionDownloadRestricted && restrictionMessage) || undefined

if (isSubmissionNotAllowedToView) {

Choose a reason for hiding this comment

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

[⚠️ maintainability]
The reassignment of tooltipContent here may lead to unexpected behavior if isSubmissionNotAllowedToView is true. Consider restructuring the logic to ensure tooltipContent is set correctly based on all conditions.

Challenges -
{' '}
{role}
{skillEventTypeMap[role as keyof typeof skillEventTypeMap] ?? ''}

Choose a reason for hiding this comment

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

[⚠️ correctness]
Using as keyof typeof skillEventTypeMap for type assertion can be risky if role is not guaranteed to be a key in skillEventTypeMap. Consider adding a runtime check or handling the case where role is not a valid key to avoid potential runtime errors.

@kkartunov kkartunov changed the title [PROD RELASE] [PROD RELASE] - Access & fixes Feb 13, 2026
)
// Check if user has admin roles or talent manager
if (
authProfile.roles?.some(role => [

Choose a reason for hiding this comment

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

[⚠️ correctness]
The use of role.toLowerCase() assumes that all roles are case-insensitive. If UserRole.talentManager or any role in ADMIN_ROLES is case-sensitive, this could lead to incorrect behavior. Consider ensuring that all roles are consistently cased or explicitly handle case sensitivity.

authProfile.roles?.some(role => [
UserRole.talentManager,
...ADMIN_ROLES,
].map(r => r.toLowerCase())

Choose a reason for hiding this comment

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

[⚠️ performance]
The use of map followed by includes could be optimized by using some with a case-insensitive comparison directly. This avoids creating an intermediate array and improves performance slightly.


// Don't render anything if user cannot edit AND cannot see any contact info
const hasContactInfo = props.profile?.email || phones.length > 0
if (!canEdit && (!canSeeEmailValue || !hasContactInfo)) {

Choose a reason for hiding this comment

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

[❗❗ correctness]
The condition !canSeeEmailValue || !hasContactInfo might not work as intended if the user can see the email but there is no contact info. Consider changing the condition to !canSeeEmailValue && !hasContactInfo to ensure that the component is only hidden when both conditions are false.

@kkartunov kkartunov merged commit bf6a11e into master Feb 13, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants