diff --git a/package.json b/package.json index 7b97fa91f..68756399a 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "devDependencies": { "@commitlint/cli": "7.0.0", "@commitlint/config-conventional": "7.0.1", - "@verdaccio/types": "3.4.2", + "@verdaccio/types": "3.4.4", "babel-cli": "6.26.0", "babel-core": "6.26.3", "babel-eslint": "8.2.6", 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 3c7b818f3..1deba686a 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -14,11 +14,12 @@ import { DEFAULT_PORT, DEFAULT_DOMAIN, } 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 @@ -478,7 +479,7 @@ function deleteProperties(propertiesToDelete: Array, objectItem: any) { 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. @@ -497,7 +498,17 @@ 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 80ba8e31b..d4a6667a7 100644 --- a/test/unit/api/utils.spec.js +++ b/test/unit/api/utils.spec.js @@ -231,35 +231,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/yarn.lock b/yarn.lock index 2a6e9cc99..f38aadbc5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -259,9 +259,9 @@ version "1.0.0" resolved "https://registry.npmjs.org/@verdaccio/streams/-/streams-1.0.0.tgz#d5d24c6747208728b9fd16b908e3932c3fb1f864" -"@verdaccio/types@3.4.2": - version "3.4.2" - resolved "https://registry.npmjs.org/@verdaccio/types/-/types-3.4.2.tgz#e1b0952df73167428dbbe071663e72911df3404e" +"@verdaccio/types@3.4.4": + version "3.4.4" + resolved "https://registry.npmjs.org/@verdaccio/types/-/types-3.4.4.tgz#0f9190d715e25ec9baf04b2e4d0226e0be319b01" "@webassemblyjs/ast@1.5.13": version "1.5.13" @@ -6641,7 +6641,7 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -mv@^2.1.1, mv@~2: +mv@2.1.1, mv@~2: version "2.1.1" resolved "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" dependencies: