From 9353fc37d5664e08b1e7e1e1eed463e787d1ad4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Louz=C3=A1n?= Date: Fri, 3 Aug 2018 20:36:21 +0200 Subject: [PATCH 1/3] feat: gitlab-11.2-group-api-improvements - use the new gitlab 11.2 `min_access_level` parameter in the groups api: publish rights are now configurable based on the access level of the user to the groups, it doesn't require owner permissions - add new configuration parameters for `access` and `publish` access levels --- README.md | 11 +++- conf/docker.yaml | 4 +- conf/localhost.yaml | 37 ++++++++++++ docker-compose.yml | 2 +- src/authcache.js | 15 +++-- src/gitlab.js | 134 +++++++++++++++++++++++++++++++++----------- 6 files changed, 160 insertions(+), 43 deletions(-) create mode 100644 conf/localhost.yaml diff --git a/README.md b/README.md index 81111d4..add9bd6 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,16 @@ the following: - no admin token required - user authenticates with Personal Access Token -- owned groups (no subgroups) are added to the user -- publish packages if package scope or name is an owned group name +- access & publish packages if package scope or name match a gitlab + group for which the user has appropriate permissions > This is experimental! +## Gitlab Version Compatibility + +Gitlab 11.2+ is required due to usage of the `v4` api version and +the granular group api `min_access_level` query param + ## Use it You need at least node version 8.x.x, codename **carbon**. @@ -47,6 +52,8 @@ auth: authCache: enabled: true ttl: 300 + access: $reporter + publish: $maintainer uplinks: npmjs: diff --git a/conf/docker.yaml b/conf/docker.yaml index cb5f79c..92ce663 100644 --- a/conf/docker.yaml +++ b/conf/docker.yaml @@ -11,6 +11,8 @@ auth: authCache: enabled: true ttl: 300 + access: $reporter + publish: $maintainer uplinks: npmjs: @@ -31,5 +33,5 @@ packages: gitlab: true logs: - - {type: stdout, format: pretty, level: info } + - { type: stdout, format: pretty, level: info } #- {type: file, path: verdaccio.log, level: info} diff --git a/conf/localhost.yaml b/conf/localhost.yaml new file mode 100644 index 0000000..e400fdb --- /dev/null +++ b/conf/localhost.yaml @@ -0,0 +1,37 @@ +storage: /tmp/storage/data + +plugins: /tmp/plugins + +listen: + - 0.0.0.0:4873 + +auth: + gitlab: + url: http://localhost:50080 + authCache: + enabled: true + ttl: 300 + access: $reporter + publish: $maintainer + +uplinks: + npmjs: + url: https://registry.npmjs.org/ + +packages: + '@*/*': + # scoped packages + access: $all + publish: $authenticated + proxy: npmjs + gitlab: true + + '**': + access: $all + publish: $authenticated + proxy: npmjs + gitlab: true + +logs: + - { type: stdout, format: pretty, level: trace } + #- {type: file, path: verdaccio.log, level: info} diff --git a/docker-compose.yml b/docker-compose.yml index 63dcc7c..3ed9811 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: gitlab: - image: 'gitlab/gitlab-ce:latest' + image: 'gitlab/gitlab-ce:nightly' restart: always environment: - GITLAB_ROOT_PASSWORD=verdaccio diff --git a/src/authcache.js b/src/authcache.js index 4c82aa6..2752dfa 100644 --- a/src/authcache.js +++ b/src/authcache.js @@ -24,7 +24,7 @@ export class AuthCache { }); this.storage.on('expired', (key, value) => { if (this.logger.trace()) { - this.logger.trace(`[gitlab] expired key: ${key} with value: ${value}`); + this.logger.trace(`[gitlab] expired key: ${key} with value:`, value); } }); } @@ -45,15 +45,20 @@ export class AuthCache { } +export type UserDataGroups = { + access: string[], + publish: string[] +}; + export class UserData { _username: string; - _groups: string[]; + _groups: UserDataGroups; get username(): string { return this._username; } - get groups(): string[] { return this._groups; } - set groups(groups: string[]) { this._groups = groups; } + get groups(): UserDataGroups { return this._groups; } + set groups(groups: UserDataGroups) { this._groups = groups; } - constructor(username: string, groups: string[]) { + constructor(username: string, groups: UserDataGroups) { this._username = username; this._groups = groups; } diff --git a/src/gitlab.js b/src/gitlab.js index 73b2ac7..cafdebe 100644 --- a/src/gitlab.js +++ b/src/gitlab.js @@ -2,29 +2,50 @@ // SPDX-License-Identifier: MIT // @flow +import type { Callback, IPluginAuth, Logger, PluginOptions, RemoteUser, PackageAccess } from '@verdaccio/types'; +import type { UserDataGroups } from './authcache'; + import Gitlab from 'gitlab'; import { AuthCache, UserData } from './authcache'; import httperror from 'http-errors'; -import type { Callback, Config, IPluginAuth, Logger, PluginOptions, RemoteUser, PackageAccess } from '@verdaccio/types'; -export type VerdaccioGitlabConfig = Config & { +export type VerdaccioGitlabAccessLevel = + '$guest' | + '$reporter' | + '$developer' | + '$maintainer' | + '$owner'; + +export type VerdaccioGitlabConfig = { url: string, authCache?: { enabled?: boolean, ttl?: number - } + }, + access?: VerdaccioGitlabAccessLevel, + publish?: VerdaccioGitlabAccessLevel }; -type VerdaccioGitlabPackageAccess = PackageAccess & { +export type VerdaccioGitlabPackageAccess = PackageAccess & { name: string, gitlab?: boolean } +const ACCESS_LEVEL_MAPPING = { + $guest: 10, + $reporter: 20, + $developer: 30, + $maintainer: 40, + $owner: 50 +}; + export default class VerdaccioGitLab implements IPluginAuth { options: PluginOptions; config: VerdaccioGitlabConfig; authCache: AuthCache; logger: Logger; + accessLevel: VerdaccioGitlabAccessLevel; + publishLevel: VerdaccioGitlabAccessLevel; constructor( config: VerdaccioGitlabConfig, @@ -46,6 +67,17 @@ export default class VerdaccioGitLab implements IPluginAuth { this.logger.info(`[gitlab] initialized auth cache with ttl: ${ttl} seconds`); } + this.accessLevel = '$reporter'; + if (this.config.access) { + this.accessLevel = this.config.access; + } + this.logger.info(`[gitlab] access control level: ${this.config.access || ''}`); + + this.publishLevel = '$owner'; + if (this.config.publish) { + this.publishLevel = this.config.publish; + } + this.logger.info(`[gitlab] publish control level: ${this.config.publish || ''}`); } authenticate(user: string, password: string, cb: Callback) { @@ -55,8 +87,8 @@ export default class VerdaccioGitLab implements IPluginAuth { const cachedUserGroups = this._getCachedUserGroups(user, password); if (cachedUserGroups) { - this.logger.debug(`[gitlab] user: ${user} found in cache, authenticated with groups: ${cachedUserGroups.toString()}`); - return cb(null, cachedUserGroups); + this.logger.debug(`[gitlab] user: ${user} found in cache, authenticated with groups:`, cachedUserGroups); + return cb(null, cachedUserGroups.publish); } // Not found in cache, query gitlab @@ -67,28 +99,47 @@ export default class VerdaccioGitLab implements IPluginAuth { token: password }); - GitlabAPI.Users.current().then(response => { + const pUsers = GitlabAPI.Users.current(); + return pUsers.then(response => { if (user !== response.username) { return cb(httperror[401]('wrong gitlab username')); } - // Set the groups of an authenticated user to themselves and all gitlab projects of which they are an owner - let ownedGroups = [user]; - GitlabAPI.Groups.all({owned: true}).then(groups => { - for (let group of groups) { - if (group.path === group.full_path) { - ownedGroups.push(group.path); - } - } + const accessLevelId = this.config.access ? ACCESS_LEVEL_MAPPING[this.config.access] : null; + const publishLevelId = this.config.publish ? ACCESS_LEVEL_MAPPING[this.config.publish] : null; + + const userGroups = { + access: [user], + publish: [user] + }; + + // Set the groups of an authenticated user: + // - for access, themselves and all groups with access level $auth.gitlab.access configuration + // - for publish, themselves and all groups with access level $auth.gitlab.publish configuration + + const pAccessGroups = GitlabAPI.Groups.all({min_access_level: accessLevelId}).then(groups => { + this._addGroupsToArray(groups, userGroups.access); + }).catch(error => { + this.logger.error(`[gitlab] user: ${user} error querying access groups: ${error}`); + }); + + const pPublishGroups = GitlabAPI.Groups.all({min_access_level: publishLevelId}).then(groups => { + this._addGroupsToArray(groups, userGroups.publish); + }).catch(error => { + this.logger.error(`[gitlab] user: ${user} error querying publish groups: ${error}`); + }); - // Store found groups in cache - this._setCachedUserGroups(user, password, ownedGroups); - this.logger.trace(`[gitlab] saving data in cache for user: ${user}`); + const pGroups = Promise.all([pAccessGroups, pPublishGroups]); + return pGroups.then(() => { + this._setCachedUserGroups(user, password, userGroups); this.logger.info(`[gitlab] user: ${user} authenticated`); - this.logger.debug(`[gitlab] user: ${user} authenticated, with groups: ${ownedGroups.toString()}`); - return cb(null, ownedGroups); + this.logger.debug(`[gitlab] user: ${user} authenticated, with groups:`, userGroups); + return cb(null, userGroups.publish); + }).catch(error => { + this.logger.error(`[gitlab] error authenticating: ${error}`); }); + }).catch(error => { this.logger.info(`[gitlab] user: ${user} error authenticating: ${error.message || {}}`); if (error) { @@ -104,22 +155,24 @@ export default class VerdaccioGitLab implements IPluginAuth { allow_access(user: RemoteUser, _package: VerdaccioGitlabPackageAccess, cb: Callback) { if (!_package.gitlab) { return cb(); } + if ((_package.access || []).includes('$authenticated') && user.name !== undefined) { this.logger.debug(`[gitlab] allow user: ${user.name} access to package: ${_package.name}`); return cb(null, true); - } else if (! (_package.access || []).includes('$authenticated')) { + } else if (!(_package.access || []).includes('$authenticated')) { this.logger.debug(`[gitlab] allow unauthenticated access to package: ${_package.name}`); return cb(null, true); } else { this.logger.debug(`[gitlab] deny user: ${user.name || ''} access to package: ${_package.name}`); return cb(null, false); } + } allow_publish(user: RemoteUser, _package: VerdaccioGitlabPackageAccess, cb: Callback) { if (!_package.gitlab) { return cb(); } - let packageScopeOwner = false; - let packageOwner = false; + let packageScopePermit = false; + let packagePermit = false; // Only allow to publish packages when: // - the package has exactly the same name as one of the user groups, or @@ -127,37 +180,37 @@ export default class VerdaccioGitLab implements IPluginAuth { for (let real_group of user.real_groups) { // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers this.logger.trace(`[gitlab] publish: checking group: ${real_group} for user: ${user.name || ''} and package: ${_package.name}`); if (real_group === _package.name) { - packageOwner = true; + packagePermit = true; break; } else { if (_package.name.indexOf('@') === 0) { if (real_group === _package.name.slice(1, _package.name.lastIndexOf('/'))) { - packageScopeOwner = true; + packageScopePermit = true; break; } } } } - if (packageOwner === true) { - this.logger.debug(`[gitlab] user: ${user.name || ''} allowed to publish package: ${_package.name} as owner of package-name`); + if (packagePermit === true) { + this.logger.debug(`[gitlab] user: ${user.name || ''} allowed to publish package: ${_package.name} based on package-name`); return cb(null, false); } else { - if (packageScopeOwner === true) { - this.logger.debug(`[gitlab] user: ${user.name || ''} allowed to publish package: ${_package.name} as owner of package-scope`); + if (packageScopePermit === true) { + this.logger.debug(`[gitlab] user: ${user.name || ''} allowed to publish package: ${_package.name} based on package-scope`); return cb(null, false); } else { this.logger.debug(`[gitlab] user: ${user.name || ''} denied from publishing package: ${_package.name}`); if (_package.name.indexOf('@') === 0) { - return cb(httperror[403]('must be owner of package-scope')); + return cb(httperror[403](`must have required permissions: ${this.config.publish || ''} at package-scope`)); } else { - return cb(httperror[403]('must be owner of package-name')); + return cb(httperror[403](`must have required permissions: ${this.config.publish || ''} at package-name`)); } } } } - _getCachedUserGroups(username: string, password: string): ?string[] { + _getCachedUserGroups(username: string, password: string): ?UserDataGroups { if (! this.authCache) { return null; } @@ -165,7 +218,20 @@ export default class VerdaccioGitLab implements IPluginAuth { return (userData || {}).groups || null; } - _setCachedUserGroups(username: string, password: string, groups: string[]): boolean { - return this.authCache && this.authCache.storeUser(username, password, new UserData(username, groups)); + _setCachedUserGroups(username: string, password: string, groups: UserDataGroups): boolean { + if (! this.authCache) { + return false; + } + this.logger.trace(`[gitlab] saving data in cache for user: ${username}`); + return this.authCache.storeUser(username, password, new UserData(username, groups)); + } + + _addGroupsToArray(src: {path: string, full_path: string}[], dst: string[]) { + src.forEach(group => { + if (group.path === group.full_path) { + dst.push(group.path); + } + }); } + } From 68068bf1c96c4c82805d39d13d71e2b9c615e02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Louz=C3=A1n?= Date: Thu, 9 Aug 2018 19:53:30 +0200 Subject: [PATCH 2/3] feat: gitlab-11.2-group-api-improvements - remove `access` access level configuration parameter since it cannot be used with the current plugins api - support gitlab 9.0+ with a new `legacy_mode` configuration flag; when not in legacy mode, gitlab 11.2+ is required - improved README, document all configuration options --- README.md | 79 +++++++++++++++++++++++++++++++++------------ conf/docker.yaml | 1 - conf/localhost.yaml | 1 - src/authcache.js | 1 - src/gitlab.js | 62 ++++++++++++++++++----------------- 5 files changed, 91 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index add9bd6..467d09b 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,19 @@ as authentication provider for the private npm registry [![build](https://travis-ci.org/bufferoverflow/verdaccio-gitlab.svg?branch=master)](https://travis-ci.org/bufferoverflow/verdaccio-gitlab) [![dependencies](https://david-dm.org/bufferoverflow/verdaccio-gitlab/status.svg)](https://david-dm.org/bufferoverflow/verdaccio-gitlab) -The main goal and the difference from other sinopia/verdaccio plugins are +The main goal and differences from other sinopia/verdaccio plugins are the following: - no admin token required - user authenticates with Personal Access Token -- access & publish packages if package scope or name match a gitlab - group for which the user has appropriate permissions +- access & publish packages depending on user rights in gitlab > This is experimental! ## Gitlab Version Compatibility -Gitlab 11.2+ is required due to usage of the `v4` api version and -the granular group api `min_access_level` query param +- If `legacy_mode: false`: Gitlab 11.2+ +- If `legacy_mode: true`: Gitlab 9.0+ ## Use it @@ -49,11 +48,6 @@ listen: auth: gitlab: url: https://gitlab.com - authCache: - enabled: true - ttl: 300 - access: $reporter - publish: $maintainer uplinks: npmjs: @@ -99,13 +93,65 @@ yarn publish --registry http://localhost:4873 a GitLab group (as owner) which has the same name as your package name. You also need a fresh login, so that Verdaccio recognizes your owned groups. +## Access Levels + +Access and publish access rights depend on the mode used. + +In the default mode, packages are available: + +- *access* is allowed depending on verdaccio `package` configuration + directives (unauthenticated / authenticated) +- *publish* is allowed if the package name matches the logged in user + id, or if the package name / scope of the package matches one of the + user groups and the user has `$auth.gitlab.publish` access rights on + the group + +For instance, assuming the following configuration: + +- `auth.gitlab.publish` = `$maintainer` +- the gitlab user `sample_user` had access to group `group1` as + `$maintainer` and `group2` as `$reporter` +- then this user could publish any of the npm packages: + - `sample_user` + - any package under `group1/**` + - error if the user tries to publish any package under `group2/**` + +If using the legacy mode, the system behaves as in normal mode with +fixed `$auth.gitlab.publish` = `$owner` + +## Configuration Options + +The full set of configuration options is: + +```yaml +auth: + gitlab: + url: + authCache: + enabled: + ttl: + legacy_mode: + publish: +``` + + +| Option | Default | Type | Description | +| ------ | ------- | ---- | ----------- | +| `url` | `` | url | mandatory, the url of the gitlab server | +| `authCache: enabled` | `true` | boolean | activate in-memory authentication cache | +| `authCache: ttl` | `300` (`0`=unlimited) | integer | time-to-live of entries in the authentication cache, in seconds | +| `legacy_mode` | `false` | boolean | gitlab versions pre-11.2 do not support groups api queries based on access level; this enables the legacy behaviour of only allowing npm publish operations on groups where the logged in user has owner rights | +| `publish` | `$maintainer` | [`$guest`, `$reporter`, `$developer`, `$maintainer`, `$owner`] | group minimum access level of the logged in user required for npm publish operations (does not apply in legacy mode) | + + ## Authentication Cache In order to avoid too many authentication requests to the underlying gitlab instance, the plugin provides an in-memory cache that will save the detected groups of the users for a configurable ttl in seconds. -No clear-text password will be saved in-memory, just an SHA-256 hash -and the groups information. + +No clear-text password will is saved in-memory, just an SHA-256 hash of +the user+password, plus the groups information. By default, the cache will be enabled and the credentials will be stored for 300 seconds. The ttl is checked on access, but there's also an @@ -113,15 +159,6 @@ internal timer that will check expired values regularly, so data of users not actively interacting with the system will also be eventually invalidated. -```yaml -auth: - gitlab: - url: https://gitlab.com - authCache: - enabled: (default true) - ttl: (default: 300) -``` - *Please note* that this implementation is in-memory and not multi-process; if the cluster module is used for starting several verdaccio processes, each process will store its own copy of the cache, diff --git a/conf/docker.yaml b/conf/docker.yaml index 92ce663..756cb7b 100644 --- a/conf/docker.yaml +++ b/conf/docker.yaml @@ -11,7 +11,6 @@ auth: authCache: enabled: true ttl: 300 - access: $reporter publish: $maintainer uplinks: diff --git a/conf/localhost.yaml b/conf/localhost.yaml index e400fdb..bf7ee14 100644 --- a/conf/localhost.yaml +++ b/conf/localhost.yaml @@ -11,7 +11,6 @@ auth: authCache: enabled: true ttl: 300 - access: $reporter publish: $maintainer uplinks: diff --git a/src/authcache.js b/src/authcache.js index 2752dfa..6f37795 100644 --- a/src/authcache.js +++ b/src/authcache.js @@ -46,7 +46,6 @@ export class AuthCache { } export type UserDataGroups = { - access: string[], publish: string[] }; diff --git a/src/gitlab.js b/src/gitlab.js index cafdebe..ae2fae8 100644 --- a/src/gitlab.js +++ b/src/gitlab.js @@ -22,7 +22,7 @@ export type VerdaccioGitlabConfig = { enabled?: boolean, ttl?: number }, - access?: VerdaccioGitlabAccessLevel, + legacy_mode?: boolean, publish?: VerdaccioGitlabAccessLevel }; @@ -44,7 +44,6 @@ export default class VerdaccioGitLab implements IPluginAuth { config: VerdaccioGitlabConfig; authCache: AuthCache; logger: Logger; - accessLevel: VerdaccioGitlabAccessLevel; publishLevel: VerdaccioGitlabAccessLevel; constructor( @@ -56,7 +55,7 @@ export default class VerdaccioGitLab implements IPluginAuth { this.config = config; this.options = options; - this.logger.info(`[gitlab] gitlab url: ${this.config.url}`); + this.logger.info(`[gitlab] url: ${this.config.url}`); if ((this.config.authCache || {}).enabled === false) { this.logger.info('[gitlab] auth cache disabled'); @@ -67,17 +66,22 @@ export default class VerdaccioGitLab implements IPluginAuth { this.logger.info(`[gitlab] initialized auth cache with ttl: ${ttl} seconds`); } - this.accessLevel = '$reporter'; - if (this.config.access) { - this.accessLevel = this.config.access; - } - this.logger.info(`[gitlab] access control level: ${this.config.access || ''}`); + if (this.config.legacy_mode) { + this.publishLevel = '$owner'; - this.publishLevel = '$owner'; - if (this.config.publish) { - this.publishLevel = this.config.publish; + this.logger.info('[gitlab] legacy mode active pre-gitlab v11.2 active, publish is only allowed to group owners'); + } else { + this.publishLevel = '$maintainer'; + if (this.config.publish) { + this.publishLevel = this.config.publish; + } + + if (! Object.keys(ACCESS_LEVEL_MAPPING).includes(this.publishLevel)) { + throw Error(`[gitlab] invalid publish access level configuration: ${this.publishLevel}`); + } + this.logger.info(`[gitlab] publish control level: ${this.publishLevel}`); } - this.logger.info(`[gitlab] publish control level: ${this.config.publish || ''}`); + } authenticate(user: string, password: string, cb: Callback) { @@ -105,39 +109,39 @@ export default class VerdaccioGitLab implements IPluginAuth { return cb(httperror[401]('wrong gitlab username')); } - const accessLevelId = this.config.access ? ACCESS_LEVEL_MAPPING[this.config.access] : null; - const publishLevelId = this.config.publish ? ACCESS_LEVEL_MAPPING[this.config.publish] : null; - + const publishLevelId = ACCESS_LEVEL_MAPPING[this.publishLevel]; const userGroups = { - access: [user], publish: [user] }; - // Set the groups of an authenticated user: - // - for access, themselves and all groups with access level $auth.gitlab.access configuration - // - for publish, themselves and all groups with access level $auth.gitlab.publish configuration + // Set the groups of an authenticated user, in normal mode: + // - for access, depending on the package settings in verdaccio + // - for publish, the logged in user id and all the groups they can reach as configured with access level `$auth.gitlab.publish` + // + // In legacy mode, the groups are: + // - for access, themselves and all groups with access level $owner + // - for publish, the logged in user id and all the groups they can reach as `$owner` - const pAccessGroups = GitlabAPI.Groups.all({min_access_level: accessLevelId}).then(groups => { - this._addGroupsToArray(groups, userGroups.access); - }).catch(error => { - this.logger.error(`[gitlab] user: ${user} error querying access groups: ${error}`); - }); + const gitlabPublishQueryParams = this.config.legacy_mode ? { owned: true } : { min_access_level: publishLevelId }; + const pPublishGroups = GitlabAPI.Groups.all(gitlabPublishQueryParams).then(groups => { + this.logger.trace('[gitlab] querying gitlab user groups with params:', gitlabPublishQueryParams); - const pPublishGroups = GitlabAPI.Groups.all({min_access_level: publishLevelId}).then(groups => { this._addGroupsToArray(groups, userGroups.publish); }).catch(error => { this.logger.error(`[gitlab] user: ${user} error querying publish groups: ${error}`); + return cb(httperror[500]('error querying gitlab')); }); - const pGroups = Promise.all([pAccessGroups, pPublishGroups]); + const pGroups = Promise.all([pPublishGroups]); return pGroups.then(() => { this._setCachedUserGroups(user, password, userGroups); - this.logger.info(`[gitlab] user: ${user} authenticated`); - this.logger.debug(`[gitlab] user: ${user} authenticated, with groups:`, userGroups); + this.logger.info(`[gitlab] user: ${user} successfully authenticated`); + this.logger.debug(`[gitlab] user: ${user}, with groups:`, userGroups); return cb(null, userGroups.publish); }).catch(error => { this.logger.error(`[gitlab] error authenticating: ${error}`); + return cb(httperror[500]('error authenticating')); }); }).catch(error => { @@ -222,7 +226,7 @@ export default class VerdaccioGitLab implements IPluginAuth { if (! this.authCache) { return false; } - this.logger.trace(`[gitlab] saving data in cache for user: ${username}`); + this.logger.debug(`[gitlab] saving data in cache for user: ${username}`); return this.authCache.storeUser(username, password, new UserData(username, groups)); } From 207a490dc4d9da4784c69c0f5d428e08d96e01bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Louz=C3=A1n?= Date: Fri, 10 Aug 2018 12:15:03 +0200 Subject: [PATCH 3/3] feat: gitlab-11.2-group-api-improvements - remove spurious localhost tests configuration file - misc corrections in README --- README.md | 16 ++++++++-------- conf/localhost.yaml | 36 ------------------------------------ 2 files changed, 8 insertions(+), 44 deletions(-) delete mode 100644 conf/localhost.yaml diff --git a/README.md b/README.md index 467d09b..7ca2763 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ the following: ## Gitlab Version Compatibility -- If `legacy_mode: false`: Gitlab 11.2+ +- If `legacy_mode: false` or undefined (default mode): Gitlab 11.2+ - If `legacy_mode: true`: Gitlab 9.0+ ## Use it @@ -89,35 +89,35 @@ and publish packages: yarn publish --registry http://localhost:4873 ``` -> **NOTE**: In order to publish packages, you need to create or be part of -a GitLab group (as owner) which has the same name as your package name. You -also need a fresh login, so that Verdaccio recognizes your owned groups. - ## Access Levels Access and publish access rights depend on the mode used. +### Normal Mode + In the default mode, packages are available: - *access* is allowed depending on verdaccio `package` configuration directives (unauthenticated / authenticated) - *publish* is allowed if the package name matches the logged in user id, or if the package name / scope of the package matches one of the - user groups and the user has `$auth.gitlab.publish` access rights on + user groups and the user has `auth.gitlab.publish` access rights on the group For instance, assuming the following configuration: - `auth.gitlab.publish` = `$maintainer` -- the gitlab user `sample_user` had access to group `group1` as +- the gitlab user `sample_user` has access to group `group1` as `$maintainer` and `group2` as `$reporter` - then this user could publish any of the npm packages: - `sample_user` - any package under `group1/**` - error if the user tries to publish any package under `group2/**` +### Legacy Mode + If using the legacy mode, the system behaves as in normal mode with -fixed `$auth.gitlab.publish` = `$owner` +fixed configuration `auth.gitlab.publish` = `$owner` ## Configuration Options diff --git a/conf/localhost.yaml b/conf/localhost.yaml deleted file mode 100644 index bf7ee14..0000000 --- a/conf/localhost.yaml +++ /dev/null @@ -1,36 +0,0 @@ -storage: /tmp/storage/data - -plugins: /tmp/plugins - -listen: - - 0.0.0.0:4873 - -auth: - gitlab: - url: http://localhost:50080 - authCache: - enabled: true - ttl: 300 - publish: $maintainer - -uplinks: - npmjs: - url: https://registry.npmjs.org/ - -packages: - '@*/*': - # scoped packages - access: $all - publish: $authenticated - proxy: npmjs - gitlab: true - - '**': - access: $all - publish: $authenticated - proxy: npmjs - gitlab: true - -logs: - - { type: stdout, format: pretty, level: trace } - #- {type: file, path: verdaccio.log, level: info}