feat(billing): scope parameter on /view/statistics endpoint
- New query parameter scope: personal/mandate/all - personal: filters to only current user's transactions (ignores admin role) - mandate: filters by mandateId parameter - all: existing RBAC-filtered behavior (default) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
e24ef42617
commit
3777839a5c
1 changed files with 27 additions and 14 deletions
|
|
@ -989,16 +989,17 @@ def getUserViewStatistics(
|
||||||
period: str = Query(default="month", description="Period: 'day' or 'month'"),
|
period: str = Query(default="month", description="Period: 'day' or 'month'"),
|
||||||
year: int = Query(default=None, description="Year"),
|
year: int = Query(default=None, description="Year"),
|
||||||
month: Optional[int] = Query(None, description="Month (1-12, required for period='day')"),
|
month: Optional[int] = Query(None, description="Month (1-12, required for period='day')"),
|
||||||
|
scope: str = Query(default="all", description="Scope: 'personal' (own costs only), 'mandate' (filter by mandateId), 'all' (RBAC-filtered)"),
|
||||||
|
mandateId: Optional[str] = Query(None, description="Mandate ID filter (used with scope='mandate')"),
|
||||||
ctx: RequestContext = Depends(getRequestContext)
|
ctx: RequestContext = Depends(getRequestContext)
|
||||||
) -> ViewStatisticsResponse:
|
) -> ViewStatisticsResponse:
|
||||||
"""
|
"""
|
||||||
Get aggregated usage statistics across all user's mandates.
|
Get aggregated usage statistics across all user's mandates.
|
||||||
|
|
||||||
RBAC filtering:
|
Scope:
|
||||||
- SysAdmin: statistics across all mandates
|
- personal: only the current user's own transactions (ignores admin role)
|
||||||
- Mandate-Admin: statistics for mandates they administrate
|
- mandate: transactions for a specific mandate (requires mandateId parameter)
|
||||||
- Feature-Instance-Admin: statistics for their feature instances
|
- all: RBAC-filtered (SysAdmin sees everything, admin sees mandate, user sees own)
|
||||||
- Regular user: only their own usage statistics
|
|
||||||
|
|
||||||
- period='month': returns monthly time series for the given year
|
- period='month': returns monthly time series for the given year
|
||||||
- period='day': returns daily time series for the given month/year
|
- period='day': returns daily time series for the given month/year
|
||||||
|
|
@ -1015,22 +1016,34 @@ def getUserViewStatistics(
|
||||||
billingInterface = getBillingInterface(ctx.user, ctx.mandateId)
|
billingInterface = getBillingInterface(ctx.user, ctx.mandateId)
|
||||||
|
|
||||||
# Evaluate RBAC scope
|
# Evaluate RBAC scope
|
||||||
scope = _getBillingDataScope(ctx.user)
|
rbacScope = _getBillingDataScope(ctx.user)
|
||||||
|
|
||||||
# Determine mandate IDs for data loading
|
# Determine mandate IDs for data loading
|
||||||
if scope.isGlobalAdmin:
|
if rbacScope.isGlobalAdmin:
|
||||||
mandateIds = None
|
loadMandateIds = None
|
||||||
else:
|
else:
|
||||||
mandateIds = scope.adminMandateIds + scope.memberMandateIds
|
loadMandateIds = rbacScope.adminMandateIds + rbacScope.memberMandateIds
|
||||||
if not mandateIds:
|
if not loadMandateIds:
|
||||||
logger.warning("No mandate IDs found for user")
|
logger.warning("No mandate IDs found for user")
|
||||||
return ViewStatisticsResponse()
|
return ViewStatisticsResponse()
|
||||||
|
|
||||||
# Get all transactions
|
# Scope=mandate: restrict to specific mandate
|
||||||
allTransactions = billingInterface.getUserTransactionsForMandates(mandateIds, limit=10000)
|
if scope == "mandate" and mandateId:
|
||||||
|
loadMandateIds = [mandateId]
|
||||||
|
|
||||||
# Apply RBAC filter
|
# Get all transactions
|
||||||
allTransactions = _filterTransactionsByScope(allTransactions, scope)
|
allTransactions = billingInterface.getUserTransactionsForMandates(loadMandateIds, limit=10000)
|
||||||
|
|
||||||
|
# Apply RBAC filter (respects admin/user roles)
|
||||||
|
allTransactions = _filterTransactionsByScope(allTransactions, rbacScope)
|
||||||
|
|
||||||
|
# Scope=personal: further filter to only own transactions
|
||||||
|
if scope == "personal":
|
||||||
|
userId = str(ctx.user.id)
|
||||||
|
allTransactions = [
|
||||||
|
t for t in allTransactions
|
||||||
|
if (t.get("createdByUserId") or t.get("userId")) == userId
|
||||||
|
]
|
||||||
|
|
||||||
logger.info(f"View statistics: {len(allTransactions)} RBAC-filtered transactions for period={period}, year={year}, month={month}")
|
logger.info(f"View statistics: {len(allTransactions)} RBAC-filtered transactions for period={period}, year={year}, month={month}")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue