Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#2538): implement configs to hide URLs in UI #3757

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
16 changes: 16 additions & 0 deletions spring-boot-admin-docs/src/site/asciidoc/customize_ui.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,19 @@ You can very simply hide views in the navbar:
----
include::{samples-dir}/spring-boot-admin-sample-servlet/src/main/resources/application.yml[tags=customization-view-settings]
----

== Hide Service URL ==
To hide service URLs in Spring Boot Admin UI entirely, set the following property in your Server's configuration:

|===
| Property name | Default | Usage

| `spring.boot.admin.ui.show-instance-url`
| `true`
| Set to `false` to hide service URLs as well as actions that require them in UI (e.g. jump to /health or /actuator).

|===

If you want to hide the URL for specific instances oncly, you can set the `hide-url` property in the instance metadata while registering a service.
When using Spring Boot Admin Client you can set the property `spring.boot.admin.client.metadata.hide-url=true` in the corresponding config file.
The value set in `metadata` does not have any effect, when the URLs are disabled in Server.
11 changes: 6 additions & 5 deletions spring-boot-admin-server-ui/src/main/frontend/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ declare global {

type UITheme = {
color: string;
palette: {
backgroundEnabled: boolean;
palette?: {
shade50: string;
shade100: string;
shade200: string;
Expand Down Expand Up @@ -60,18 +61,18 @@ declare global {
type UISettings = {
title: string;
brand: string;
loginIcon: string;
favicon: string;
faviconDanger: string;
pollTimer: PollTimer;
uiTheme: UITheme;
theme: UITheme;
notificationFilterEnabled: boolean;
rememberMeEnabled: boolean;
availableLanguages: string[];
routes: string[];
externalViews: ExternalView[];
viewSettings: ViewSettings[];
enableToasts: boolean;
showInstanceUrl: boolean;
};

type SBASettings = {
Expand All @@ -81,8 +82,8 @@ declare global {
[key: string]: any;
};
extensions: {
js: Extension[];
css: Extension[];
js?: Extension[];
css?: Extension[];
};
csrf: {
headerName: string;
Expand Down
16 changes: 10 additions & 6 deletions spring-boot-admin-server-ui/src/main/frontend/sba-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@ import { merge } from 'lodash-es';
const brand =
'<img src="assets/img/icon-spring-boot-admin.svg">Spring Boot Admin';

const DEFAULT_CONFIG = {
const DEFAULT_CONFIG: SBASettings = {
uiSettings: {
title: 'Spring Boot Admin',
brand,
theme: {
backgroundEnabled: true,
color: '#42d3a5',
},
notifications: {
enabled: true,
},
rememberMeEnabled: true,
enableToasts: false,
externalViews: [] as ExternalView[],
favicon: 'assets/img/favicon.png',
faviconDanger: 'assets/img/favicon-danger.png',
Expand All @@ -45,9 +44,10 @@ const DEFAULT_CONFIG = {
threads: 2500,
logfile: 1000,
},
showInstanceUrl: true,
},
user: null,
extensions: [],
extensions: {},
csrf: {
parameterName: '_csrf',
headerName: 'X-XSRF-TOKEN',
Expand All @@ -57,10 +57,14 @@ const DEFAULT_CONFIG = {
},
};

const mergedConfig = merge(DEFAULT_CONFIG, window.SBA);
const mergedConfig = merge(DEFAULT_CONFIG, window.SBA) as SBASettings;

export const getCurrentUser = () => {
return mergedConfig.user;
};

export default mergedConfig;

export const useSbaConfig = () => {
return mergedConfig;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { describe, expect, test, vi } from 'vitest';

import Instance from '@/services/instance';

const { useSbaConfig } = vi.hoisted(() => ({
useSbaConfig: vi.fn().mockReturnValue(true),
}));

vi.mock('@/sba-config', async (importOriginal) => ({
...(await importOriginal<typeof import('@/sba-config')>()),
useSbaConfig,
}));

describe('Instance', () => {
test.each`
showInstanceUrl | metadataHideUrl | expected
${true} | ${'true'} | ${true}
${false} | ${'true'} | ${false}
${true} | ${'false'} | ${false}
${false} | ${'false'} | ${false}
${true} | ${undefined} | ${true}
`(
'showUrl when showInstanceUrl=$showInstanceUrl and metadataHideUrl=$metadataHideUrl should return $expected',
({ showInstanceUrl, metadataHideUrl, expected }) => {
useSbaConfig.mockReturnValue({
uiSettings: {
showInstanceUrl: showInstanceUrl,
},
});

const instance = new Instance({
id: 'id',
registration: {
metadata: {
['hide-url']: metadataHideUrl,
},
},
});

expect(instance.showUrl()).toBe(expected);
},
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import waitForPolyfill from '../utils/eventsource-polyfill';
import logtail from '../utils/logtail';
import uri from '../utils/uri';

import { useSbaConfig } from '@/sba-config';

const actuatorMimeTypes = [
'application/vnd.spring-boot.actuator.v2+json',
'application/vnd.spring-boot.actuator.v1+json',
Expand Down Expand Up @@ -117,6 +119,16 @@ class Instance {
}));
}

showUrl() {
const sbaConfig = useSbaConfig();
if (sbaConfig.uiSettings.showInstanceUrl) {
const hideUrlMetadata = this.registration.metadata?.['hide-url'];
return hideUrlMetadata === undefined || hideUrlMetadata === 'true';
}

return false;
}

getId() {
return this.id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('Navbar', function () {
});

render(Navbar);
screen.logTestingPlaygroundURL();

expect(screen.getByTestId('usermenu')).toBeVisible();
expect(screen.getByText('[email protected]')).toBeVisible();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/vitest';
import { cleanup } from '@testing-library/vue';
import { afterAll, afterEach, beforeAll, vi } from 'vitest';

import { server } from '@/mocks/server';
import sbaConfig from '@/sba-config';

global.IntersectionObserver = vi.fn().mockImplementation(() => ({
observe: vi.fn(),
Expand All @@ -15,6 +17,8 @@ global.ResizeObserver = vi.fn().mockImplementation(() => ({
disconnect: vi.fn(),
}));

global.SBA = sbaConfig;

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!--
- Copyright 2014-2018 the original author or authors.
- Copyright 2014-2024 the original author or authors.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,25 +30,39 @@
/>
</div>
<div class="flex-auto xl:flex-1 xl:w-1/4 truncate">
<a
:href="
instance.registration.serviceUrl || instance.registration.healthUrl
"
@click.stop
v-text="
instance.registration.serviceUrl || instance.registration.healthUrl
"
/>
<sba-tag
v-if="instance.registration.metadata?.['group']"
class="ml-2"
:value="instance.registration.metadata?.['group']"
small
/>
<br />
<span class="text-sm italic" v-text="instance.id" />
<template v-if="instance.showUrl()">
<a
:href="
instance.registration.serviceUrl ||
instance.registration.healthUrl
"
@click.stop
v-text="
instance.registration.serviceUrl ||
instance.registration.healthUrl
"
/>
<sba-tag
v-if="instance.registration.metadata?.['group']"
class="ml-2"
:value="instance.registration.metadata?.['group']"
small
/>
<br />
<span class="text-sm italic" v-text="instance.id" />
</template>
<template v-else>
<span v-text="instance.id"></span>
<sba-tag
v-if="instance.registration.metadata?.['group']"
class="ml-2"
:value="instance.registration.metadata?.['group']"
small
/>
</template>
</div>
<div
v-if="Array.isArray(instance.tags)"
class="hidden xl:block w-1/4"
:class="{
'overflow-x-scroll': Object.keys(instance.tags ?? {}).length > 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<div class="flex-1 text-right">
<sba-button-group>
<sba-button
v-if="instance.showUrl()"
:title="instance.registration.serviceUrl"
class="border-gray-400 ml-1"
@click="openLink(instance.registration.serviceUrl)"
Expand All @@ -31,6 +32,7 @@
</sba-button>

<sba-button
v-if="instance.showUrl()"
:title="instance.registration.managementUrl"
class="border-gray-400 ml-1"
@click="openLink(instance.registration.managementUrl)"
Expand All @@ -52,6 +54,7 @@
</sba-button>

<sba-button
v-if="instance.showUrl()"
:title="instance.registration.healthUrl"
class="border-gray-400 ml-1"
@click="openLink(instance.registration.healthUrl)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2023 the original author or authors.
* Copyright 2014-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -109,6 +109,7 @@ public UiController homeUiController(UiExtensions uiExtensions) throws IOExcepti
.favicon(this.adminUi.getFavicon())
.faviconDanger(this.adminUi.getFaviconDanger())
.enableToasts(this.adminUi.getEnableToasts())
.showInstanceUrl(this.adminUi.getShowInstanceUrl())
.notificationFilterEnabled(
!this.applicationContext.getBeansOfType(NotificationFilterController.class).isEmpty())
.routes(routes)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2023 the original author or authors.
* Copyright 2014-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -132,6 +132,11 @@ public class AdminServerUiProperties {
*/
private Boolean enableToasts = false;

/**
* Show or hide URL of instances.
*/
private Boolean showInstanceUrl = true;

private UiTheme theme = new UiTheme();

@lombok.Data
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2023 the original author or authors.
* Copyright 2014-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -150,6 +150,8 @@ public static class Settings {

private final Boolean enableToasts;

private final Boolean showInstanceUrl;

}

@lombok.Data
Expand Down
Loading