diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc65f09ef..ddc865203 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,16 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+## [3.8.2](https://github.com/verdaccio/verdaccio/compare/v3.8.1...v3.8.2) (2018-09-27)
+
+
+### Bug Fixes
+
+* normalize contributors field [#1022](https://github.com/verdaccio/verdaccio/issues/1022) ([#1024](https://github.com/verdaccio/verdaccio/issues/1024)) ([4deefe7](https://github.com/verdaccio/verdaccio/commit/4deefe7))
+
+
+
## [3.8.1](https://github.com/verdaccio/verdaccio/compare/v3.8.0...v3.8.1) (2018-09-10)
diff --git a/package.json b/package.json
index 1aacd1a32..2612feefe 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "verdaccio",
- "version": "3.8.1",
+ "version": "3.8.2",
"description": "Private npm repository server",
"author": {
"name": "Alex Kocharin",
@@ -56,7 +56,7 @@
"@commitlint/config-conventional": "7.1.2",
"@material-ui/core": "3.1.0",
"@material-ui/icons": "3.0.1",
- "@verdaccio/types": "3.7.1",
+ "@verdaccio/types": "3.7.2",
"babel-cli": "6.26.0",
"babel-core": "6.26.3",
"babel-eslint": "10.0.0",
diff --git a/src/lib/local-storage.js b/src/lib/local-storage.js
index 49289a630..ac5bf45f9 100644
--- a/src/lib/local-storage.js
+++ b/src/lib/local-storage.js
@@ -8,7 +8,7 @@ import _ from 'lodash';
// $FlowFixMe
import {ErrorCode, isObject, getLatestVersion, tagVersion, validateName, DIST_TAGS} from './utils';
import {
- generatePackageTemplate, normalizePackage, generateRevision, getLatestReadme, cleanUpReadme,
+ generatePackageTemplate, normalizePackage, generateRevision, getLatestReadme, cleanUpReadme, normalizeContributors,
fileExist, noSuchFile, DEFAULT_REVISION, pkgFileName,
} from './storage-utils';
import {createTarballHash} from './crypto-utils';
@@ -138,6 +138,7 @@ class LocalStorage implements IStorage {
// we don't keep readmes for package versions,
// only one readme per package
version = cleanUpReadme(version);
+ version.contributors = normalizeContributors(version.contributors);
change = true;
packageLocalJson.versions[versionId] = version;
@@ -219,6 +220,7 @@ class LocalStorage implements IStorage {
// TODO: lodash remove
metadata = cleanUpReadme(metadata);
+ metadata.contributors = normalizeContributors(metadata.contributors);
if (data.versions[version] != null) {
return cb( ErrorCode.getConflict() );
diff --git a/src/lib/storage-utils.js b/src/lib/storage-utils.js
index 4d20a3a65..715037fb2 100644
--- a/src/lib/storage-utils.js
+++ b/src/lib/storage-utils.js
@@ -5,7 +5,7 @@ import {ErrorCode, isObject, normalizeDistTags, DIST_TAGS, semverSort} from './u
import Search from './search';
import {generateRandomHexString} from '../lib/crypto-utils';
-import type {Package, Version} from '@verdaccio/types';
+import type {Package, Version, Author} from '@verdaccio/types';
import type {IStorage} from '../../types';
import {API_ERROR, HTTP_STATUS} from './constants';
@@ -99,7 +99,15 @@ function cleanUpReadme(version: Version): Version {
return version;
}
-export const WHITELIST = ['_rev', 'name', 'versions', DIST_TAGS, 'readme', 'time'];
+export function normalizeContributors(contributors: Array): Array {
+ if (isObject(contributors) || _.isString(contributors)) {
+ return [((contributors): any)];
+ }
+
+ return contributors;
+}
+
+export const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time'];
export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Package {
const propertyToKeep = [...WHITELIST];
diff --git a/src/lib/utils.js b/src/lib/utils.js
index 1bdab933f..909746fce 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -17,11 +17,12 @@ import {
DEFAULT_PROTOCOL,
CHARACTER_ENCODING, HEADERS
} from './constants';
-import {generateGravatarUrl} from '../utils/user';
+import {generateGravatarUrl, GRAVATAR_DEFAULT} from '../utils/user';
import type {Package} from '@verdaccio/types';
import type {$Request} from 'express';
import type {StringValue} from '../../types';
+import {normalizeContributors} from './storage-utils';
const Logger = require('./logger');
const pkginfo = require('pkginfo')(module); // eslint-disable-line no-unused-vars
@@ -482,7 +483,7 @@ export function deleteProperties(propertiesToDelete: Array, objectItem:
export function addGravatarSupport(pkgInfo: Object): Object {
const pkgInfoCopy = {...pkgInfo};
const author = _.get(pkgInfo, 'latest.author', null);
- const contributors = _.get(pkgInfo, 'latest.contributors', []);
+ const contributors = normalizeContributors(_.get(pkgInfo, 'latest.contributors', []));
const maintainers = _.get(pkgInfo, 'latest.maintainers', []);
// for author.
@@ -501,7 +502,17 @@ export function addGravatarSupport(pkgInfo: Object): Object {
// for contributors
if (_.isEmpty(contributors) === false) {
pkgInfoCopy.latest.contributors = contributors.map((contributor) => {
- contributor.avatar = generateGravatarUrl(contributor.email);
+ if (isObject(contributor)) {
+ // $FlowFixMe
+ contributor.avatar = generateGravatarUrl(contributor.email);
+ } else if (_.isString(contributor)) {
+ contributor = {
+ avatar: GRAVATAR_DEFAULT,
+ email: contributor,
+ name: contributor,
+ };
+ }
+
return contributor;
});
}
diff --git a/test/unit/api/utils.spec.js b/test/unit/api/utils.spec.js
index 909494828..552966140 100644
--- a/test/unit/api/utils.spec.js
+++ b/test/unit/api/utils.spec.js
@@ -396,35 +396,82 @@ describe('Utilities', () => {
expect(addGravatarSupport(packageInfo)).toEqual(packageInfo);
});
- test('contributors field has contributors', () => {
- const packageInfo = {
- latest: {
- contributors: [
- { name: 'user', email: 'user@verdccio.org' },
- { name: 'user1', email: 'user1@verdccio.org' }
- ]
- }
- };
+ describe("contributors", () => {
+ test('contributors field has contributors', () => {
+ const packageInfo = {
+ latest: {
+ contributors: [
+ { name: 'user', email: 'user@verdccio.org' },
+ { name: 'user1', email: 'user1@verdccio.org' }
+ ]
+ }
+ };
- const result = {
- latest: {
- contributors: [
- {
- avatar:
- 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
- email: 'user@verdccio.org',
- name: 'user'
- },
- {
- avatar:
- 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762',
- email: 'user1@verdccio.org',
- name: 'user1'
- }
- ]
- }
- };
- expect(addGravatarSupport(packageInfo)).toEqual(result);
+ const result = {
+ latest: {
+ contributors: [
+ {
+ avatar:
+ 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
+ email: 'user@verdccio.org',
+ name: 'user'
+ },
+ {
+ avatar:
+ 'https://www.gravatar.com/avatar/51105a49ce4a9c2bfabf0f6a2cba3762',
+ email: 'user1@verdccio.org',
+ name: 'user1'
+ }
+ ]
+ }
+ };
+ expect(addGravatarSupport(packageInfo)).toEqual(result);
+ });
+
+ test('contributors field is an object', () => {
+ const packageInfo = {
+ latest: {
+ contributors: { name: 'user', email: 'user@verdccio.org' }
+ }
+ };
+
+ const result = {
+ latest: {
+ contributors: [
+ {
+ avatar: 'https://www.gravatar.com/avatar/794d7f6ef93d0689437de3c3e48fadc7',
+ email: 'user@verdccio.org',
+ name: 'user'
+ }
+ ]
+ }
+ };
+
+ expect(addGravatarSupport(packageInfo)).toEqual(result);
+ });
+
+ test('contributors field is a string', () => {
+ const contributor: string = 'Barney Rubble (http://barnyrubble.tumblr.com/)';
+ const packageInfo = {
+ latest: {
+ contributors: contributor
+ }
+ };
+
+ const result = {
+ latest: {
+ contributors: [
+ {
+ avatar: GRAVATAR_DEFAULT,
+ email: contributor,
+ name: contributor
+ }
+ ]
+ }
+ };
+
+ expect(addGravatarSupport(packageInfo)).toEqual(result);
+ });
});
test('maintainers field is a blank array', () => {
diff --git a/website/siteConfig.js b/website/siteConfig.js
index 72c24b823..83193ce75 100644
--- a/website/siteConfig.js
+++ b/website/siteConfig.js
@@ -56,7 +56,7 @@ const users = [
const siteConfig = {
title: 'Verdaccio' /* title for your website */,
- tagline: 'Verdaccio ยท A lightweight private npm proxy registry',
+ tagline: 'A lightweight private npm proxy registry',
url: 'https://verdaccio.org' /* your website url */,
organizationName: 'verdaccio',
cname: 'verdaccio.org',