Skip to content
Merged
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
14 changes: 14 additions & 0 deletions api/test/disk-health-data.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,17 @@ test('with no link set the widget opens the Scrutiny address the browser can rea
'https://disks.example.com',
);
});

for (const endpoint of ['', 'devices']) {
test(`${endpoint || 'the bay list'} sends the Scrutiny token as a Bearer header only when one is set`, async () => {
const seen = [];
const fetchJSON = async (url, opts) => {
seen.push(opts.headers);
return { status: 200, data: { data: { summary: FORK } } };
};
const base = { diskProvider: 'scrutiny', scrutinyUrl: 'http://s.local', bays: [] };
await dataFn(makeCtx(endpoint, { ...base, scrutinyToken: 'tok' }, fetchJSON));
await dataFn(makeCtx(endpoint, base, fetchJSON));
assert.deepEqual(seen, [{ Authorization: 'Bearer tok' }, {}]);
});
}
13 changes: 10 additions & 3 deletions ui/widgets/disk-health/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ function scrutinyDeviceIds(key, device) {
return [device?.device_id, device?.scrutiny_uuid, device?.wwn, key].filter(v => typeof v === 'string' && v);
}

function scrutinyHeaders(config) {
return config.scrutinyToken ? { Authorization: 'Bearer ' + config.scrutinyToken } : {};
}

function scrutinyStatus(ctx, r) {
if (r.status === 401 || r.status === 403) ctx.fail('Scrutiny auth failed', { kind: ctx.KIND.AUTH });
if (r.status === 401 || r.status === 403) ctx.fail('Scrutiny auth failed, check API token', { kind: ctx.KIND.AUTH });
if (r.status >= 400) ctx.fail('Scrutiny HTTP ' + r.status);
}

Expand All @@ -40,7 +44,10 @@ function scrutinyIndex(summary) {
async function scrutinyDeviceOptions(ctx) {
const { config, fetchJSON, normalizeBase } = ctx;
if (!config.scrutinyUrl) ctx.fail('Enter the Scrutiny URL first.', { kind: ctx.KIND.INVALID });
const r = await fetchJSON(normalizeBase(config.scrutinyUrl) + '/api/summary', { timeout: 8000 });
const r = await fetchJSON(normalizeBase(config.scrutinyUrl) + '/api/summary', {
headers: scrutinyHeaders(config),
timeout: 8000,
});
scrutinyStatus(ctx, r);
const summary = r.data?.data?.summary || {};
const options = Object.entries(summary)
Expand Down Expand Up @@ -90,7 +97,7 @@ async function diskHealthScrutiny(ctx) {
const bays = config.bays || [];

const base = normalizeBase(url);
const r = await fetchJSON(base + '/api/summary', { timeout: 8000 });
const r = await fetchJSON(base + '/api/summary', { headers: scrutinyHeaders(config), timeout: 8000 });
scrutinyStatus(ctx, r);

const byId = scrutinyIndex(r.data?.data?.summary || {});
Expand Down
2 changes: 2 additions & 0 deletions ui/widgets/disk-health/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"diskProvider.opt.truenas": "TrueNAS",
"scrutinyUrl.label": "Scrutiny-URL",
"scrutinyUrl.placeholder": "scrutiny:8080",
"scrutinyToken.label": "Scrutiny-API-Token",
"scrutinyToken.hint": "Nötig, wenn Scrutiny eine Anmeldung verlangt. Ab Scrutiny 2.0 ist das die Vorgabe. Ein Token mit dem Bereich read genügt.",
"scrutinyHref.label": "Link-URL",
"scrutinyHref.placeholder": "http://your-server:8080",
"scrutinyHref.hint": "Die Adresse, unter der dein Browser diesen Dienst öffnet. Leer lassen, um die Adresse oben zu verwenden, sofern dein Browser sie erreicht.",
Expand Down
2 changes: 2 additions & 0 deletions ui/widgets/disk-health/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"diskProvider.opt.truenas": "TrueNAS",
"scrutinyUrl.label": "Scrutiny URL",
"scrutinyUrl.placeholder": "scrutiny:8080",
"scrutinyToken.label": "Scrutiny API Token",
"scrutinyToken.hint": "Needed when Scrutiny requires a login, which is the default from Scrutiny 2.0. A token with read scope is enough.",
"scrutinyHref.label": "Link URL",
"scrutinyHref.placeholder": "http://your-server:8080",
"scrutinyHref.hint": "The address your browser uses for this service. Leave blank to use the one above, if your browser can reach it.",
Expand Down
2 changes: 2 additions & 0 deletions ui/widgets/disk-health/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"diskProvider.opt.truenas": "TrueNAS",
"scrutinyUrl.label": "URL de Scrutiny",
"scrutinyUrl.placeholder": "scrutiny:8080",
"scrutinyToken.label": "Token de API de Scrutiny",
"scrutinyToken.hint": "Necesario si Scrutiny exige iniciar sesión, lo predeterminado desde Scrutiny 2.0. Basta un token con el ámbito read.",
"scrutinyHref.label": "URL del enlace",
"scrutinyHref.placeholder": "http://your-server:8080",
"scrutinyHref.hint": "La dirección con la que tu navegador abre este servicio. Déjalo en blanco para usar la de arriba, si tu navegador puede acceder a ella.",
Expand Down
2 changes: 2 additions & 0 deletions ui/widgets/disk-health/i18n/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"diskProvider.opt.truenas": "TrueNAS",
"scrutinyUrl.label": "آدرس Scrutiny",
"scrutinyUrl.placeholder": "scrutiny:8080",
"scrutinyToken.label": "توکن API Scrutiny",
"scrutinyToken.hint": "اگر Scrutiny ورود بخواهد لازم است. از Scrutiny 2.0 این حالت پیش‌فرض است. توکنی با دسترسی read کافی است.",
"scrutinyHref.label": "آدرس پیوند",
"scrutinyHref.placeholder": "http://your-server:8080",
"scrutinyHref.hint": "آدرسی که مرورگرتان برای این سرویس استفاده می‌کند. اگر مرورگرتان به آدرس بالا دسترسی دارد، خالی بگذارید.",
Expand Down
2 changes: 2 additions & 0 deletions ui/widgets/disk-health/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"diskProvider.opt.truenas": "TrueNAS",
"scrutinyUrl.label": "URL Scrutiny",
"scrutinyUrl.placeholder": "scrutiny:8080",
"scrutinyToken.label": "Jeton d’API Scrutiny",
"scrutinyToken.hint": "Nécessaire si Scrutiny exige une connexion, ce qui est le cas par défaut depuis Scrutiny 2.0. Un jeton avec la portée read suffit.",
"scrutinyHref.label": "URL du lien",
"scrutinyHref.placeholder": "http://your-server:8080",
"scrutinyHref.hint": "L’adresse que votre navigateur utilise pour ce service. Laissez vide pour utiliser celle ci-dessus, si votre navigateur peut l’atteindre.",
Expand Down
2 changes: 2 additions & 0 deletions ui/widgets/disk-health/i18n/zh-Hans.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"diskProvider.opt.truenas": "TrueNAS",
"scrutinyUrl.label": "Scrutiny 地址",
"scrutinyUrl.placeholder": "scrutiny:8080",
"scrutinyToken.label": "Scrutiny API 令牌",
"scrutinyToken.hint": "Scrutiny 要求登录时需要填写,Scrutiny 2.0 起默认要求登录。具有 read 权限的令牌即可。",
"scrutinyHref.label": "链接地址",
"scrutinyHref.placeholder": "http://your-server:8080",
"scrutinyHref.hint": "浏览器访问此服务所用的地址。留空则使用上方地址(前提是浏览器能访问它)。",
Expand Down
11 changes: 11 additions & 0 deletions ui/widgets/disk-health/widget.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@
"equals": "scrutiny"
}
},
{
"key": "scrutinyToken",
"type": "secret",
"label": "scrutinyToken.label",
"hint": "scrutinyToken.hint",
"optional": true,
"showIf": {
"field": "diskProvider",
"equals": "scrutiny"
}
},
{
"key": "scrutinyHref",
"type": "text",
Expand Down
Loading