Skip to content

Commit

Permalink
fix: restore using local path web logo (#2270)
Browse files Browse the repository at this point in the history
* fix: logo loaded locally

* chore: fix lint
  • Loading branch information
juanpicado committed May 22, 2021
1 parent 1e4c900 commit 8434cc5
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 21 deletions.
6 changes: 3 additions & 3 deletions src/api/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ export function serveFavicon(config: Config) {
debug('no read permissions to read: %o, reason:', logoConf, err?.message);
return res.status(HTTP_STATUS.NOT_FOUND).end();
} else {
res.setHeader('Content-Type', 'image/x-icon');
res.setHeader('content-type', 'image/x-icon');
fs.createReadStream(faviconPath).pipe(res);
debug('rendered custom ico');
}
});
}
} else {
res.setHeader('Content-Type', 'image/x-icon');
fs.createReadStream(path.join(__dirname, './web/html/favicon.ico')).pipe(res);
res.setHeader('content-type', 'image/x-icon');
fs.createReadStream(path.posix.join(__dirname, './web/html/favicon.ico')).pipe(res);
debug('rendered ico');
}
} catch (err) {
Expand Down
17 changes: 15 additions & 2 deletions src/api/web/html/renderHTML.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { URL } from 'url';
import path from 'path';
import buildDebug from 'debug';
import LRU from 'lru-cache';
import { HEADERS } from '@verdaccio/commons-api';

import { getPublicUrl } from '../../../lib/utils';
import { getPublicUrl, isHTTPProtocol } from '../../../lib/utils';
import { WEB_TITLE } from '../../../lib/constants';
import renderTemplate from './template';

Expand All @@ -28,6 +29,18 @@ export function validatePrimaryColor(primaryColor) {
return primaryColor;
}

export function resolveLogo(config, req) {
const isLocalFile = config?.web?.logo && !isHTTPProtocol(config?.web?.logo);

if (isLocalFile) {
return `${getPublicUrl(config?.url_prefix, req)}-/static/${path.basename(config?.web?.logo)}`;
} else if (isHTTPProtocol(config?.web?.logo)) {
return config?.web?.logo;
} else {
return '';
}
}

export default function renderHTML(config, manifest, manifestFiles, req, res) {
const { url_prefix } = config;
const base = getPublicUrl(config?.url_prefix, req);
Expand All @@ -36,7 +49,7 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
const darkMode = config?.web?.darkMode ?? false;
const title = config?.web?.title ?? WEB_TITLE;
const scope = config?.web?.scope ?? '';
let logoURI = config?.web?.logo ?? '';
const logoURI = resolveLogo(config, req);
const version = pkgJSON.version;
const primaryColor = validatePrimaryColor(config?.web?.primary_color) ?? '#4b5e40';
const { scriptsBodyAfter, metaScripts, scriptsbodyBefore } = Object.assign(
Expand Down
40 changes: 37 additions & 3 deletions src/api/web/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import fs from 'fs';
import path from 'path';
import _ from 'lodash';

import express from 'express';
import buildDebug from 'debug';

import Search from '../../lib/search';
import { HTTP_STATUS } from '../../lib/constants';
import loadPlugin from '../../lib/plugin-loader';
import { isHTTPProtocol } from '../../lib/utils';
import { logger } from '../../lib/logger';
import renderHTML from './html/renderHTML';

const { setSecurityWebHeaders } = require('../middleware');
Expand Down Expand Up @@ -66,14 +71,43 @@ export default function (config, auth, storage) {
res.sendFile(file, sendFileCallback(next));
});

// logo
if (config?.web?.logo && !isHTTPProtocol(config?.web?.logo)) {
// URI related to a local file
const absoluteLocalFile = path.posix.resolve(config.web.logo);
debug('serve local logo %s', absoluteLocalFile);
try {
if (fs.existsSync(absoluteLocalFile) && typeof fs.accessSync(absoluteLocalFile, fs.constants.R_OK) === 'undefined') {
// Note: `path.join` will break on Windows, because it transforms `/` to `\`
// Use POSIX version `path.posix.join` instead.
config.web.logo = path.posix.join('/-/static/', path.basename(config.web.logo));
router.get(config.web.logo, function (_req, res, next) {
debug('serve custom logo web:%s - local:%s', config.web.logo, absoluteLocalFile);
res.sendFile(absoluteLocalFile, sendFileCallback(next));
});
debug('enabled custom logo %s', config.web.logo);
} else {
config.web.logo = undefined;
logger.warn(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);
}
} catch {
config.web.logo = undefined;
logger.warn(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);
}
}

router.get('/-/web/:section/*', function (req, res) {
renderHTML(config, manifest, manifestFiles, req, res);
debug('render html section');
});

router.get('/', function (req, res) {
renderHTML(config, manifest, manifestFiles, req, res);
debug('render root');
router.get('/', function (req, res, next) {
try {
renderHTML(config, manifest, manifestFiles, req, res);
debug('render root');
} catch {
next(new Error('boom'));
}
});

return router;
Expand Down
25 changes: 25 additions & 0 deletions test/unit/modules/web/__snapshots__/template.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,31 @@ exports[`template custom body before 1`] = `
"
`;
exports[`template custom logo 1`] = `
"
<!DOCTYPE html>
<html lang=\\"en-us\\">
<head>
<meta charset=\\"utf-8\\">
<base href=\\"http://domain.com\\">
<title></title>
<link rel=\\"icon\\" href=\\"http://domain.com-/static/favicon.ico\\"/>
<meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1\\" />
<script>
window.__VERDACCIO_BASENAME_UI_OPTIONS={\\"base\\":\\"http://domain.com\\",\\"logo\\":\\"http://domain/logo.png\\"}
</script>
</head>
<body class=\\"body\\">
<div id=\\"root\\"></div>
<script defer=\\"defer\\" src=\\"http://domain.com-/static/runtime.9be80fd172e81558124c.js\\"></script><script defer=\\"defer\\" src=\\"http://domain.com-/static/main.9be80fd172e81558124c.js\\"></script>
</body>
</html>
"
`;
exports[`template custom render 1`] = `
"
<!DOCTYPE html>
Expand Down
24 changes: 11 additions & 13 deletions test/unit/modules/web/template.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import renderTemplate from "../../../../src/api/web/html/template";
import renderTemplate from '../../../../src/api/web/html/template';

const manifest = require('./partials/manifest/manifest.json');

Expand All @@ -10,38 +10,36 @@ const exampleManifest = {

describe('template', () => {
test('custom render', () => {
expect(renderTemplate({ options: {base: 'http://domain.com'}, manifest: exampleManifest }, manifest)).toMatchSnapshot();
expect(renderTemplate({ options: { base: 'http://domain.com' }, manifest: exampleManifest }, manifest)).toMatchSnapshot();
});

test('custom title', () => {
expect(
renderTemplate({ options: {base: 'http://domain.com', title: 'foo title' }, manifest: exampleManifest }, manifest)
).toMatchSnapshot();
expect(renderTemplate({ options: { base: 'http://domain.com', title: 'foo title' }, manifest: exampleManifest }, manifest)).toMatchSnapshot();
});

test('custom title', () => {
expect(
renderTemplate({ options: {base: 'http://domain.com', title: 'foo title' }, manifest: exampleManifest }, manifest)
).toMatchSnapshot();
expect(renderTemplate({ options: { base: 'http://domain.com', title: 'foo title' }, manifest: exampleManifest }, manifest)).toMatchSnapshot();
});

test('custom logo', () => {
expect(renderTemplate({ options: { base: 'http://domain.com', logo: 'http://domain/logo.png' }, manifest: exampleManifest }, manifest)).toMatchSnapshot();
});

test('meta scripts', () => {
expect(
renderTemplate({ options: {base: 'http://domain.com'}, metaScripts: [`<style>.someclass{font-size:10px;}</style>`], manifest: exampleManifest }, manifest)
renderTemplate({ options: { base: 'http://domain.com' }, metaScripts: [`<style>.someclass{font-size:10px;}</style>`], manifest: exampleManifest }, manifest)
).toMatchSnapshot();
});

test('custom body after', () => {
expect(
renderTemplate({ options: {base: 'http://domain.com'}, scriptsBodyAfter: [`<script src="foo"/>`], manifest: exampleManifest }, manifest)
).toMatchSnapshot();
expect(renderTemplate({ options: { base: 'http://domain.com' }, scriptsBodyAfter: [`<script src="foo"/>`], manifest: exampleManifest }, manifest)).toMatchSnapshot();
});

test('custom body before', () => {
expect(
renderTemplate(
{
options: {base: 'http://domain.com'},
options: { base: 'http://domain.com' },
scriptsbodyBefore: [`<script src="fooBefore"/>`, `<script src="barBefore"/>`],
manifest: exampleManifest,
},
Expand Down

0 comments on commit 8434cc5

Please sign in to comment.