Skip to content

Commit fc8a256

Browse files
committed
support page and Dynamic Entity field writeRole and git commit on about
pages
1 parent 8d91923 commit fc8a256

14 files changed

Lines changed: 398 additions & 25 deletions

File tree

.github/workflows/build_container_image.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ jobs:
1717
- name: Build the Docker images with latest tag
1818
run: |
1919
echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin docker.io
20-
docker build . -f Dockerfile_portal --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/obp-portal:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/obp-portal:main --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/obp-portal:latest
21-
docker build . -f Dockerfile_apimanager --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/api-manager-ii:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/api-manager-ii:main --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/api-manager-ii:latest
20+
docker build . -f Dockerfile_portal --build-arg GIT_COMMIT=$GITHUB_SHA --build-arg GIT_BRANCH=${{ github.ref_name }} --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/obp-portal:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/obp-portal:main --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/obp-portal:latest
21+
docker build . -f Dockerfile_apimanager --build-arg GIT_COMMIT=$GITHUB_SHA --build-arg GIT_BRANCH=${{ github.ref_name }} --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/api-manager-ii:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/api-manager-ii:main --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/api-manager-ii:latest
2222
docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/obp-portal --all-tags
2323
docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/api-manager-ii --all-tags
2424
echo docker obp-portal with latest tag done

Dockerfile_apimanager

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,18 @@ ARG OBP_OAUTH_CLIENT_SECRET
2222
ARG APP_CALLBACK_URL
2323
ARG ORIGIN
2424

25+
# Build provenance: the .git directory is not copied into the image, so the commit
26+
# and branch must be passed in (CI sets these from $GITHUB_SHA / the ref name).
27+
ARG GIT_COMMIT
28+
ARG GIT_BRANCH
29+
2530
# Set environment variables for build
2631
ENV OBP_OAUTH_CLIENT_ID=$OBP_OAUTH_CLIENT_ID
2732
ENV OBP_OAUTH_CLIENT_SECRET=$OBP_OAUTH_CLIENT_SECRET
2833
ENV APP_CALLBACK_URL=$APP_CALLBACK_URL
2934
ENV ORIGIN=$ORIGIN
35+
ENV GIT_COMMIT=$GIT_COMMIT
36+
ENV GIT_BRANCH=$GIT_BRANCH
3037

3138
# Generate .svelte-kit/ for shared package so its tsconfig.json can resolve during the app build
3239
RUN npm run prepare --workspace=packages/shared

Dockerfile_portal

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,18 @@ ARG OBP_OAUTH_CLIENT_SECRET
2222
ARG APP_CALLBACK_URL
2323
ARG ORIGIN
2424

25+
# Build provenance: the .git directory is not copied into the image, so the commit
26+
# and branch must be passed in (CI sets these from $GITHUB_SHA / the ref name).
27+
ARG GIT_COMMIT
28+
ARG GIT_BRANCH
29+
2530
# Set environment variables for build
2631
ENV OBP_OAUTH_CLIENT_ID=$OBP_OAUTH_CLIENT_ID
2732
ENV OBP_OAUTH_CLIENT_SECRET=$OBP_OAUTH_CLIENT_SECRET
2833
ENV APP_CALLBACK_URL=$APP_CALLBACK_URL
2934
ENV ORIGIN=$ORIGIN
35+
ENV GIT_COMMIT=$GIT_COMMIT
36+
ENV GIT_BRANCH=$GIT_BRANCH
3037

3138
# Generate .svelte-kit/ for shared package so its tsconfig.json can resolve during the app build
3239
RUN npm run prepare --workspace=packages/shared

apps/api-manager/src/app.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ declare global {
88
// interface PageState {}
99
// interface Platform {}
1010
}
11+
12+
// Build-time injected variables
13+
const __APP_VERSION__: string;
14+
const __GIT_COMMIT__: string;
15+
const __GIT_BRANCH__: string;
16+
const __BUILD_TIME__: string;
1117
}
1218

1319
export {};

apps/api-manager/src/routes/(protected)/dynamic-entities/system/[id]/+page.svelte

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,26 @@
593593
>
594594
{getTypeDisplayName(fieldDefTyped.type)}
595595
</span>
596+
{#if fieldDefTyped.writeRoleRequired || fieldDefTyped.writeRole}
597+
<span
598+
class="inline-flex items-center rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-800 dark:bg-amber-900 dark:text-amber-200"
599+
title={fieldDefTyped.writeRole
600+
? `Write-restricted — requires role: ${fieldDefTyped.writeRole}`
601+
: "Write-restricted — set only via PATCH by a holder of the auto-generated field write role"}
602+
>
603+
Write-restricted
604+
</span>
605+
{/if}
606+
{#if fieldDefTyped.readRoleRequired || fieldDefTyped.readRole}
607+
<span
608+
class="inline-flex items-center rounded-full bg-purple-100 px-2 py-0.5 text-xs font-medium text-purple-800 dark:bg-purple-900 dark:text-purple-200"
609+
title={fieldDefTyped.readRole
610+
? `Read-restricted — requires role: ${fieldDefTyped.readRole}`
611+
: "Read-restricted — omitted from GET unless the caller holds the auto-generated field read role"}
612+
>
613+
Read-restricted
614+
</span>
615+
{/if}
596616
</div>
597617
{#if fieldDefTyped.description}
598618
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">

apps/api-manager/src/routes/(protected)/dynamic-entities/system/create/+page.svelte

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@
7676
"type": "boolean",
7777
"description": "Is active",
7878
"example": true
79+
},
80+
"internal_note": {
81+
"type": "string",
82+
"description": "Write-restricted: settable only via PATCH by a holder of the field's write role",
83+
"example": "set by a privileged service",
84+
"writeRoleRequired": true
7985
}
8086
},
8187
"required": ["name"]
@@ -472,6 +478,15 @@
472478
<li>
473479
<strong>description:</strong> Human-readable description of the field (optional)
474480
</li>
481+
<li>
482+
<strong>writeRoleRequired / writeRole:</strong> Make a field <em>write-restricted</em> — it cannot be
483+
set via POST/PUT (its value is preserved), only via PATCH by a caller holding the field's write role.
484+
Use the boolean to auto-generate a per-field role, or name an explicit role to share across fields.
485+
</li>
486+
<li>
487+
<strong>readRoleRequired / readRole:</strong> Make a field <em>read-restricted</em> — it is omitted
488+
from GET responses unless the caller holds the field's read role.
489+
</li>
475490
<li>
476491
<strong>has_personal_entity:</strong> Allow each user to create their own private records (optional, default true)
477492
</li>

apps/api-manager/src/routes/about/+page.svelte

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
<script lang="ts">
22
import { env } from "$env/dynamic/public";
3+
4+
function formatBuildTime(isoString: string): string {
5+
try {
6+
return new Date(isoString).toLocaleString();
7+
} catch {
8+
return isoString;
9+
}
10+
}
311
</script>
412

513
<div class="mx-auto max-w-3xl px-6 py-10">
@@ -50,5 +58,26 @@
5058
— source code
5159
</li>
5260
</ul>
61+
62+
<!-- Version Information Footer -->
63+
<div class="mt-12 border-t border-surface-200-800 pt-8" data-testid="build-info">
64+
<div class="text-sm text-surface-600-400">
65+
<span class="font-medium">Version:</span>
66+
<span class="font-mono text-surface-900-100" data-testid="build-version">{__APP_VERSION__}</span>
67+
{#if __GIT_COMMIT__ !== 'unknown'}
68+
<span class="mx-2">•</span>
69+
<span class="font-medium">Commit:</span>
70+
<span class="font-mono text-surface-900-100" data-testid="build-commit">{__GIT_COMMIT__}</span>
71+
{/if}
72+
{#if __GIT_BRANCH__ !== 'unknown'}
73+
<span class="mx-2">•</span>
74+
<span class="font-medium">Branch:</span>
75+
<span class="font-mono text-surface-900-100" data-testid="build-branch">{__GIT_BRANCH__}</span>
76+
{/if}
77+
<span class="mx-2">•</span>
78+
<span class="font-medium">Built:</span>
79+
<span class="font-mono text-surface-900-100" data-testid="build-time">{formatBuildTime(__BUILD_TIME__)}</span>
80+
</div>
81+
</div>
5382
</div>
5483
</div>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { createLogger } from '@obp/shared/utils';
2+
const logger = createLogger('SupportPage');
3+
import { obp_requests } from '$lib/obp/requests';
4+
5+
const DEFAULT_SUPPORT_PLATFORM_URL = 'https://chat.openbankproject.com';
6+
7+
interface WebUIProp {
8+
name: string;
9+
value: string;
10+
}
11+
12+
export async function load() {
13+
let supportPlatformUrl = DEFAULT_SUPPORT_PLATFORM_URL;
14+
15+
try {
16+
const json = await obp_requests.get('/obp/v6.0.0/webui-props?active=true');
17+
const prop = (json?.webui_props as WebUIProp[] | undefined)?.find(
18+
(p) => p.name === 'webui_support_platform_url'
19+
);
20+
if (prop?.value) {
21+
supportPlatformUrl = prop.value;
22+
}
23+
} catch (e) {
24+
// Public page must render even if OBP-API is unreachable; fall back to the default.
25+
logger.warn('Could not fetch webui_support_platform_url, using default:', e);
26+
}
27+
28+
return { supportPlatformUrl };
29+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script lang="ts">
2+
import { LifeBuoy, MessageCircle, ExternalLink } from "@lucide/svelte";
3+
import type { PageData } from "./$types";
4+
5+
let { data }: { data: PageData } = $props();
6+
</script>
7+
8+
<svelte:head>
9+
<title>Support</title>
10+
</svelte:head>
11+
12+
<div class="flex flex-col h-full w-full items-center justify-center">
13+
<div class="mx-auto p-5">
14+
<LifeBuoy size={100} color="var(--color-primary-200)" />
15+
</div>
16+
<div class="text-center mt-6 max-w-xl">
17+
<h1 class="text-2xl font-bold mb-4">Need a hand?</h1>
18+
<p class="text-gray-500 mb-8">
19+
Reach the team on our internal chat, or contact the support platform.
20+
</p>
21+
<div class="flex flex-col sm:flex-row justify-center gap-4">
22+
<a href="/chat-rooms" class="btn btn-primary" data-testid="support-internal-chat">
23+
<MessageCircle size={18} />
24+
<span>Team Chat</span>
25+
</a>
26+
<a
27+
href={data.supportPlatformUrl}
28+
target="_blank"
29+
rel="noopener noreferrer"
30+
class="btn btn-secondary"
31+
data-testid="support-platform-link"
32+
>
33+
<span>Support Platform</span>
34+
<ExternalLink size={18} />
35+
</a>
36+
</div>
37+
</div>
38+
</div>

apps/api-manager/vite.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@ import { svelteTesting } from '@testing-library/svelte/vite';
22
import tailwindcss from '@tailwindcss/vite';
33
import { sveltekit } from '@sveltejs/kit/vite';
44
import { defineConfig } from 'vitest/config';
5+
import { readFileSync } from 'fs';
6+
import { buildInfoDefine } from '../../packages/shared/build/build-info.js';
7+
8+
// Get version from package.json
9+
const packageJson = JSON.parse(readFileSync('./package.json', 'utf-8'));
10+
const version = packageJson.version;
511

612
export default defineConfig({
713
server: { port: 5174 },
14+
define: buildInfoDefine(version),
815
plugins: [tailwindcss(), sveltekit()],
916
test: {
1017
workspace: [

0 commit comments

Comments
 (0)