Skip to content

Commit

Permalink
feat: allow admin to sync package only (#434)
Browse files Browse the repository at this point in the history
closes #412
  • Loading branch information
hezhengxu2018 authored Apr 6, 2023
1 parent 52a60ca commit c5ac715
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 6 deletions.
1 change: 1 addition & 0 deletions app/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const LATEST_TAG = 'latest';
export const GLOBAL_WORKER = 'GLOBAL_WORKER';
export enum SyncMode {
none = 'none',
admin = 'admin',
exist = 'exist',
all = 'all',
}
Expand Down
7 changes: 4 additions & 3 deletions app/port/controller/AbstractController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { UserService } from '../../core/service/UserService';
import {
VersionRule,
} from '../typebox';
import { SyncMode } from '../../common/constants';

class PackageNotFoundError extends NotFoundError {}

Expand All @@ -43,7 +44,7 @@ export abstract class AbstractController extends MiddlewareController {
}

protected get enableSync() {
return this.config.cnpmcore.syncMode === 'all' || this.config.cnpmcore.syncMode === 'exist';
return this.config.cnpmcore.syncMode !== SyncMode.none;
}

protected isPrivateScope(scope: string) {
Expand Down Expand Up @@ -104,8 +105,8 @@ export abstract class AbstractController extends MiddlewareController {
const [ scope ] = getScopeAndName(fullname);
// dont sync private scope
if (!this.isPrivateScope(scope)) {
// syncMode = none, redirect public package to source registry
if (!this.enableSync) {
// syncMode = none/admin, redirect public package to source registry
if (!this.enableSync && this.config.cnpmcore.syncMode !== SyncMode.admin) {
if (this.redirectNotFound) {
err.redirectToSourceRegistry = this.sourceRegistry;
}
Expand Down
5 changes: 5 additions & 0 deletions app/port/controller/PackageSyncController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { PackageSyncerService } from '../../core/service/PackageSyncerService';
import { RegistryManagerService } from '../../core/service/RegistryManagerService';
import { TaskState } from '../../common/enum/Task';
import { SyncPackageTaskRule, SyncPackageTaskType } from '../typebox';
import { SyncMode } from '../../common/constants';

@HTTPController()
export class PackageSyncController extends AbstractController {
Expand Down Expand Up @@ -60,6 +61,10 @@ export class PackageSyncController extends AbstractController {
const tips = data.tips || `Sync cause by "${ctx.href}", parent traceId: ${ctx.tracer.traceId}`;
const isAdmin = await this.userRoleManager.isAdmin(ctx);

if (this.config.cnpmcore.syncMode === SyncMode.admin && !isAdmin) {
throw new ForbiddenError('Only admin allow to sync package');
}

const params = {
fullname,
tips,
Expand Down
4 changes: 3 additions & 1 deletion app/port/schedule/CheckRecentlyUpdatedPackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Inject } from '@eggjs/tegg';
import { PackageSyncerService } from '../../core/service/PackageSyncerService';
import { PackageRepository } from '../../repository/PackageRepository';
import { getScopeAndName } from '../../common/PackageUtil';
import { SyncMode } from '../../common/constants';

// https://github.com/cnpm/cnpmcore/issues/9
@Schedule<IntervalParams>({
Expand All @@ -29,7 +30,8 @@ export class CheckRecentlyUpdatedPackages {
private readonly httpclient: EggHttpClient;

async subscribe() {
if (this.config.cnpmcore.syncMode === 'none' || !this.config.cnpmcore.enableCheckRecentlyUpdated) return;
const notAllowUpdateModeList = [ SyncMode.none, SyncMode.admin ];
if (notAllowUpdateModeList.includes(this.config.cnpmcore.syncMode) || !this.config.cnpmcore.enableCheckRecentlyUpdated) return;
const pageSize = 36;
const pageCount = this.config.env === 'unittest' ? 2 : 5;
for (let pageIndex = 0; pageIndex < pageCount; pageIndex++) {
Expand Down
3 changes: 2 additions & 1 deletion app/port/schedule/SyncPackageWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { EggAppConfig, EggLogger } from 'egg';
import { IntervalParams, Schedule, ScheduleType } from '@eggjs/tegg/schedule';
import { Inject } from '@eggjs/tegg';
import { PackageSyncerService } from '../../core/service/PackageSyncerService';
import { SyncMode } from '../../common/constants';


let executingCount = 0;
Expand All @@ -23,7 +24,7 @@ export class SyncPackageWorker {
private readonly logger: EggLogger;

async subscribe() {
if (this.config.cnpmcore.syncMode === 'none') return;
if (this.config.cnpmcore.syncMode === SyncMode.none) return;
if (executingCount >= this.config.cnpmcore.syncPackageWorkerMaxConcurrentTasks) return;

executingCount++;
Expand Down
3 changes: 2 additions & 1 deletion config/config.default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export default (appInfo: EggAppConfig) => {
sourceRegistrySyncTimeout: 180000,
taskQueueHighWaterSize: 100,
// sync mode
// - none: don't sync npm package, just redirect it to sourceRegistry
// - none: don't sync npm package
// - admin: don't sync npm package,only admin can create sync task by sync contorller.
// - all: sync all npm packages
// - exist: only sync exist packages, effected when `enableCheckRecentlyUpdated` or `enableChangesStream` is enabled
syncMode: SyncMode.none,
Expand Down
34 changes: 34 additions & 0 deletions test/port/controller/PackageSyncController/createSyncTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ describe('test/port/controller/PackageSyncController/createSyncTask.test.ts', ()
assert(res.body.error === '[FORBIDDEN] Not allow to sync package');
});

it('should 403 when syncMode = admin', async () => {
mock(app.config.cnpmcore, 'syncMode', 'admin');
const res = await app.httpRequest()
.put('/-/package/koa/syncs')
.expect(403);
assert(res.body.error === '[FORBIDDEN] Only admin allow to sync package');
});

it('should 201 when syncMode = admin & login as admin', async () => {
mock(app.config.cnpmcore, 'syncMode', 'admin');
const adminUser = await TestUtil.createAdmin();
await app.httpRequest()
.put('/-/package/koa/syncs')
.set('authorization', adminUser.authorization)
.expect(201);
});

it('should 401 if user not login when alwaysAuth = true', async () => {
mock(app.config.cnpmcore, 'alwaysAuth', true);
const res = await app.httpRequest()
Expand Down Expand Up @@ -315,6 +332,23 @@ describe('test/port/controller/PackageSyncController/createSyncTask.test.ts', ()
assert(res.body.error === '[FORBIDDEN] Not allow to sync package');
});

it('should 403 when syncMode = admin', async () => {
mock(app.config.cnpmcore, 'syncMode', 'admin');
const res = await app.httpRequest()
.put('/koa/sync')
.expect(403);
assert(res.body.error === '[FORBIDDEN] Only admin allow to sync package');
});

it('should 201 when syncMode = admin & login as admin', async () => {
mock(app.config.cnpmcore, 'syncMode', 'admin');
const adminUser = await TestUtil.createAdmin();
await app.httpRequest()
.put('/koa/sync')
.set('authorization', adminUser.authorization)
.expect(201);
});

it('should 201', async () => {
let res = await app.httpRequest()
.put('/koa/sync')
Expand Down

0 comments on commit c5ac715

Please sign in to comment.