Skip to content

Commit 65bb8b7

Browse files
committed
Help with project manager access to BAs
1 parent 1680241 commit 65bb8b7

2 files changed

Lines changed: 16 additions & 14 deletions

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@
4646
Line items with unresolved project access are omitted for those callers.
4747
Projects DB access checks try both the configured connection search path and
4848
the explicit `projects` schema so deployments do not need to rely on a
49-
schema-qualified `PROJECTS_DB_URL`.
49+
schema-qualified `PROJECTS_DB_URL`. Those checks compare ids as normalized
50+
text so legacy varchar project columns and newer numeric project columns both
51+
work.
5052
Role checks are case-insensitive so mixed token casing does not block access.
5153
- Configure env: `AUTH_SECRET` or `AUTH0_URL/AUDIENCE/ISSUER` as needed.
5254

src/billing-accounts/external-budget-entry-lookup.service.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ const PROJECT_LOOKUP_TARGETS: ProjectLookupTarget[] = [
7979
* Missing DB URLs or missing referenced rows produce empty lookup mappings
8080
* rather than failing the billing account response. Projects API lookups try
8181
* both the configured connection search path and the explicit `projects`
82-
* schema, because deployment URLs are not always schema-qualified.
82+
* schema, because deployment URLs are not always schema-qualified. Project
83+
* ids are compared as normalized text so legacy varchar columns and newer
84+
* numeric columns both work.
8385
*/
8486
@Injectable()
8587
export class ExternalBudgetEntryLookupService implements OnModuleDestroy {
@@ -237,7 +239,8 @@ export class ExternalBudgetEntryLookupService implements OnModuleDestroy {
237239
* members require non-deleted membership. Callers without a billing-account
238240
* Topcoder role can require the membership to be a management/copilot
239241
* project role. The Projects DB table lookup is tolerant of URLs with or
240-
* without a `schema=projects` search path.
242+
* without a `schema=projects` search path, and of project id columns stored
243+
* as either numeric or varchar values.
241244
*
242245
* @param billingAccountId Topcoder billing-account id from the detail route.
243246
* @param userId Topcoder user id from the authenticated caller; optional
@@ -299,12 +302,10 @@ export class ExternalBudgetEntryLookupService implements OnModuleDestroy {
299302
SELECT true AS "hasAccess"
300303
FROM ${target.projectsTable} project
301304
INNER JOIN ${target.projectMembersTable} project_member
302-
ON project_member."projectId" = project."id"
303-
WHERE project."billingAccountId" = ${BigInt(
304-
normalizedBillingAccountId,
305-
)}
305+
ON project_member."projectId"::text = project."id"::text
306+
WHERE project."billingAccountId"::text = ${normalizedBillingAccountId}
306307
AND project."deletedAt" IS NULL
307-
AND project_member."userId" = ${BigInt(membershipUserId)}
308+
AND project_member."userId"::text = ${membershipUserId}
308309
${projectRoleFilter}
309310
AND project_member."deletedAt" IS NULL
310311
LIMIT 1
@@ -349,7 +350,7 @@ export class ExternalBudgetEntryLookupService implements OnModuleDestroy {
349350
Prisma.sql`
350351
SELECT true AS "hasAccess"
351352
FROM ${target.projectsTable} project
352-
WHERE project."billingAccountId" = ${BigInt(billingAccountId)}
353+
WHERE project."billingAccountId"::text = ${billingAccountId}
353354
AND project."deletedAt" IS NULL
354355
LIMIT 1
355356
`,
@@ -601,7 +602,8 @@ export class ExternalBudgetEntryLookupService implements OnModuleDestroy {
601602
* @param projectIds Candidate project ids from line-item references.
602603
* @returns Set of candidate project ids with an active project member row.
603604
* The lookup checks both the configured search path and the explicit
604-
* `projects` schema.
605+
* `projects` schema. Id comparisons are text-normalized so both legacy
606+
* varchar columns and newer numeric columns work.
605607
*/
606608
private async getAccessibleProjectIdsForUser(
607609
userId: string,
@@ -635,10 +637,8 @@ export class ExternalBudgetEntryLookupService implements OnModuleDestroy {
635637
Prisma.sql`
636638
SELECT DISTINCT "projectId"::text AS "projectId"
637639
FROM ${target.projectMembersTable}
638-
WHERE "userId" = ${BigInt(userId)}
639-
AND "projectId" IN (${Prisma.join(
640-
uniqueProjectIds.map((projectId) => BigInt(projectId)),
641-
)})
640+
WHERE "userId"::text = ${userId}
641+
AND "projectId"::text IN (${Prisma.join(uniqueProjectIds)})
642642
AND "deletedAt" IS NULL
643643
`,
644644
);

0 commit comments

Comments
 (0)