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
22 changes: 0 additions & 22 deletions .github/workflows/code_reviewer.yml

This file was deleted.

24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- Endpoints:
- `GET /billing-accounts`
- `POST /billing-accounts`
- `GET /billing-accounts/:billingAccountId` (includes locked/consumed arrays + budget totals; line items expose `amount`, `date`, `externalId`, `externalType`, `externalName`, and `challengeId` only for challenge compatibility; copilot, Project Manager, and Talent Manager callers only receive line items for projects they belong to)
- `GET /billing-accounts/:billingAccountId` (includes locked/consumed arrays + budget totals; line items expose `amount`, `date`, `externalId`, `externalType`, `externalName`, and `challengeId` only for challenge compatibility; copilot, project-scoped, and Talent Manager callers only receive line items for projects they belong to; copilot-only callers receive `memberPaymentsRemaining` and per-line-item `memberPaymentAmount` instead of raw `markup`)
- `GET /billing-accounts/users/:userId` (list billing accounts accessible by the given Topcoder user ID — resolved via Salesforce resource object)
- `PATCH /billing-accounts/:billingAccountId`
- `PATCH /billing-accounts/:billingAccountId/lock-amount` (challenge-only typed reference; non-negative amount; 0 amount = unlock; rejects insufficient remaining funds)
Expand All @@ -27,12 +27,28 @@
- Billing-account management endpoints accept `administrator`, `Talent Manager`,
and `Topcoder Talent Manager` JWT roles; read-only billing-account lookups
also continue to allow `copilot`, `Project Manager`, and `Topcoder Project Manager`.
Project Managers are restricted to billing accounts granted to their own
user id on `GET /billing-accounts` and `GET /billing-accounts/:billingAccountId`.
On billing-account detail responses, copilot, Project Manager, and Talent
The detail endpoint additionally accepts `Topcoder User` so project-member
callers from Work can be authorized by project membership.
Project-scoped billing-account readers are restricted to billing accounts
granted to their own user id on `GET /billing-accounts`. On
`GET /billing-accounts/:billingAccountId`, Project Manager callers can read
billing accounts granted to their own user id or assigned to non-deleted
projects. Plain `Topcoder User` project-member callers need a
management or copilot project role for the project fallback.
Copilot-only callers receive billing-account responses with `markup` omitted
and `memberPaymentsRemaining` derived server-side as total remaining minus
the total remaining markup amount. Billing-account detail
responses for copilots also include per-line-item `memberPaymentAmount` values
that remove the markup fee from locked and consumed amounts. On detail
responses, copilot, project-scoped, and Talent
Manager callers only receive locked/consumed line items whose challenge or
engagement project maps to an active `project_members` row for their user id.
Line items with unresolved project access are omitted for those callers.
Projects DB access checks try both the configured connection search path and
the explicit `projects` schema so deployments do not need to rely on a
schema-qualified `PROJECTS_DB_URL`. Those checks compare ids as normalized
text so legacy varchar project columns and newer numeric project columns both
work.
Role checks are case-insensitive so mixed token casing does not block access.
- Configure env: `AUTH_SECRET` or `AUTH0_URL/AUDIENCE/ISSUER` as needed.

Expand Down
1 change: 1 addition & 0 deletions src/auth/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export const ADMIN_ROLE = "administrator";
export const COPILOT_ROLE = "copilot";
export const PROJECT_MANAGER_ROLE = "Project Manager";
export const TOPCODER_PROJECT_MANAGER_ROLE = "Topcoder Project Manager";
export const TOPCODER_USER_ROLE = "Topcoder User";
export const TALENT_MANAGER_ROLE = "Talent Manager";
export const TOPCODER_TALENT_MANAGER_ROLE = "Topcoder Talent Manager";
14 changes: 10 additions & 4 deletions src/billing-accounts/billing-accounts.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
PROJECT_MANAGER_ROLE,
TALENT_MANAGER_ROLE,
TOPCODER_PROJECT_MANAGER_ROLE,
TOPCODER_USER_ROLE,
TOPCODER_TALENT_MANAGER_ROLE,
} from "../auth/constants";
import type { Request } from "express";
Expand Down Expand Up @@ -58,6 +59,11 @@ const BILLING_ACCOUNT_PROJECT_READ_ROLES = [
TOPCODER_PROJECT_MANAGER_ROLE,
];

const BILLING_ACCOUNT_DETAIL_READ_ROLES = [
...BILLING_ACCOUNT_PROJECT_READ_ROLES,
TOPCODER_USER_ROLE,
];

const BILLING_ACCOUNT_MANAGE_ROLES = [
ADMIN_ROLE,
TALENT_MANAGER_ROLE,
Expand All @@ -83,7 +89,7 @@ export class BillingAccountsController {
buildOperationDoc({
summary: "List billing accounts",
description:
"Retrieve billing accounts with optional filters, sorting, and pagination. Project Managers are limited to billing accounts granted to their own user id.",
"Retrieve billing accounts with optional filters, sorting, and pagination. Project Managers are limited to billing accounts granted to their own user id. Copilot-only callers receive copilot-safe budget data without the raw markup field.",
jwtRoles: BILLING_ACCOUNT_PROJECT_READ_ROLES,
m2mScopes: [SCOPES.READ_BA, SCOPES.ALL_BA],
}),
Expand Down Expand Up @@ -167,14 +173,14 @@ export class BillingAccountsController {

@Get(":billingAccountId")
@UseGuards(RolesGuard, ScopesGuard)
@Roles(...BILLING_ACCOUNT_PROJECT_READ_ROLES)
@Roles(...BILLING_ACCOUNT_DETAIL_READ_ROLES)
@Scopes(SCOPES.READ_BA, SCOPES.ALL_BA)
@ApiOperation(
buildOperationDoc({
summary: "Get a billing account",
description:
"Fetch a billing account by its identifier, including budget, client data, and normalized locked/consumed line items. Line items include amount, date, externalId, externalType, externalName, and challengeId only for legacy challenge compatibility. Project Managers can read only billing accounts granted to them. Copilot, Project Manager, and Talent Manager callers only receive locked/consumed line items for projects they belong to.",
jwtRoles: BILLING_ACCOUNT_PROJECT_READ_ROLES,
"Fetch a billing account by its identifier, including budget, client data, and normalized locked/consumed line items. Line items include amount, date, externalId, externalType, externalName, and challengeId only for legacy challenge compatibility. Project Managers can read billing accounts granted to them or assigned to non-deleted projects; plain Topcoder User project members need an allowed project billing-account role. Copilot, Project Manager, Topcoder User, and Talent Manager callers only receive locked/consumed line items for projects they belong to. Copilot-only callers receive copilot-safe budget data without the raw markup field, including memberPaymentsRemaining and per-line-item memberPaymentAmount values.",
jwtRoles: BILLING_ACCOUNT_DETAIL_READ_ROLES,
m2mScopes: [SCOPES.READ_BA, SCOPES.ALL_BA],
}),
)
Expand Down
Loading
Loading