mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-30 22:34:10 -05:00
feat: add star and unstar api for 4.x
This commit is contained in:
parent
9c01aa4072
commit
1ab7c504ec
7 changed files with 121 additions and 4 deletions
|
@ -11,6 +11,7 @@ import { API_MESSAGE, HEADERS, DIST_TAGS, API_ERROR, HTTP_STATUS } from '../../.
|
|||
import { validateMetadata, isObject, ErrorCode } from '../../../lib/utils';
|
||||
import { media, expectJson, allow } from '../../middleware';
|
||||
import { notify } from '../../../lib/notify';
|
||||
import star from './star';
|
||||
|
||||
import type { Router } from 'express';
|
||||
import type { Config, Callback, MergeTags, Version } from '@verdaccio/types';
|
||||
|
@ -40,6 +41,7 @@ export default function publish(router: Router, auth: IAuth, storage: IStorageHa
|
|||
* Publish a package
|
||||
*/
|
||||
export function publishPackage(storage: IStorageHandler, config: Config) {
|
||||
const starApi = star(storage);
|
||||
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
||||
const packageName = req.params.package;
|
||||
/**
|
||||
|
@ -138,7 +140,7 @@ export function publishPackage(storage: IStorageHandler, config: Config) {
|
|||
};
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(req.body, '_rev') && isObject(req.body.users)) {
|
||||
return next(ErrorCode.getNotFound('npm star| un-star calls are not implemented'));
|
||||
return starApi(req, res, next);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
64
src/api/endpoint/api/star.js
Normal file
64
src/api/endpoint/api/star.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
// @flow
|
||||
|
||||
import { USERS, HTTP_STATUS } from '../../../lib/constants';
|
||||
import type {$Response} from 'express';
|
||||
import type {$RequestExtend, $NextFunctionVer, IStorageHandler} from '../../../../types';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default function(storage: IStorageHandler) {
|
||||
const validateInputs = (newUsers, localUsers, username, isStar) => {
|
||||
const isExistlocalUsers = _.isNil(localUsers[username]) === false;
|
||||
if (isStar && isExistlocalUsers && localUsers[username]) {
|
||||
return true;
|
||||
} else if (!isStar && isExistlocalUsers) {
|
||||
return false;
|
||||
} else if (!isStar && !isExistlocalUsers) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return (req: $RequestExtend, res: $Response, next: $NextFunctionVer): void => {
|
||||
const name = req.params.package;
|
||||
const afterChangePackage = function(err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.status(HTTP_STATUS.OK);
|
||||
next({
|
||||
success: true,
|
||||
});
|
||||
};
|
||||
|
||||
storage.getPackage({
|
||||
name,
|
||||
req,
|
||||
callback: function(err, info) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
const newStarUser = req.body[USERS];
|
||||
const remoteUsername = req.remote_user.name;
|
||||
const localStarUsers = info[USERS];
|
||||
// Check is star or unstar
|
||||
const isStar = Object.keys(newStarUser).includes(remoteUsername);
|
||||
if (_.isNil(localStarUsers) === false && validateInputs(newStarUser, localStarUsers, remoteUsername, isStar)) {
|
||||
return afterChangePackage();
|
||||
}
|
||||
const users = isStar ? {
|
||||
...localStarUsers,
|
||||
[remoteUsername]: true,
|
||||
} : _.reduce(localStarUsers, (users, value, key) => {
|
||||
if (key !== remoteUsername) {
|
||||
users[key] = value;
|
||||
}
|
||||
return users;
|
||||
}, {});
|
||||
storage.changePackage(name, { ...info, users}, req.body._rev, function(err) {
|
||||
afterChangePackage(err);
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
|
@ -10,6 +10,7 @@ export const DEFAULT_DOMAIN: string = 'localhost';
|
|||
export const TIME_EXPIRATION_24H: string = '24h';
|
||||
export const TIME_EXPIRATION_7D: string = '7d';
|
||||
export const DIST_TAGS = 'dist-tags';
|
||||
export const USERS = 'users';
|
||||
export const DEFAULT_MIN_LIMIT_PASSWORD: number = 3;
|
||||
export const DEFAULT_USER = 'Anonymous';
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import UrlNode from 'url';
|
|||
import _ from 'lodash';
|
||||
import { ErrorCode, isObject, getLatestVersion, tagVersion, validateName } from './utils';
|
||||
import { generatePackageTemplate, normalizePackage, generateRevision, getLatestReadme, cleanUpReadme, normalizeContributors } from './storage-utils';
|
||||
import { API_ERROR, DIST_TAGS, STORAGE } from './constants';
|
||||
import { API_ERROR, DIST_TAGS, STORAGE, USERS } from './constants';
|
||||
import { createTarballHash } from './crypto-utils';
|
||||
import { prepareSearchPackage } from './storage-utils';
|
||||
import loadPlugin from '../lib/plugin-loader';
|
||||
|
@ -334,6 +334,7 @@ class LocalStorage implements IStorage {
|
|||
}
|
||||
}
|
||||
|
||||
localData[USERS] = incomingPkg[USERS];
|
||||
localData[DIST_TAGS] = incomingPkg[DIST_TAGS];
|
||||
cb();
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ import { generateRandomHexString } from '../lib/crypto-utils';
|
|||
|
||||
import type { Package, Version, Author } from '@verdaccio/types';
|
||||
import type { IStorage } from '../../types';
|
||||
import { API_ERROR, HTTP_STATUS, DIST_TAGS, STORAGE } from './constants';
|
||||
import { API_ERROR, HTTP_STATUS, DIST_TAGS, USERS, STORAGE } from './constants';
|
||||
|
||||
export function generatePackageTemplate(name: string): Package {
|
||||
return {
|
||||
|
@ -18,6 +18,7 @@ export function generatePackageTemplate(name: string): Package {
|
|||
name,
|
||||
versions: {},
|
||||
time: {},
|
||||
[USERS]: {},
|
||||
[DIST_TAGS]: {},
|
||||
_uplinks: {},
|
||||
_distfiles: {},
|
||||
|
@ -97,7 +98,7 @@ export function normalizeContributors(contributors: Array<Author>): Array<Author
|
|||
return contributors;
|
||||
}
|
||||
|
||||
export const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time', '_id'];
|
||||
export const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time', '_id', 'users'];
|
||||
|
||||
export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Package {
|
||||
const propertyToKeep = [...WHITELIST];
|
||||
|
|
|
@ -5,6 +5,7 @@ import rimraf from 'rimraf';
|
|||
|
||||
import configDefault from '../partials/config/index';
|
||||
import publishMetadata from '../partials/publish-api';
|
||||
import starMetadata from '../partials/star-api';
|
||||
import endPointAPI from '../../../src/api/index';
|
||||
|
||||
import {HEADERS, API_ERROR, HTTP_STATUS, HEADER_TYPE, API_MESSAGE, TOKEN_BEARER} from '../../../src/lib/constants';
|
||||
|
@ -561,6 +562,46 @@ describe('endpoint unit test', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('should test star api', () => {
|
||||
test('should star a package', (done) => {
|
||||
request(app)
|
||||
.put('/@scope%2fpk1-test')
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify({
|
||||
...starMetadata,
|
||||
users: {
|
||||
[credentials.name]: true
|
||||
}
|
||||
}))
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
expect(err).toBeNull();
|
||||
return done(err);
|
||||
}
|
||||
expect(res.body.success).toBeDefined();
|
||||
expect(res.body.success).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should unstar a package', (done) => {
|
||||
request(app)
|
||||
.put('/@scope%2fpk1-test')
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify(starMetadata))
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
expect(err).toBeNull();
|
||||
return done(err);
|
||||
}
|
||||
expect(res.body.success).toBeDefined();
|
||||
expect(res.body.success).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
test('should unpublish a new package with credentials', async (done) => {
|
||||
|
||||
const credentials = { name: 'jota_unpublish', password: 'secretPass' };
|
||||
|
|
7
test/unit/partials/star-api.js
Normal file
7
test/unit/partials/star-api.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
const json = {
|
||||
"_id": "@scope\/pk1-test",
|
||||
"_rev": "4-6abcdb4efd41a576",
|
||||
"users": {}
|
||||
}
|
||||
|
||||
module.exports = json;
|
Loading…
Reference in a new issue