diff --git a/Dockerfile b/Dockerfile index 56c599876..3fd2e377b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM node:10.14.1-alpine as builder +FROM node:10.15.1-alpine as builder ENV NODE_ENV=production \ - VERDACCIO_BUILD_REGISTRY=https://registry.verdaccio.org + VERDACCIO_BUILD_REGISTRY=https://registry.npmjs.org RUN apk --no-cache add openssl ca-certificates wget && \ apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python && \ @@ -13,12 +13,12 @@ WORKDIR /opt/verdaccio-build COPY . . RUN yarn config set registry $VERDACCIO_BUILD_REGISTRY && \ - yarn install --production=false && \ + yarn install --production=false --no-lockfile && \ yarn lint && \ yarn code:docker-build && \ yarn build:webui && \ yarn cache clean && \ - yarn install --production=true --pure-lockfile + yarn install --production=true --no-lockfile diff --git a/package.json b/package.json index 7e082d400..14a0643ce 100644 --- a/package.json +++ b/package.json @@ -18,45 +18,45 @@ "@verdaccio/file-locking": "0.0.8", "@verdaccio/local-storage": "2.0.0-beta.1", "@verdaccio/streams": "2.0.0-beta.0", - "JSONStream": "1.3.4", + "JSONStream": "1.3.5", "async": "3.0.1-0", "body-parser": "1.18.3", "bunyan": "1.8.12", - "chalk": "2.4.1", - "commander": "2.18.0", + "chalk": "2.4.2", + "commander": "2.19.0", "compression": "1.7.3", - "cookies": "0.7.2", - "cors": "2.8.4", - "date-fns": "1.29.0", - "express": "4.16.3", + "cookies": "0.7.3", + "cors": "2.8.5", + "date-fns": "1.30.1", + "express": "4.16.4", "global": "4.3.2", "handlebars": "4.0.12", "http-errors": "1.7.1", - "js-base64": "2.4.9", + "js-base64": "2.5.1", "js-string-escape": "1.0.1", - "js-yaml": "3.12.0", - "jsonwebtoken": "8.3.0", + "js-yaml": "3.12.1", + "jsonwebtoken": "8.4.0", "lockfile": "1.0.4", "lodash": "4.17.11", - "lunr-mutable-indexes": "2.3.1", - "marked": "0.5.1", - "mime": "2.3.1", + "lunr-mutable-indexes": "2.3.2", + "marked": "0.6.0", + "mime": "2.4.0", "minimatch": "3.0.4", "mkdirp": "0.5.1", "mv": "2.1.1", "pkginfo": "0.4.1", "request": "2.88.0", - "semver": "5.5.1", + "semver": "5.6.0", "verdaccio-audit": "1.1.0", - "verdaccio-htpasswd": "1.0.1", + "verdaccio-htpasswd": "2.0.0-beta.0", "verror": "1.10.0" }, "devDependencies": { "@commitlint/cli": "7.2.1", "@commitlint/config-conventional": "7.1.2", - "@material-ui/core": "3.1.0", - "@material-ui/icons": "3.0.1", - "@verdaccio/babel-preset": "0.0.3", + "@material-ui/core": "3.9.0", + "@material-ui/icons": "3.0.2", + "@verdaccio/babel-preset": "0.0.4", "@verdaccio/types": "4.1.4", "autosuggest-highlight": "3.1.1", "bundlesize": "0.17.0", @@ -102,9 +102,9 @@ "prettier": "1.14.3", "prop-types": "15.6.2", "puppeteer": "1.8.0", - "react": "16.4.2", + "react": "16.7.0", "react-autosuggest": "9.4.2", - "react-dom": "16.4.2", + "react-dom": "16.7.0", "react-emotion": "9.2.12", "react-hot-loader": "4.2.0", "react-router": "4.3.1", @@ -132,7 +132,8 @@ "webpack-cli": "3.1.1", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4", - "whatwg-fetch": "3.0.0" + "whatwg-fetch": "3.0.0", + "xss": "1.0.3" }, "keywords": [ "private", diff --git a/src/api/web/index.js b/src/api/web/index.js index be76dec57..71bbfe863 100644 --- a/src/api/web/index.js +++ b/src/api/web/index.js @@ -12,6 +12,7 @@ import express from 'express'; import { combineBaseUrl, getWebProtocol } from '../../lib/utils'; import Search from '../../lib/search'; import { HEADERS, HTTP_STATUS, WEB_TITLE } from '../../lib/constants'; +import { spliceURL } from '../../utils/string'; const { securityIframe } = require('../middleware'); /* eslint new-cap:off */ @@ -52,9 +53,8 @@ module.exports = function(config, auth, storage) { }); }); - router.get('/', function(req, res) { - const installPath = _.get(config, 'url_prefix', ''); - const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), installPath); + function renderHTML(req, res) { + const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), config.url_prefix); const webPage = template .replace(/ToReplaceByVerdaccio/g, base) .replace(/ToReplaceByTitle/g, _.get(config, 'web.title') ? config.web.title : WEB_TITLE) @@ -64,6 +64,20 @@ module.exports = function(config, auth, storage) { res.setHeader('Content-Type', 'text/html'); res.send(webPage); + } + + router.get('/-/web/:pkg', function(req, res) { + renderHTML(req, res); + }); + + router.get('/-/verdaccio/logo', function(req, res) { + const installPath = _.get(config, 'url_prefix', ''); + + res.send(_.get(config, 'web.logo') || spliceURL(installPath, '/-/static/logo.png')); + }); + + router.get('/', function(req, res) { + renderHTML(req, res); }); return router; diff --git a/src/webui/app.js b/src/webui/app.js index d5737a349..4ca152050 100644 --- a/src/webui/app.js +++ b/src/webui/app.js @@ -4,21 +4,26 @@ import isNil from 'lodash/isNil'; import storage from './utils/storage'; import { makeLogin, isTokenExpire } from './utils/login'; -import Footer from './components/Footer'; import Loading from './components/Loading'; import LoginModal from './components/Login'; import Header from './components/Header'; import { Container, Content } from './components/Layout'; -import Route from './router'; +import RouterApp from './router'; import API from './utils/api'; import './styles/typeface-roboto.scss'; import './styles/main.scss'; import 'normalize.css'; +import Footer from './components/Footer'; + +export const AppContext = React.createContext(); + +export const AppContextProvider = AppContext.Provider; +export const AppContextConsumer = AppContext.Consumer; export default class App extends Component { state = { error: {}, - logoUrl: '', + logoUrl: window.VERDACCIO_LOGO, user: {}, scope: (window.VERDACCIO_SCOPE) ? `${window.VERDACCIO_SCOPE}:` : '', showLoginModal: false, @@ -28,26 +33,18 @@ export default class App extends Component { } componentDidMount() { - this.loadLogo(); this.isUserAlreadyLoggedIn(); - this.loadPackages(); + this.loadOnHandler(); } // eslint-disable-next-line no-unused-vars componentDidUpdate(_, prevState) { const { isUserLoggedIn } = this.state; if (prevState.isUserLoggedIn !== isUserLoggedIn) { - this.loadPackages(); + this.loadOnHandler(); } } - loadLogo = () => { - const logoUrl = window.VERDACCIO_LOGO; - this.setState({ - logoUrl, - }); - } - isUserAlreadyLoggedIn = () => { // checks for token validity const token = storage.getItem('token'); @@ -62,7 +59,7 @@ export default class App extends Component { } } - loadPackages = async () => { + loadOnHandler = async () => { try { this.req = await API.request('packages', 'GET'); this.setState({ @@ -70,7 +67,8 @@ export default class App extends Component { isLoading: false, }); } catch (error) { - this.handleShowAlertDialog({ + // FIXME: add dialog + console.error({ title: 'Warning', message: `Unable to load package list: ${error.message}`, }); @@ -143,18 +141,16 @@ export default class App extends Component { } render() { - const { isLoading, isUserLoggedIn, packages } = this.state; + const { isLoading, isUserLoggedIn, packages, logoUrl, user, scope } = this.state; return ( {isLoading ? ( ) : ( - {this.renderHeader()} - - - -