Skip to content

Commit d65dcc5

Browse files
Merge pull request #60 from bufferoverflow/feat/improve-access-modes
feat: make allow_access behave closer to htpasswd default auth plugin
2 parents fbe9b75 + ccf5325 commit d65dcc5

File tree

4 files changed

+71
-24
lines changed

4 files changed

+71
-24
lines changed

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,41 @@ yarn publish --registry http://localhost:4873
9393

9494
Access and publish access rights depend on the mode used.
9595

96-
### Normal Mode
96+
verdaccio-gitlab access control will only be applied to package sections that
97+
are marked with `gitlab: true` as in the configuration sample above. If you
98+
wish to disable gitlab authentication to any package config, just remove the
99+
element from the config.
97100

98-
In the default mode, packages are available:
101+
### Normal Mode (default)
99102

100-
- *access* is allowed depending on verdaccio `package` configuration
101-
directives (unauthenticated / authenticated)
102-
- *publish* is allowed if the package name matches the logged in user
103-
id, or if the package name / scope of the package matches one of the
104-
user groups and the user has `auth.gitlab.publish` access rights on
103+
In normal mode, packages are available:
104+
105+
#### Access
106+
107+
*access* is allowed depending on the following verdaccio `package` configuration
108+
directives:
109+
110+
- authenticated users are able to access all packages
111+
- unauthenticated users will be able to access packages marked with either
112+
`$all` or `$anonymous` access levels at the package group definition
113+
114+
Please note that no group or package name mapping is applied on access, any
115+
user successfully authenticated can access all packages.
116+
117+
#### Publish
118+
119+
*publish* is allowed if the package name matches the logged in user
120+
id, or if the package name or scope of the package matches one of the
121+
user's groups, and the user has `auth.gitlab.publish` access rights on
105122
the group
106123

107124
For instance, assuming the following configuration:
108125

109126
- `auth.gitlab.publish` = `$maintainer`
110127
- the gitlab user `sample_user` has access to group `group1` as
111-
`$maintainer` and `group2` as `$reporter`
112-
- then this user could publish any of the npm packages:
128+
`$maintainer` and `group2` as `$reporter` in gitlab
129+
- then this user would be able to *access* any package
130+
- *publish* any of the following npm packages in verdaccio:
113131
- `sample_user`
114132
- any package under `group1/**`
115133
- error if the user tries to publish any package under `group2/**`

src/gitlab.js

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ const ACCESS_LEVEL_MAPPING = {
3939
$owner: 50
4040
};
4141

42+
// List of verdaccio builtin levels that map to anonymous access
43+
const BUILTIN_ACCESS_LEVEL_ANONYMOUS = [ '$anonymous', '$all' ];
44+
45+
// Level to apply on 'allow_access' calls when a package definition does not define one
46+
const DEFAULT_ALLOW_ACCESS_LEVEL = [ '$all' ];
47+
48+
4249
export default class VerdaccioGitLab implements IPluginAuth {
4350
options: PluginOptions;
4451
config: VerdaccioGitlabConfig;
@@ -140,15 +147,19 @@ export default class VerdaccioGitLab implements IPluginAuth {
140147
allow_access(user: RemoteUser, _package: VerdaccioGitlabPackageAccess, cb: Callback) {
141148
if (!_package.gitlab) return cb(null, false);
142149

143-
if ((_package.access || []).includes('$authenticated') && user.name !== undefined) {
144-
this.logger.debug(`[gitlab] allow user: ${user.name} access to package: ${_package.name}`);
145-
return cb(null, false);
146-
} else if ((_package.access || []).includes('$all')) {
147-
this.logger.debug(`[gitlab] allow unauthenticated access to package: ${_package.name}`);
148-
return cb(null, false);
149-
} else {
150-
this.logger.debug(`[gitlab] deny user: ${user.name || '<empty>'} access to package: ${_package.name}`);
151-
return cb(httperror[401]('access denied, user not authenticated in gitlab and unauthenticated package access disabled'));
150+
const packageAccess = (_package.access && _package.access.length > 0) ? _package.access : DEFAULT_ALLOW_ACCESS_LEVEL;
151+
152+
if (user.name !== undefined) { // successfully authenticated
153+
this.logger.debug(`[gitlab] allow user: ${user.name} authenticated access to package: ${_package.name}`);
154+
return cb(null, true);
155+
} else { // unauthenticated
156+
if (BUILTIN_ACCESS_LEVEL_ANONYMOUS.some(level => packageAccess.includes(level))) {
157+
this.logger.debug(`[gitlab] allow anonymous access to package: ${_package.name}`);
158+
return cb(null, true);
159+
} else {
160+
this.logger.debug(`[gitlab] deny access to package: ${_package.name}`);
161+
return cb(httperror[401]('access denied, user not authenticated and anonymous access disabled'));
162+
}
152163
}
153164
}
154165

@@ -175,7 +186,7 @@ export default class VerdaccioGitLab implements IPluginAuth {
175186
if (packagePermit || packageScopePermit) {
176187
const perm = packagePermit ? 'package-name' : 'package-scope';
177188
this.logger.debug(`[gitlab] user: ${user.name || ''} allowed to publish package: ${_package.name} based on ${perm}`);
178-
return cb(null, false);
189+
return cb(null, true);
179190
} else {
180191
this.logger.debug(`[gitlab] user: ${user.name || ''} denied from publishing package: ${_package.name}`);
181192
const missingPerm = _package.name.indexOf('@') === 0 ? 'package-scope' : 'package-name';

test/functional/auth/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default (server: any, gitlab: any) => { // eslint-disable-line no-unused-
3030
.status(HTTP_STATUS.UNAUTHORIZED)
3131
.then((body) => {
3232
expect(body).toHaveProperty('error');
33-
expect(body.error).toMatch(/invalid/);
33+
expect(body.error).toMatch(/error/);
3434
});
3535
});
3636
});

test/unit/gitlab.spec.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ describe('Gitlab Auth Plugin Unit Tests', () => {
6767
const cb: Callback = (err, data) => {
6868
expect(err).toBeFalsy();
6969
// false allows the plugin chain to continue
70-
expect(data).toBe(false);
70+
expect(data).toBe(true);
7171
done();
7272
};
7373

@@ -85,7 +85,25 @@ describe('Gitlab Auth Plugin Unit Tests', () => {
8585
const cb: Callback = (err, data) => {
8686
expect(err).toBeFalsy();
8787
// false allows the plugin chain to continue
88-
expect(data).toBe(false);
88+
expect(data).toBe(true);
89+
done();
90+
};
91+
92+
verdaccioGitlab.allow_access(config.remoteUser, _package, cb);
93+
});
94+
95+
test('should allow access to package when access level is empty (default = $all)', done => {
96+
const verdaccioGitlab: VerdaccioGitlab = new VerdaccioGitlab(config.verdaccioGitlabConfig, config.options);
97+
const _package: VerdaccioGitlabPackageAccess = {
98+
name: config.user,
99+
access: undefined,
100+
gitlab: true
101+
};
102+
103+
const cb: Callback = (err, data) => {
104+
expect(err).toBeFalsy();
105+
// false allows the plugin chain to continue
106+
expect(data).toBe(true);
89107
done();
90108
};
91109

@@ -123,7 +141,7 @@ describe('Gitlab Auth Plugin Unit Tests', () => {
123141

124142
const cb: Callback = (err, data) => {
125143
expect(err).toBeFalsy();
126-
expect(data).toBe(false);
144+
expect(data).toBe(true);
127145
done();
128146
};
129147

@@ -139,7 +157,7 @@ describe('Gitlab Auth Plugin Unit Tests', () => {
139157

140158
const cb: Callback = (err, data) => {
141159
expect(err).toBeFalsy();
142-
expect(data).toBe(false);
160+
expect(data).toBe(true);
143161
done();
144162
};
145163

0 commit comments

Comments
 (0)