diff --git a/package.json b/package.json
index 5c2a935d9..8073efb58 100644
--- a/package.json
+++ b/package.json
@@ -51,7 +51,6 @@
"@commitlint/config-conventional": "6.1.3",
"@commitlint/travis-cli": "6.1.3",
"@verdaccio/types": "2.0.2",
- "axios": "0.18.0",
"babel-cli": "6.26.0",
"babel-core": "6.26.0",
"babel-eslint": "8.2.2",
@@ -129,7 +128,8 @@
"verdaccio-memory": "0.0.6",
"webpack": "3.10.0",
"webpack-dev-server": "2.11.1",
- "webpack-merge": "4.1.2"
+ "webpack-merge": "4.1.2",
+ "whatwg-fetch": "2.0.3"
},
"keywords": [
"private",
diff --git a/src/api/web/endpoint/user.js b/src/api/web/endpoint/user.js
index bf459306d..2c57f6b75 100644
--- a/src/api/web/endpoint/user.js
+++ b/src/api/web/endpoint/user.js
@@ -4,7 +4,6 @@ import HTTPError from 'http-errors';
import type {Config} from '@verdaccio/types';
import type {Router} from 'express';
import type {IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer} from '../../../../types';
-// import {combineBaseUrl, getWebProtocol} from '../../../lib/utils';
function addUserAuthApi(route: Router, auth: IAuth, config: Config) {
route.post('/login', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
@@ -21,14 +20,6 @@ function addUserAuthApi(route: Router, auth: IAuth, config: Config) {
}
});
});
-
- // FIXME: this will be re-implemented
- // route.post('/-/logout', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
- // const base = combineBaseUrl(getWebProtocol(req), req.get('host'), config.url_prefix);
-
- // res.cookies.set('token', '');
- // res.redirect(base);
- // });
}
export default addUserAuthApi;
diff --git a/src/lib/auth.js b/src/lib/auth.js
index 68d7f2975..5087d5b8a 100644
--- a/src/lib/auth.js
+++ b/src/lib/auth.js
@@ -296,11 +296,12 @@ class Auth {
/**
* JWT middleware for WebUI
- * @return {Function}
*/
jwtMiddleware() {
return (req: $RequestExtend, res: $Response, _next: NextFunction) => {
- if (req.remote_user !== null && req.remote_user.name !== undefined) return _next();
+ if (req.remote_user !== null && req.remote_user.name !== undefined) {
+ return _next();
+ }
req.pause();
const next = function(_err) {
@@ -308,18 +309,22 @@ class Auth {
return _next();
};
- req.remote_user = buildAnonymousUser();
-
- let token = (req.headers.authorization || '').replace('Bearer ', '');
- if (!token) return next();
+ const token = (req.headers.authorization || '').replace('Bearer ', '');
+ if (!token) {
+ return next();
+ }
let decoded;
try {
decoded = this.decode_token(token);
- } catch (err) {/**/}
+ } catch (err) {
+ // FIXME: intended behaviour, do we want it?
+ }
if (decoded) {
req.remote_user = authenticatedUser(decoded.user, decoded.group);
+ } else {
+ req.remote_user = buildAnonymousUser();
}
next();
diff --git a/src/webui/src/components/Header/index.js b/src/webui/src/components/Header/index.js
index 397fed3d9..7aec24afa 100644
--- a/src/webui/src/components/Header/index.js
+++ b/src/webui/src/components/Header/index.js
@@ -1,17 +1,16 @@
import React from 'react';
import {Button, Dialog, Input, Alert} from 'element-react';
import isString from 'lodash/isString';
-import get from 'lodash/get';
import isNumber from 'lodash/isNumber';
import {Link} from 'react-router-dom';
import API from '../../../utils/api';
import storage from '../../../utils/storage';
-
+import {getRegistryURL} from '../../../utils/url';
import classes from './header.scss';
import './logo.png';
-import {getRegistryURL} from '../../../utils/url';
+
export default class Header extends React.Component {
state = {
@@ -43,10 +42,8 @@ export default class Header extends React.Component {
}
componentWillMount() {
- API.get('logo')
- .then((response) => {
- this.setState({logo: response.data});
- })
+ API.request('logo')
+ .then((response) => response.text().then((logo) => this.setState({logo})))
.catch((error) => {
throw new Error(error);
});
@@ -62,26 +59,27 @@ export default class Header extends React.Component {
}
try {
- let resp = await API.post(`login`, {
- data: {
- username: this.state.username,
- password: this.state.password
+ const credentials = {
+ username: this.state.username,
+ password: this.state.password
+ };
+ let resp = await API.request(`login`, 'POST', {
+ body: JSON.stringify(credentials),
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json'
}
- });
+ }).then((response) => response.json());
- storage.setItem('token', resp.data.token);
- storage.setItem('username', resp.data.username);
+ storage.setItem('token', resp.token);
+ storage.setItem('username', resp.username);
location.reload();
} catch (e) {
const errorObj = {
title: 'Unable to login',
type: 'error'
};
- if (get(e, 'response.status', 0) === 401) {
- errorObj.description = e.response.data.error;
- } else {
- errorObj.description = e.message;
- }
+ errorObj.description = e.message;
this.setState({loginError: errorObj});
}
}
diff --git a/src/webui/src/components/PackageSidebar/index.jsx b/src/webui/src/components/PackageSidebar/index.jsx
index b4830a83b..a95f602bc 100644
--- a/src/webui/src/components/PackageSidebar/index.jsx
+++ b/src/webui/src/components/PackageSidebar/index.jsx
@@ -32,7 +32,9 @@ export default class PackageSidebar extends React.Component {
let packageMeta;
try {
- packageMeta = (await API.get(`sidebar/${packageName}`)).data;
+ packageMeta = await API.request(`sidebar/${packageName}`, 'GET').then(function(response) {
+ return response.json();
+ });
} catch (err) {
this.setState({
failed: true
diff --git a/src/webui/src/modules/detail/index.jsx b/src/webui/src/modules/detail/index.jsx
index 744b24ce8..acd93be16 100644
--- a/src/webui/src/modules/detail/index.jsx
+++ b/src/webui/src/modules/detail/index.jsx
@@ -47,9 +47,9 @@ export default class Detail extends React.Component {
});
try {
- const resp = await API.get(`package/readme/${packageName}`);
+ const resp = await API.request(`package/readme/${packageName}`, 'GET').then((response) => response.text());
this.setState({
- readMe: resp.data
+ readMe: resp
});
} catch (err) {
this.setState({
diff --git a/src/webui/src/modules/home/index.js b/src/webui/src/modules/home/index.js
index d055cf623..8fcc17083 100644
--- a/src/webui/src/modules/home/index.js
+++ b/src/webui/src/modules/home/index.js
@@ -52,11 +52,11 @@ export default class Home extends React.Component {
async loadPackages() {
try {
- this.req = await API.get('packages');
+ this.req = await API.request('packages', 'GET').then((response) => response.json());
if (this.state.query === '') {
this.setState({
- packages: this.req.data,
+ packages: this.req,
loading: false
});
}
@@ -71,12 +71,12 @@ export default class Home extends React.Component {
async searchPackage(query) {
try {
- this.req = await API.get(`/search/${query}`);
+ this.req = await API.request(`/search/${query}`, 'GET').then((response) => response.json());
// Implement cancel feature later
if (this.state.query === query) {
this.setState({
- packages: this.req.data,
+ packages: this.req,
fistTime: false,
loading: false
});
diff --git a/src/webui/utils/api.js b/src/webui/utils/api.js
index 7995bc4d2..084738dfd 100644
--- a/src/webui/utils/api.js
+++ b/src/webui/utils/api.js
@@ -1,34 +1,34 @@
import storage from './storage';
-import axios from 'axios';
class API {
- constructor() {
- ['get', 'delete', 'post', 'put', 'patch'].map((method) => {
- this[method] = (url, options = {}) => {
- if (!window.VERDACCIO_API_URL) {
- throw new Error('VERDACCIO_API_URL is not defined!');
+ request(url, method = 'GET', options = {}) {
+ if (!window.VERDACCIO_API_URL) {
+ throw new Error('VERDACCIO_API_URL is not defined!');
+ }
+
+ const token = storage.getItem('token');
+ if (token) {
+ if (!options.headers) options.headers = {};
+
+ options.headers.authorization = token;
+ }
+
+ if (!['http://', 'https://', '//'].some((prefix) => url.startsWith(prefix))) {
+ url = window.VERDACCIO_API_URL + url;
+ }
+
+ function handleErrors(response) {
+ if (!response.ok) {
+ throw Error(response.statusText);
}
+ return response;
+ }
- const token = storage.getItem('token');
- if (token) {
- if (!options.headers) options.headers = {};
-
- options.headers.authorization = token;
- }
-
- if (!['http://', 'https://', '//'].some((prefix) => url.startsWith(prefix))) {
- url = window.VERDACCIO_API_URL + url;
- }
-
- return axios.request({
- method,
- url,
- ...options
- });
- };
- });
- }
+ return fetch(url, {
+ method,
+ ...options
+ }).then(handleErrors);
+ }
}
-
export default new API();
diff --git a/test/webui/components/PackageSidebar/packageSidebar.spec.js b/test/webui/components/PackageSidebar/packageSidebar.spec.js
index 3db1a4f09..e64059511 100644
--- a/test/webui/components/PackageSidebar/packageSidebar.spec.js
+++ b/test/webui/components/PackageSidebar/packageSidebar.spec.js
@@ -8,7 +8,7 @@ import PackageSidebar from '../../../../src/webui/src/components/PackageSidebar'
import { packageMeta } from '../store/packageMeta';
jest.mock('../../../../src/webui/utils/api', () => ({
- get: require('../__mocks__/api').default.get
+ request: require('../__mocks__/api').default.request,
}));
console.error = jest.fn();
@@ -18,7 +18,7 @@ describe(' component', () => {
const wrapper = mount();
const { loadPackageData } = wrapper.instance();
expect(console.error).toBeCalled();
- loadPackageData().then(response => {
+ loadPackageData().catch(response => {
expect(response).toBeUndefined();
expect(wrapper.state()).toEqual({ failed: true });
});
diff --git a/test/webui/components/__mocks__/api.js b/test/webui/components/__mocks__/api.js
index d89c2b875..2c8e2cf3e 100644
--- a/test/webui/components/__mocks__/api.js
+++ b/test/webui/components/__mocks__/api.js
@@ -10,29 +10,36 @@ import { packageMeta } from '../store/packageMeta';
* @param {string} endpoint
* @returns {Promise}
*/
-const register = (method = 'get', endpoint, config = {}) => {
+const register = (url, method = 'get', options = {}) => {
- if (endpoint === 'login' && method === 'post') {
- return login(config);
+ if (url === 'login' && method.toLocaleLowerCase() === 'post') {
+ return login(options);
}
- if (endpoint === 'logo' && method === 'get') {
+ if (url === 'logo' && method.toLocaleLowerCase() === 'get') {
return logo();
}
- if (endpoint === 'sidebar/verdaccio' && method === 'get') {
- return Promise.resolve({ data: packageMeta });
+ if (url === 'sidebar/verdaccio' && method.toLocaleLowerCase() === 'get') {
+ return new Promise(function(resolve) {
+ resolve({
+ json: function() {
+ return packageMeta;
+ }
+ });
+ });
}
- return Promise.reject({ status: 404, data: 'Not found' });
+ throw Error('Not found');
};
/**
* Bind API methods
*/
-const API = ['get', 'post'].reduce((api, method) => {
- api[method] = register.bind(null, method);
- return api;
-}, {});
+class API {
+ request() {
+ return register.call(null, ...arguments);
+ }
+}
-export default API;
+export default new API;
diff --git a/test/webui/components/header.spec.js b/test/webui/components/header.spec.js
index 82de9d3e2..e567375cf 100644
--- a/test/webui/components/header.spec.js
+++ b/test/webui/components/header.spec.js
@@ -8,8 +8,7 @@ import { BrowserRouter } from 'react-router-dom';
import storage from '../../../src/webui/utils/storage';
jest.mock('../../../src/webui/utils/api', () => ({
- get: require('./__mocks__/api').default.get,
- post: require('./__mocks__/api').default.post
+ request: require('./__mocks__/api').default.request,
}));
describe(' component shallow', () => {
@@ -81,15 +80,15 @@ describe(' component shallow', () => {
it('handleSubmit - login should failed with 401', () => {
const HeaderWrapper = wrapper.find(Header).dive();
const handleSubmit = HeaderWrapper.instance().handleSubmit;
- const error = {
+ const errorObject = {
title: 'Unable to login',
type: 'error',
description: 'Unauthorized'
};
HeaderWrapper.setState({ username: 'sam', password: '12345' });
- handleSubmit().then(() => {
- expect(HeaderWrapper.state('loginError')).toEqual(error);
+ handleSubmit().catch((error) => {
+ expect(HeaderWrapper.state('loginError')).toEqual(errorObject);
});
});
diff --git a/test/webui/components/store/login.js b/test/webui/components/store/login.js
index d69821465..35f6897fc 100644
--- a/test/webui/components/store/login.js
+++ b/test/webui/components/store/login.js
@@ -5,21 +5,20 @@
*/
export default function(config) {
return new Promise(function(resolve, reject) {
- if (config.data.username === 'sam' && config.data.password === '1234') {
- resolve({
- status: 200,
- data: {
- username: 'sam',
- token: 'TEST_TOKEN'
- }
+ const body = JSON.parse(config.body);
+ if (body.username === 'sam' && body.password === '1234') {
+ return new Promise(function(resolve) {
+ resolve({
+ json: function() {
+ return {
+ username: 'sam',
+ token: 'TEST_TOKEN'
+ }
+ }
+ });
});
} else {
- reject({
- response: {
- status: 401,
- data: { error: 'Unauthorized' }
- }
- });
+ throw Error('Unauthorized');
}
});
}
diff --git a/test/webui/components/store/logo.js b/test/webui/components/store/logo.js
index 0e721525d..74162df22 100644
--- a/test/webui/components/store/logo.js
+++ b/test/webui/components/store/logo.js
@@ -4,7 +4,7 @@
*/
export default function() {
const response = {
- data: 'http://xyz.com/image.jpg'
+ url: 'http://xyz.com/image.jpg'
};
return Promise.resolve(response);
}
diff --git a/tools/webpack.dev.config.babel.js b/tools/webpack.dev.config.babel.js
index ef063a0e9..cfd989e4f 100644
--- a/tools/webpack.dev.config.babel.js
+++ b/tools/webpack.dev.config.babel.js
@@ -10,6 +10,7 @@ export default {
...baseConfig,
entry: {
main: [
+ 'whatwg-fetch',
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:4872',
'webpack/hot/only-dev-server',
@@ -22,6 +23,8 @@ export default {
publicPath: '/',
},
+ devtool: 'cheap-module-eval-source-map',
+
plugins: [
new webpack.DefinePlugin({
__DEBUG__: true,
diff --git a/tools/webpack.prod.config.babel.js b/tools/webpack.prod.config.babel.js
index 9107562f9..610bd630f 100644
--- a/tools/webpack.prod.config.babel.js
+++ b/tools/webpack.prod.config.babel.js
@@ -9,7 +9,7 @@ import getPackageVersion from './getPackageVersion';
const prodConf = {
entry: {
- main: ['babel-polyfill', `${env.SRC_ROOT}/webui/src/index.js`],
+ main: ['babel-polyfill', 'whatwg-fetch', `${env.SRC_ROOT}/webui/src/index.js`],
},
module: {
diff --git a/yarn.lock b/yarn.lock
index 9e28deee6..5ec019813 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -601,13 +601,6 @@ aws4@^1.2.1, aws4@^1.6.0:
version "1.6.0"
resolved "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
-axios@0.18.0:
- version "0.18.0"
- resolved "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
- dependencies:
- follow-redirects "^1.3.0"
- is-buffer "^1.1.5"
-
babel-cli@6.26.0:
version "6.26.0"
resolved "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1"
@@ -3600,12 +3593,6 @@ flow-runtime@0.17.0:
version "0.17.0"
resolved "https://registry.npmjs.org/flow-runtime/-/flow-runtime-0.17.0.tgz#ff57dd22bd7b0682c7beff20c3590f6a4a8286e3"
-follow-redirects@^1.3.0:
- version "1.4.1"
- resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz#d8120f4518190f55aac65bb6fc7b85fcd666d6aa"
- dependencies:
- debug "^3.1.0"
-
for-in@^0.1.3:
version "0.1.8"
resolved "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
@@ -9123,7 +9110,7 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
dependencies:
iconv-lite "0.4.19"
-whatwg-fetch@>=0.10.0:
+whatwg-fetch@2.0.3, whatwg-fetch@>=0.10.0:
version "2.0.3"
resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"