Skip to content

Commit 4c71a9e

Browse files
committed
Adding Connector Trace and System Config Props
1 parent 751c556 commit 4c71a9e

8 files changed

Lines changed: 1575 additions & 20 deletions

File tree

src/lib/components/MissingRoleAlert.svelte

Lines changed: 99 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
let rolesMetadata = $state<Map<string, boolean>>(new Map());
2222
let loadingMetadata = $state(false);
2323
let selectedBankId = $state(currentBank.bankId);
24+
// "bank" = bank-scoped (send bank_id), "system" = system-wide (send empty string)
25+
let scopeChoice = $state<"bank" | "system">("bank");
2426
2527
$effect(() => {
2628
selectedBankId = currentBank.bankId;
@@ -38,6 +40,13 @@
3840
});
3941
rolesMetadata = metadataMap;
4042
43+
// Default scope based on whether role requires bank_id
44+
const anyRequiresBank = Array.from(metadataMap.values()).some((v) => v);
45+
if (!anyRequiresBank) {
46+
scopeChoice = "system";
47+
} else {
48+
scopeChoice = "bank";
49+
}
4150
} catch (error) {
4251
console.error("Failed to fetch role metadata:", error);
4352
} finally {
@@ -50,15 +59,17 @@
5059
Array.from(rolesMetadata.values()).some((requires) => requires),
5160
);
5261
53-
// The effective bank_id to use (provided prop or from currentBank)
54-
let effectiveBankId = $derived(bankId || selectedBankId);
62+
// The effective bank_id to use: empty for system-wide, otherwise provided prop or currentBank
63+
let effectiveBankId = $derived(
64+
scopeChoice === "system" ? "" : (bankId || selectedBankId)
65+
);
5566
5667
async function handleRequestClick() {
5768
if (isSubmitting) return;
5869
59-
// Validate bank selection if required
60-
if (requiresBankId && !bankId && !selectedBankId) {
61-
submitError = "Please select a bank in My Account for this role.";
70+
// Validate bank selection if bank-scoped
71+
if (scopeChoice === "bank" && !bankId && !selectedBankId) {
72+
submitError = "Please select a bank in My Account for this bank-scoped role.";
6273
return;
6374
}
6475
@@ -129,25 +140,45 @@
129140
{/each}
130141
</div>
131142

132-
{#if bankId}
143+
<!-- Scope selector: System-wide vs Bank-scoped -->
144+
{#if !bankId}
145+
<div class="scope-selector">
146+
<p class="scope-label"><strong>Role scope:</strong></p>
147+
<label class="scope-option">
148+
<input
149+
type="radio"
150+
name="scope-choice"
151+
value="system"
152+
bind:group={scopeChoice}
153+
/>
154+
<span class="scope-option-text">
155+
System-wide <span class="scope-hint">(no bank_id — for system roles)</span>
156+
</span>
157+
</label>
158+
<label class="scope-option">
159+
<input
160+
type="radio"
161+
name="scope-choice"
162+
value="bank"
163+
bind:group={scopeChoice}
164+
/>
165+
<span class="scope-option-text">
166+
Bank-scoped
167+
{#if selectedBankId}
168+
<code class="bank-code">{selectedBankId}</code>
169+
<span class="scope-hint">(from current bank selection)</span>
170+
{:else}
171+
<span class="scope-hint">— <a href="/user" style="color: #3b82f6; text-decoration: underline;">select a bank</a> first</span>
172+
{/if}
173+
</span>
174+
</label>
175+
</div>
176+
{:else}
133177
<p class="bank-info">
134178
<strong>Bank ID:</strong> <code class="bank-code">{bankId}</code>
135179
</p>
136180
{/if}
137181

138-
{#if requiresBankId && !bankId}
139-
{#if selectedBankId}
140-
<p class="bank-info">
141-
<strong>Bank ID:</strong> <code class="bank-code">{selectedBankId}</code>
142-
<span class="bank-hint">(from current bank selection)</span>
143-
</p>
144-
{:else}
145-
<div class="bank-selector">
146-
<p>This role requires a bank. Please select a bank in <a href="/user" style="color: #3b82f6; text-decoration: underline;">My Account</a> first.</p>
147-
</div>
148-
{/if}
149-
{/if}
150-
151182
{#if message}
152183
<MessageBox {message} type="error" />
153184
{/if}
@@ -475,4 +506,53 @@
475506
margin-left: 0.25rem;
476507
}
477508
509+
.scope-selector {
510+
margin: 1rem 0;
511+
padding: 0.75rem 1rem;
512+
background: rgba(59, 130, 246, 0.1);
513+
border: 1px solid rgba(59, 130, 246, 0.3);
514+
border-radius: 6px;
515+
}
516+
517+
:global([data-mode="dark"]) .scope-selector {
518+
background: rgba(59, 130, 246, 0.15);
519+
border-color: rgba(59, 130, 246, 0.4);
520+
}
521+
522+
.scope-label {
523+
margin: 0 0 0.5rem 0;
524+
font-size: 0.875rem;
525+
}
526+
527+
.scope-option {
528+
display: flex;
529+
align-items: center;
530+
gap: 0.5rem;
531+
padding: 0.375rem 0;
532+
font-size: 0.875rem;
533+
cursor: pointer;
534+
}
535+
536+
.scope-option input[type="radio"] {
537+
margin: 0;
538+
cursor: pointer;
539+
}
540+
541+
.scope-option-text {
542+
display: inline-flex;
543+
align-items: center;
544+
gap: 0.375rem;
545+
flex-wrap: wrap;
546+
}
547+
548+
.scope-hint {
549+
font-size: 0.75rem;
550+
color: #6b7280;
551+
font-weight: normal;
552+
}
553+
554+
:global([data-mode="dark"]) .scope-hint {
555+
color: rgb(var(--color-surface-400));
556+
}
557+
478558
</style>

src/lib/config/navigation.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ export function getActiveMenuItem(pathname: string) {
9999
function buildSystemItems(): NavigationItem[] {
100100
const items: NavigationItem[] = [
101101
{ href: "/system/cache", label: "Cache", iconComponent: HardDrive },
102+
{
103+
href: "/system/config-props",
104+
label: "Config Props",
105+
iconComponent: FileText,
106+
},
102107
{
103108
href: "/system/database-pool",
104109
label: "Database Pool",
@@ -180,6 +185,11 @@ function buildMetricsItems(): NavigationItem[] {
180185
label: "Connector Metrics",
181186
iconComponent: Plug,
182187
},
188+
{
189+
href: "/connector-traces",
190+
label: "Connector Traces",
191+
iconComponent: Plug,
192+
},
183193
{
184194
href: "/connector-counts",
185195
label: "Connector Counts",
@@ -446,7 +456,7 @@ export const navSections: NavigationSection[] = [
446456
{ id: "my-account", label: "My Account", iconComponent: User, items: myAccountItems, basePaths: ["/user"] },
447457
{ id: "system", label: "System", iconComponent: Server, items: systemItems, basePaths: ["/system"] },
448458
{ id: "integration", label: "Integration", iconComponent: Plug, items: integrationItems, basePaths: ["/integration"] },
449-
{ id: "metrics", label: "Metrics", iconComponent: BarChart3, items: metricsItems, basePaths: ["/metrics", "/aggregate-metrics", "/connector-metrics", "/connector-counts"] },
459+
{ id: "metrics", label: "Metrics", iconComponent: BarChart3, items: metricsItems, basePaths: ["/metrics", "/aggregate-metrics", "/connector-metrics", "/connector-traces", "/connector-counts"] },
450460
{ id: "abac", label: "ABAC", iconComponent: Lock, items: abacItems, basePaths: ["/abac"] },
451461
{ id: "products", label: "API Products", iconComponent: Package, items: productsItems, basePaths: ["/products"] },
452462
{ id: "financial-products", label: "Financial Products", iconComponent: Banknote, items: financialProductsItems, basePaths: ["/products/financial", "/products/collections"] },
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { createLogger } from "$lib/utils/logger";
2+
import { error } from "@sveltejs/kit";
3+
import type { PageServerLoad } from "./$types";
4+
5+
const logger = createLogger("ConnectorTracesPageServer");
6+
7+
export const load: PageServerLoad = async ({ locals }) => {
8+
const session = locals.session;
9+
10+
if (!session?.data?.user) {
11+
throw error(401, "Unauthorized");
12+
}
13+
14+
// Get user entitlements from session for role checking
15+
const userEntitlements = (session.data.user as any)?.entitlements?.list || [];
16+
const requiredRoles = [
17+
{
18+
role: "CanGetConnectorTrace",
19+
description: "View connector traces",
20+
action: "view connector traces",
21+
},
22+
];
23+
24+
return {
25+
userEntitlements,
26+
requiredRoles,
27+
};
28+
};

0 commit comments

Comments
 (0)