Skip to content

Commit ff056de

Browse files
committed
Consumer Call Counters and Limit
1 parent 5518dba commit ff056de

4 files changed

Lines changed: 100 additions & 25 deletions

File tree

src/routes/(protected)/consumers/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@
180180
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
181181
/>
182182
</svg>
183-
Edit
183+
Details
184184
</a>
185185
<a
186186
href="/consumers/{consumer.consumer_id}/rate-limits"

src/routes/(protected)/consumers/[consumer_id]/edit/+page.server.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const logger = createLogger("EditConsumerServer");
1010
interface CallCounter {
1111
calls_made: number;
1212
reset_in_seconds: number;
13+
status?: string;
1314
}
1415

1516
interface Consumer {
@@ -94,6 +95,13 @@ export async function load(event: RequestEvent) {
9495
let scopes: Scope[] = [];
9596
let availableRoles: Role[] = [];
9697
let banks: Array<{ bank_id: string; short_name: string }> = [];
98+
let isCurrentConsumer = false;
99+
let rateLimitingInfo: {
100+
enabled?: boolean;
101+
is_active?: boolean;
102+
technology?: string;
103+
service_available?: boolean;
104+
} | null = null;
97105

98106
// Fetch consumer details
99107
try {
@@ -111,6 +119,31 @@ export async function load(event: RequestEvent) {
111119
throw error(404, "Consumer not found.");
112120
}
113121

122+
// Check if this is the current consumer (the one being used for this session)
123+
try {
124+
const currentConsumer = await obp_requests.get(
125+
`/obp/v6.0.0/consumers/current`,
126+
token,
127+
);
128+
isCurrentConsumer = currentConsumer?.consumer_id === consumerId;
129+
logger.debug(`Is current consumer: ${isCurrentConsumer}`);
130+
} catch (e) {
131+
logger.error("Error fetching current consumer:", e);
132+
// Non-fatal - continue without this info
133+
}
134+
135+
// Fetch rate limiting info
136+
try {
137+
rateLimitingInfo = await obp_requests.get(
138+
`/obp/v6.0.0/rate-limiting`,
139+
token,
140+
);
141+
logger.debug(`Rate limiting info: enabled=${rateLimitingInfo?.enabled}, active=${rateLimitingInfo?.is_active}`);
142+
} catch (e) {
143+
logger.error("Error fetching rate limiting info:", e);
144+
// Non-fatal - continue without this info
145+
}
146+
114147
// Fetch scopes for this consumer
115148
try {
116149
const scopesResponse = await obp_requests.get(
@@ -161,6 +194,8 @@ export async function load(event: RequestEvent) {
161194
userEntitlements,
162195
requiredRoles,
163196
actionRoles,
197+
isCurrentConsumer,
198+
rateLimitingInfo,
164199
};
165200
}
166201

src/routes/(protected)/consumers/[consumer_id]/edit/+page.svelte

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
const userEntitlements = data.userEntitlements || [];
1414
const requiredRoles = data.requiredRoles || [];
1515
const actionRoles = data.actionRoles || {};
16+
const isCurrentConsumer = data.isCurrentConsumer || false;
17+
const rateLimitingInfo = data.rateLimitingInfo;
1618
1719
// Helper to check if user has a specific role
1820
function hasRole(roleName: string): boolean {
@@ -98,7 +100,7 @@
98100
</script>
99101

100102
<svelte:head>
101-
<title>Edit Consumer - {consumer.app_name}</title>
103+
<title>{consumer.app_name} - Detail</title>
102104
</svelte:head>
103105

104106
<PageRoleCheck {userEntitlements} {requiredRoles}>
@@ -111,13 +113,19 @@
111113
</a>
112114
</div>
113115

114-
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2">
115-
Edit Consumer
116+
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-4">
117+
{consumer.app_name} - Detail
116118
</h1>
117119

118-
<p class="mb-6 text-gray-600 dark:text-gray-400">
119-
Manage settings and scopes for <strong>{consumer.app_name}</strong>
120-
</p>
120+
{#if isCurrentConsumer}
121+
<div class="mb-6 rounded-lg border border-blue-200 bg-blue-50 px-4 py-3 dark:border-blue-800 dark:bg-blue-900/20">
122+
<div class="flex items-center gap-2">
123+
<span class="text-blue-600 dark:text-blue-400">ℹ️</span>
124+
<span class="text-sm font-medium text-blue-800 dark:text-blue-200">This is the current consumer</span>
125+
<span class="text-xs text-blue-600 dark:text-blue-400">— the app you are using to access the API right now</span>
126+
</div>
127+
</div>
128+
{/if}
121129

122130
<!-- Error/Success Messages -->
123131
{#if form?.error}
@@ -168,18 +176,18 @@
168176
</div>
169177
{/if}
170178

171-
<!-- Consumer Details Section -->
179+
<!-- Consumer / Client Section -->
172180
<div class="mb-8 rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
173181
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">
174-
Consumer Details
182+
Consumer / Client
175183
</h2>
176184

177185
<!-- Editable fields in 2-column grid -->
178186
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 mb-4 pb-4 border-b border-gray-100 dark:border-gray-700">
179-
<!-- App Name (Editable) -->
187+
<!-- Name (Editable) -->
180188
<div>
181189
<div class="flex items-center justify-between">
182-
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400">App Name</label>
190+
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400">Name</label>
183191
{#if editingField !== "name"}
184192
<button
185193
type="button"
@@ -481,68 +489,88 @@
481489
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">
482490
API Call Counters
483491
</h2>
484-
<p class="mb-4 text-sm text-gray-500 dark:text-gray-400">
485-
Current API usage for this consumer (from Redis).
492+
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
493+
Current API usage for this consumer.
486494
</p>
495+
{#if rateLimitingInfo}
496+
<p class="mb-4 text-[11px] text-gray-400 dark:text-gray-500">
497+
Rate limiting: {rateLimitingInfo.enabled ? 'enabled' : 'disabled'}
498+
{#if rateLimitingInfo.enabled}
499+
• {rateLimitingInfo.is_active ? 'active' : 'inactive'}
500+
{#if rateLimitingInfo.technology}
501+
• backend: {rateLimitingInfo.technology}
502+
{/if}
503+
{#if rateLimitingInfo.service_available !== undefined}
504+
• service: {rateLimitingInfo.service_available ? 'available' : 'unavailable'}
505+
{/if}
506+
{/if}
507+
</p>
508+
{/if}
487509
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-4">
488510
<div class="rounded-lg bg-gray-50 p-3 dark:bg-gray-900/50">
489511
<div class="text-xs font-medium text-gray-500 dark:text-gray-400">Per Second</div>
490512
{#if consumer.call_counters?.per_second && typeof consumer.call_counters.per_second.calls_made === 'number'}
491513
<div class="mt-1 text-lg font-semibold text-gray-900 dark:text-gray-100">{consumer.call_counters.per_second.calls_made}</div>
492-
<div class="text-xs text-gray-500 dark:text-gray-400">resets in {consumer.call_counters.per_second.reset_in_seconds}s</div>
514+
<div class="text-[10px] text-gray-400 dark:text-gray-500">resets: {consumer.call_counters.per_second.reset_in_seconds}s</div>
515+
<div class="text-[10px] text-gray-400 dark:text-gray-500">{consumer.call_counters.per_second.status || ''}</div>
493516
{:else}
494517
<div class="mt-1 text-lg font-semibold text-red-600 dark:text-red-400">Err</div>
495-
<div class="text-xs text-gray-500 dark:text-gray-400">unavailable</div>
518+
<div class="text-[10px] text-gray-400 dark:text-gray-500">unavailable</div>
496519
{/if}
497520
</div>
498521
<div class="rounded-lg bg-gray-50 p-3 dark:bg-gray-900/50">
499522
<div class="text-xs font-medium text-gray-500 dark:text-gray-400">Per Minute</div>
500523
{#if consumer.call_counters?.per_minute && typeof consumer.call_counters.per_minute.calls_made === 'number'}
501524
<div class="mt-1 text-lg font-semibold text-gray-900 dark:text-gray-100">{consumer.call_counters.per_minute.calls_made}</div>
502-
<div class="text-xs text-gray-500 dark:text-gray-400">resets in {consumer.call_counters.per_minute.reset_in_seconds}s</div>
525+
<div class="text-[10px] text-gray-400 dark:text-gray-500">resets: {consumer.call_counters.per_minute.reset_in_seconds}s</div>
526+
<div class="text-[10px] text-gray-400 dark:text-gray-500">{consumer.call_counters.per_minute.status || ''}</div>
503527
{:else}
504528
<div class="mt-1 text-lg font-semibold text-red-600 dark:text-red-400">Err</div>
505-
<div class="text-xs text-gray-500 dark:text-gray-400">unavailable</div>
529+
<div class="text-[10px] text-gray-400 dark:text-gray-500">unavailable</div>
506530
{/if}
507531
</div>
508532
<div class="rounded-lg bg-gray-50 p-3 dark:bg-gray-900/50">
509533
<div class="text-xs font-medium text-gray-500 dark:text-gray-400">Per Hour</div>
510534
{#if consumer.call_counters?.per_hour && typeof consumer.call_counters.per_hour.calls_made === 'number'}
511535
<div class="mt-1 text-lg font-semibold text-gray-900 dark:text-gray-100">{consumer.call_counters.per_hour.calls_made}</div>
512-
<div class="text-xs text-gray-500 dark:text-gray-400">resets in {consumer.call_counters.per_hour.reset_in_seconds}s</div>
536+
<div class="text-[10px] text-gray-400 dark:text-gray-500">resets: {consumer.call_counters.per_hour.reset_in_seconds}s</div>
537+
<div class="text-[10px] text-gray-400 dark:text-gray-500">{consumer.call_counters.per_hour.status || ''}</div>
513538
{:else}
514539
<div class="mt-1 text-lg font-semibold text-red-600 dark:text-red-400">Err</div>
515-
<div class="text-xs text-gray-500 dark:text-gray-400">unavailable</div>
540+
<div class="text-[10px] text-gray-400 dark:text-gray-500">unavailable</div>
516541
{/if}
517542
</div>
518543
<div class="rounded-lg bg-gray-50 p-3 dark:bg-gray-900/50">
519544
<div class="text-xs font-medium text-gray-500 dark:text-gray-400">Per Day</div>
520545
{#if consumer.call_counters?.per_day && typeof consumer.call_counters.per_day.calls_made === 'number'}
521546
<div class="mt-1 text-lg font-semibold text-gray-900 dark:text-gray-100">{consumer.call_counters.per_day.calls_made}</div>
522-
<div class="text-xs text-gray-500 dark:text-gray-400">resets in {consumer.call_counters.per_day.reset_in_seconds}s</div>
547+
<div class="text-[10px] text-gray-400 dark:text-gray-500">resets: {consumer.call_counters.per_day.reset_in_seconds}s</div>
548+
<div class="text-[10px] text-gray-400 dark:text-gray-500">{consumer.call_counters.per_day.status || ''}</div>
523549
{:else}
524550
<div class="mt-1 text-lg font-semibold text-red-600 dark:text-red-400">Err</div>
525-
<div class="text-xs text-gray-500 dark:text-gray-400">unavailable</div>
551+
<div class="text-[10px] text-gray-400 dark:text-gray-500">unavailable</div>
526552
{/if}
527553
</div>
528554
<div class="rounded-lg bg-gray-50 p-3 dark:bg-gray-900/50">
529555
<div class="text-xs font-medium text-gray-500 dark:text-gray-400">Per Week</div>
530556
{#if consumer.call_counters?.per_week && typeof consumer.call_counters.per_week.calls_made === 'number'}
531557
<div class="mt-1 text-lg font-semibold text-gray-900 dark:text-gray-100">{consumer.call_counters.per_week.calls_made}</div>
532-
<div class="text-xs text-gray-500 dark:text-gray-400">resets in {consumer.call_counters.per_week.reset_in_seconds}s</div>
558+
<div class="text-[10px] text-gray-400 dark:text-gray-500">resets: {consumer.call_counters.per_week.reset_in_seconds}s</div>
559+
<div class="text-[10px] text-gray-400 dark:text-gray-500">{consumer.call_counters.per_week.status || ''}</div>
533560
{:else}
534561
<div class="mt-1 text-lg font-semibold text-red-600 dark:text-red-400">Err</div>
535-
<div class="text-xs text-gray-500 dark:text-gray-400">unavailable</div>
562+
<div class="text-[10px] text-gray-400 dark:text-gray-500">unavailable</div>
536563
{/if}
537564
</div>
538565
<div class="rounded-lg bg-gray-50 p-3 dark:bg-gray-900/50">
539566
<div class="text-xs font-medium text-gray-500 dark:text-gray-400">Per Month</div>
540567
{#if consumer.call_counters?.per_month && typeof consumer.call_counters.per_month.calls_made === 'number'}
541568
<div class="mt-1 text-lg font-semibold text-gray-900 dark:text-gray-100">{consumer.call_counters.per_month.calls_made}</div>
542-
<div class="text-xs text-gray-500 dark:text-gray-400">resets in {consumer.call_counters.per_month.reset_in_seconds}s</div>
569+
<div class="text-[10px] text-gray-400 dark:text-gray-500">resets: {consumer.call_counters.per_month.reset_in_seconds}s</div>
570+
<div class="text-[10px] text-gray-400 dark:text-gray-500">{consumer.call_counters.per_month.status || ''}</div>
543571
{:else}
544572
<div class="mt-1 text-lg font-semibold text-red-600 dark:text-red-400">Err</div>
545-
<div class="text-xs text-gray-500 dark:text-gray-400">unavailable</div>
573+
<div class="text-[10px] text-gray-400 dark:text-gray-500">unavailable</div>
546574
{/if}
547575
</div>
548576
</div>

src/routes/(protected)/consumers/[consumer_id]/rate-limits/+page.svelte

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@
287287
{formatUsageValue(callCounters, "per_second")}
288288
{#if activeRateLimits && activeRateLimits.active_per_second_rate_limit > 0}
289289
/ {formatNumber(activeRateLimits.active_per_second_rate_limit)}
290+
{:else}
291+
/ <span class="text-gray-500 dark:text-gray-400">Unlimited</span>
290292
{/if}
291293
</div>
292294
</div>
@@ -300,6 +302,8 @@
300302
{formatUsageValue(callCounters, "per_minute")}
301303
{#if activeRateLimits && activeRateLimits.active_per_minute_rate_limit > 0}
302304
/ {formatNumber(activeRateLimits.active_per_minute_rate_limit)}
305+
{:else}
306+
/ <span class="text-gray-500 dark:text-gray-400">Unlimited</span>
303307
{/if}
304308
</div>
305309
</div>
@@ -311,6 +315,8 @@
311315
{formatUsageValue(callCounters, "per_hour")}
312316
{#if activeRateLimits && activeRateLimits.active_per_hour_rate_limit > 0}
313317
/ {formatNumber(activeRateLimits.active_per_hour_rate_limit)}
318+
{:else}
319+
/ <span class="text-gray-500 dark:text-gray-400">Unlimited</span>
314320
{/if}
315321
</div>
316322
</div>
@@ -322,6 +328,8 @@
322328
{formatUsageValue(callCounters, "per_day")}
323329
{#if activeRateLimits && activeRateLimits.active_per_day_rate_limit > 0}
324330
/ {formatNumber(activeRateLimits.active_per_day_rate_limit)}
331+
{:else}
332+
/ <span class="text-gray-500 dark:text-gray-400">Unlimited</span>
325333
{/if}
326334
</div>
327335
</div>
@@ -333,6 +341,8 @@
333341
{formatUsageValue(callCounters, "per_week")}
334342
{#if activeRateLimits && activeRateLimits.active_per_week_rate_limit > 0}
335343
/ {formatNumber(activeRateLimits.active_per_week_rate_limit)}
344+
{:else}
345+
/ <span class="text-gray-500 dark:text-gray-400">Unlimited</span>
336346
{/if}
337347
</div>
338348
</div>
@@ -344,6 +354,8 @@
344354
{formatUsageValue(callCounters, "per_month")}
345355
{#if activeRateLimits && activeRateLimits.active_per_month_rate_limit > 0}
346356
/ {formatNumber(activeRateLimits.active_per_month_rate_limit)}
357+
{:else}
358+
/ <span class="text-gray-500 dark:text-gray-400">Unlimited</span>
347359
{/if}
348360
</div>
349361
</div>

0 commit comments

Comments
 (0)