@verdaccio/config 7.0.0-next.5 → 8.0.0-next-8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +175 -0
- package/LICENSE +1 -1
- package/README.md +69 -0
- package/build/agent.js +1 -1
- package/build/agent.js.map +1 -1
- package/build/builder.js +2 -3
- package/build/builder.js.map +1 -1
- package/build/conf/default.yaml +10 -1
- package/build/conf/docker.yaml +10 -1
- package/build/conf/index.js.map +1 -1
- package/build/config-path.d.ts +2 -3
- package/build/config-path.js +51 -22
- package/build/config-path.js.map +1 -1
- package/build/config-utils.js +14 -3
- package/build/config-utils.js.map +1 -1
- package/build/config.d.ts +13 -5
- package/build/config.js +71 -35
- package/build/config.js.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/package-access.js +5 -2
- package/build/package-access.js.map +1 -1
- package/build/parse.js +1 -1
- package/build/parse.js.map +1 -1
- package/build/security.js +2 -1
- package/build/security.js.map +1 -1
- package/build/serverSettings.js.map +1 -1
- package/build/token.d.ts +1 -0
- package/build/token.js +2 -0
- package/build/token.js.map +1 -1
- package/build/uplinks.js +1 -1
- package/build/uplinks.js.map +1 -1
- package/build/user.js.map +1 -1
- package/package.json +8 -10
- package/src/builder.ts +1 -2
- package/src/conf/default.yaml +10 -1
- package/src/conf/docker.yaml +10 -1
- package/src/config-path.ts +57 -25
- package/src/config-utils.ts +13 -2
- package/src/config.ts +79 -35
- package/src/package-access.ts +5 -1
- package/src/security.ts +1 -0
- package/src/token.ts +2 -0
- package/test/__snapshots__/builder.spec.ts.snap +2 -2
- package/test/__snapshots__/config-parsing.spec.ts.snap +2 -2
- package/test/agent.spec.ts +44 -0
- package/test/builder.spec.ts +61 -0
- package/test/config-parsing.spec.ts +1 -0
- package/test/config-utils.spec.ts +1 -0
- package/test/config.path.spec.ts +102 -74
- package/test/config.spec.ts +92 -4
- package/test/package-access.spec.ts +28 -1
- package/test/token.spec.ts +2 -0
- package/test/uplinks.spec.ts +2 -0
- package/test/utils.spec.ts +2 -0
- package/jest.config.js +0 -10
package/test/builder.spec.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
|
|
1
3
|
import { ConfigBuilder } from '../src';
|
|
2
4
|
|
|
3
5
|
describe('Config builder', () => {
|
|
@@ -13,6 +15,7 @@ describe('Config builder', () => {
|
|
|
13
15
|
proxy: 'some',
|
|
14
16
|
})
|
|
15
17
|
.addLogger({ level: 'info', type: 'stdout', format: 'json' })
|
|
18
|
+
.addAuth({ htpasswd: { file: '.htpasswd' } })
|
|
16
19
|
.addStorage('/tmp/verdaccio')
|
|
17
20
|
.addSecurity({ api: { legacy: true } });
|
|
18
21
|
expect(config.getConfig()).toEqual({
|
|
@@ -21,6 +24,11 @@ describe('Config builder', () => {
|
|
|
21
24
|
legacy: true,
|
|
22
25
|
},
|
|
23
26
|
},
|
|
27
|
+
auth: {
|
|
28
|
+
htpasswd: {
|
|
29
|
+
file: '.htpasswd',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
24
32
|
storage: '/tmp/verdaccio',
|
|
25
33
|
packages: {
|
|
26
34
|
'upstream/*': {
|
|
@@ -61,5 +69,58 @@ describe('Config builder', () => {
|
|
|
61
69
|
.addStorage('/tmp/verdaccio')
|
|
62
70
|
.addSecurity({ api: { legacy: true } });
|
|
63
71
|
expect(config.getAsYaml()).toMatchSnapshot();
|
|
72
|
+
|
|
73
|
+
expect(config.getConfig()).toEqual({
|
|
74
|
+
uplinks: {
|
|
75
|
+
upstream: {
|
|
76
|
+
url: 'https://registry.verdaccio.org',
|
|
77
|
+
},
|
|
78
|
+
upstream2: {
|
|
79
|
+
url: 'https://registry.verdaccio.org',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
packages: {
|
|
83
|
+
'upstream/*': {
|
|
84
|
+
access: 'public',
|
|
85
|
+
publish: 'foo, bar',
|
|
86
|
+
unpublish: 'foo, bar',
|
|
87
|
+
proxy: 'some',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
security: {
|
|
91
|
+
api: {
|
|
92
|
+
legacy: true,
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
log: {
|
|
96
|
+
level: 'info',
|
|
97
|
+
type: 'stdout',
|
|
98
|
+
format: 'json',
|
|
99
|
+
},
|
|
100
|
+
storage: '/tmp/verdaccio',
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('should merge configurations', () => {
|
|
105
|
+
// @ts-expect-error
|
|
106
|
+
const config = ConfigBuilder.build({ security: { api: { legacy: false } } });
|
|
107
|
+
config.addSecurity({ web: { verify: {}, sign: { algorithm: 'ES256' } } });
|
|
108
|
+
config.addStorage('/tmp/verdaccio');
|
|
109
|
+
expect(config.getConfig()).toEqual({
|
|
110
|
+
security: {
|
|
111
|
+
api: {
|
|
112
|
+
legacy: false,
|
|
113
|
+
},
|
|
114
|
+
web: {
|
|
115
|
+
verify: {},
|
|
116
|
+
sign: {
|
|
117
|
+
algorithm: 'ES256',
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
uplinks: {},
|
|
122
|
+
packages: {},
|
|
123
|
+
storage: '/tmp/verdaccio',
|
|
124
|
+
});
|
|
64
125
|
});
|
|
65
126
|
});
|
package/test/config.path.spec.ts
CHANGED
|
@@ -1,76 +1,105 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
1
2
|
import os from 'os';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
4
|
|
|
3
5
|
import { findConfigFile } from '../src/config-path';
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
...fsOri,
|
|
13
|
-
statSync: (path) => ({
|
|
14
|
-
isDirectory: () => {
|
|
15
|
-
if (path.match(/fail/)) {
|
|
16
|
-
throw Error('file does not exist');
|
|
17
|
-
}
|
|
18
|
-
return true;
|
|
19
|
-
},
|
|
20
|
-
}),
|
|
21
|
-
accessSync: (a) => mockaccessSync(a),
|
|
22
|
-
mkdirSync: (a) => mockmkDir(a),
|
|
23
|
-
writeFileSync: (a) => mockwriteFile(a),
|
|
7
|
+
describe('config-path', () => {
|
|
8
|
+
let statSyncMock;
|
|
9
|
+
let mkdirSyncMock;
|
|
10
|
+
let writeFileSyncMock;
|
|
11
|
+
let accessSyncMock;
|
|
12
|
+
let fakeStats = {
|
|
13
|
+
isDirectory: vi.fn().mockReturnValue(true),
|
|
24
14
|
};
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
jest.mock('fs');
|
|
28
15
|
|
|
29
|
-
describe('config-path', () => {
|
|
30
16
|
beforeEach(() => {
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
// Mock only statSync method
|
|
18
|
+
statSyncMock = vi.spyOn(fs, 'statSync');
|
|
19
|
+
mkdirSyncMock = vi.spyOn(fs, 'mkdirSync');
|
|
20
|
+
writeFileSyncMock = vi.spyOn(fs, 'writeFileSync');
|
|
21
|
+
accessSyncMock = vi.spyOn(fs, 'accessSync');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
// Restore the original implementation after each test
|
|
26
|
+
statSyncMock.mockRestore();
|
|
27
|
+
vi.unstubAllEnvs();
|
|
33
28
|
});
|
|
34
29
|
|
|
30
|
+
function platformPath(path: string): string {
|
|
31
|
+
return path.replace(/\//g, os.platform() === 'win32' ? '\\' : '/');
|
|
32
|
+
}
|
|
33
|
+
|
|
35
34
|
describe('findConfigFile', () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
describe('using file location from arguments', () => {
|
|
36
|
+
test('with custom location', () => {
|
|
37
|
+
// mock
|
|
38
|
+
statSyncMock.mockReturnValue(fakeStats);
|
|
39
|
+
mkdirSyncMock.mockReturnValue(true);
|
|
40
|
+
writeFileSyncMock.mockReturnValue(undefined);
|
|
41
|
+
// Note: on Windows, path contains drive letter
|
|
42
|
+
expect(findConfigFile('/home/user/custom/location/config.yaml')).toMatch(
|
|
43
|
+
platformPath('/home/user/custom/location/config.yaml')
|
|
44
|
+
);
|
|
45
|
+
expect(writeFileSyncMock).not.toHaveBeenCalled();
|
|
46
|
+
expect(mkdirSyncMock).not.toHaveBeenCalled();
|
|
45
47
|
});
|
|
48
|
+
});
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
describe('with env variables', () => {
|
|
51
|
+
test('the env XDG_CONFIG_HOME is defined and the directory exist but config file is missing', async () => {
|
|
52
|
+
// mock
|
|
53
|
+
statSyncMock.mockReturnValue(fakeStats);
|
|
54
|
+
mkdirSyncMock.mockReturnValue(true);
|
|
55
|
+
writeFileSyncMock.mockReturnValue(undefined);
|
|
56
|
+
// node env variable
|
|
57
|
+
vi.stubEnv('XDG_CONFIG_HOME', '/home/user');
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
expect
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
expect(findConfigFile()).toEqual(platformPath('/home/user/verdaccio/config.yaml'));
|
|
60
|
+
expect(writeFileSyncMock).toHaveBeenCalledWith(
|
|
61
|
+
platformPath('/home/user/verdaccio/config.yaml'),
|
|
62
|
+
expect.stringContaining('packages')
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('with HOME if directory exist but config file is missing', () => {
|
|
67
|
+
// mock
|
|
68
|
+
statSyncMock.mockReturnValue(fakeStats);
|
|
69
|
+
mkdirSyncMock.mockReturnValue(true);
|
|
70
|
+
writeFileSyncMock.mockReturnValue(undefined);
|
|
71
|
+
vi.stubEnv('XDG_CONFIG_HOME', '');
|
|
72
|
+
vi.stubEnv('HOME', '/home/user');
|
|
73
|
+
expect(findConfigFile()).toEqual(platformPath('/home/user/.config/verdaccio/config.yaml'));
|
|
74
|
+
expect(writeFileSyncMock).toHaveBeenCalledWith(
|
|
75
|
+
platformPath('/home/user/.config/verdaccio/config.yaml'),
|
|
76
|
+
expect.stringContaining('packages')
|
|
77
|
+
);
|
|
78
|
+
expect(mkdirSyncMock).toHaveBeenCalledWith(
|
|
79
|
+
platformPath('/home/user/.config/verdaccio'),
|
|
80
|
+
expect.anything()
|
|
81
|
+
);
|
|
82
|
+
});
|
|
62
83
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
expect(findConfigFile()).toMatch('packages/config/verdaccio/config.yaml');
|
|
84
|
+
describe('error handling', () => {
|
|
85
|
+
test('XDG_CONFIG_HOME is not directory fallback to default', () => {
|
|
86
|
+
// mock
|
|
87
|
+
statSyncMock.mockReturnValue({
|
|
88
|
+
isDirectory: vi.fn().mockReturnValue(false),
|
|
69
89
|
});
|
|
90
|
+
mkdirSyncMock.mockReturnValue(true);
|
|
91
|
+
writeFileSyncMock.mockReturnValue(undefined);
|
|
92
|
+
// node env variable
|
|
93
|
+
vi.stubEnv('XDG_CONFIG_HOME', '/home/user/fail');
|
|
70
94
|
|
|
95
|
+
expect(findConfigFile()).toMatch(platformPath('packages/config/verdaccio/config.yaml'));
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Does not work on Windows
|
|
99
|
+
if (os.platform() !== 'win32') {
|
|
71
100
|
test('no permissions on read default config file', () => {
|
|
72
|
-
|
|
73
|
-
|
|
101
|
+
vi.stubEnv('XDG_CONFIG_HOME', '/home/user');
|
|
102
|
+
accessSyncMock.mockImplementation(() => {
|
|
74
103
|
throw new Error('error on write file');
|
|
75
104
|
});
|
|
76
105
|
|
|
@@ -78,29 +107,28 @@ describe('config-path', () => {
|
|
|
78
107
|
findConfigFile();
|
|
79
108
|
}).toThrow(/configuration file does not have enough permissions for reading/);
|
|
80
109
|
});
|
|
81
|
-
}
|
|
110
|
+
}
|
|
82
111
|
});
|
|
112
|
+
});
|
|
83
113
|
|
|
84
|
-
|
|
114
|
+
// Note: Trying to mock Windows platform leads to different results (incorrect slashes)
|
|
115
|
+
if (os.platform() === 'win32') {
|
|
116
|
+
describe('with Windows env variables', () => {
|
|
85
117
|
test('with relative location', () => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
// mock
|
|
119
|
+
statSyncMock.mockReturnValue(fakeStats);
|
|
120
|
+
mkdirSyncMock.mockReturnValue(true);
|
|
121
|
+
writeFileSyncMock.mockReturnValue(undefined);
|
|
122
|
+
accessSyncMock.mockImplementation(() => {});
|
|
123
|
+
// delete process.env.XDG_CONFIG_HOME;
|
|
124
|
+
vi.stubEnv('XDG_CONFIG_HOME', '');
|
|
125
|
+
vi.stubEnv('HOME', '');
|
|
126
|
+
vi.stubEnv('APPDATA', 'C:\\Users\\Tester\\AppData\\');
|
|
127
|
+
expect(findConfigFile()).toEqual('C:\\Users\\Tester\\AppData\\verdaccio\\config.yaml');
|
|
128
|
+
expect(writeFileSyncMock).toHaveBeenCalled();
|
|
129
|
+
expect(mkdirSyncMock).toHaveBeenCalled();
|
|
93
130
|
});
|
|
94
131
|
});
|
|
95
|
-
} else {
|
|
96
|
-
test('with windows as directory exist but config file is missing', () => {
|
|
97
|
-
delete process.env.XDG_CONFIG_HOME;
|
|
98
|
-
delete process.env.HOME;
|
|
99
|
-
process.env.APPDATA = '/app/data/';
|
|
100
|
-
expect(findConfigFile()).toMatch('\\app\\data\\verdaccio\\config.yaml');
|
|
101
|
-
expect(mockwriteFile).toHaveBeenCalled();
|
|
102
|
-
expect(mockmkDir).toHaveBeenCalled();
|
|
103
|
-
});
|
|
104
132
|
}
|
|
105
133
|
});
|
|
106
134
|
});
|
package/test/config.spec.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
3
4
|
|
|
4
5
|
import {
|
|
5
6
|
Config,
|
|
6
7
|
DEFAULT_REGISTRY,
|
|
7
8
|
DEFAULT_UPLINK,
|
|
8
9
|
ROLES,
|
|
10
|
+
TOKEN_VALID_LENGTH,
|
|
9
11
|
WEB_TITLE,
|
|
10
12
|
defaultSecurity,
|
|
13
|
+
generateRandomSecretKey,
|
|
11
14
|
getDefaultConfig,
|
|
15
|
+
isNodeVersionGreaterThan21,
|
|
12
16
|
parseConfigFile,
|
|
13
17
|
} from '../src';
|
|
14
18
|
import { parseConfigurationFile } from './utils';
|
|
@@ -19,6 +23,8 @@ const resolveConf = (conf) => {
|
|
|
19
23
|
return path.join(__dirname, `../src/conf/${name}${ext.startsWith('.') ? ext : '.yaml'}`);
|
|
20
24
|
};
|
|
21
25
|
|
|
26
|
+
const itif = (condition) => (condition ? test : test.skip);
|
|
27
|
+
|
|
22
28
|
const checkDefaultUplink = (config) => {
|
|
23
29
|
expect(_.isObject(config.uplinks[DEFAULT_UPLINK])).toBeTruthy();
|
|
24
30
|
expect(config.uplinks[DEFAULT_UPLINK].url).toMatch(DEFAULT_REGISTRY);
|
|
@@ -94,18 +100,85 @@ describe('check basic content parsed file', () => {
|
|
|
94
100
|
describe('checkSecretKey', () => {
|
|
95
101
|
test('with default.yaml and pre selected secret', () => {
|
|
96
102
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
97
|
-
expect(config.checkSecretKey(
|
|
103
|
+
expect(config.checkSecretKey(generateRandomSecretKey())).toHaveLength(TOKEN_VALID_LENGTH);
|
|
98
104
|
});
|
|
99
105
|
|
|
100
106
|
test('with default.yaml and void secret', () => {
|
|
101
107
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
102
|
-
|
|
108
|
+
const secret = config.checkSecretKey();
|
|
109
|
+
expect(typeof secret === 'string').toBeTruthy();
|
|
110
|
+
expect(secret).toHaveLength(TOKEN_VALID_LENGTH);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('with default.yaml and empty string secret', () => {
|
|
114
|
+
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
115
|
+
const secret = config.checkSecretKey('');
|
|
116
|
+
expect(typeof secret === 'string').toBeTruthy();
|
|
117
|
+
expect(secret).toHaveLength(TOKEN_VALID_LENGTH);
|
|
103
118
|
});
|
|
104
119
|
|
|
105
|
-
test('with default.yaml and
|
|
120
|
+
test('with default.yaml and valid string secret length', () => {
|
|
106
121
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
107
|
-
expect(typeof config.checkSecretKey(
|
|
122
|
+
expect(typeof config.checkSecretKey(generateRandomSecretKey()) === 'string').toBeTruthy();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('with default.yaml migrate a valid string secret length', () => {
|
|
126
|
+
const config = new Config(parseConfigFile(resolveConf('default')), {
|
|
127
|
+
forceMigrateToSecureLegacySignature: true,
|
|
128
|
+
});
|
|
129
|
+
expect(
|
|
130
|
+
// 64 characters secret long
|
|
131
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
132
|
+
).toHaveLength(TOKEN_VALID_LENGTH);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// only runs on Node.js 22 or higher
|
|
136
|
+
itif(isNodeVersionGreaterThan21())('with enhanced legacy signature Node 22 or higher', () => {
|
|
137
|
+
const config = new Config(parseConfigFile(resolveConf('default')), {
|
|
138
|
+
forceMigrateToSecureLegacySignature: false,
|
|
139
|
+
});
|
|
140
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
141
|
+
expect(() =>
|
|
142
|
+
// 64 characters secret long
|
|
143
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
144
|
+
).toThrow();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
itif(isNodeVersionGreaterThan21())('with enhanced legacy signature Node 22 or higher', () => {
|
|
148
|
+
const config = new Config(parseConfigFile(resolveConf('default')), {
|
|
149
|
+
forceMigrateToSecureLegacySignature: false,
|
|
150
|
+
});
|
|
151
|
+
config.security.api.migrateToSecureLegacySignature = true;
|
|
152
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
153
|
+
expect(
|
|
154
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
155
|
+
).toHaveLength(TOKEN_VALID_LENGTH);
|
|
108
156
|
});
|
|
157
|
+
|
|
158
|
+
itif(isNodeVersionGreaterThan21() === false)(
|
|
159
|
+
'with old unsecure legacy signature Node 21 or lower',
|
|
160
|
+
() => {
|
|
161
|
+
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
162
|
+
config.security.api.migrateToSecureLegacySignature = false;
|
|
163
|
+
// 64 characters secret long
|
|
164
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
165
|
+
expect(
|
|
166
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
167
|
+
).toHaveLength(64);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
test('with migration to new legacy signature Node 21 or lower', () => {
|
|
172
|
+
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
173
|
+
config.security.api.migrateToSecureLegacySignature = true;
|
|
174
|
+
// 64 characters secret long
|
|
175
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
176
|
+
expect(
|
|
177
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
178
|
+
).toHaveLength(TOKEN_VALID_LENGTH);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test.todo('test emit warning with secret key');
|
|
109
182
|
});
|
|
110
183
|
|
|
111
184
|
describe('getMatchedPackagesSpec', () => {
|
|
@@ -159,3 +232,18 @@ describe('VERDACCIO_STORAGE_PATH', () => {
|
|
|
159
232
|
delete process.env.VERDACCIO_STORAGE_PATH;
|
|
160
233
|
});
|
|
161
234
|
});
|
|
235
|
+
|
|
236
|
+
describe('configPath', () => {
|
|
237
|
+
test('should set configPath in config', () => {
|
|
238
|
+
const defaultConfig = parseConfigFile(resolveConf('default'));
|
|
239
|
+
const config = new Config(defaultConfig);
|
|
240
|
+
expect(config.getConfigPath()).toBe(path.join(__dirname, '../src/conf/default.yaml'));
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('should throw an error if configPath is not provided', () => {
|
|
244
|
+
const defaultConfig = parseConfigFile(resolveConf('default'));
|
|
245
|
+
defaultConfig.configPath = '';
|
|
246
|
+
defaultConfig.config_path = '';
|
|
247
|
+
expect(() => new Config(defaultConfig)).toThrow('configPath property is required');
|
|
248
|
+
});
|
|
249
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
2
3
|
|
|
3
4
|
import { parseConfigFile } from '../src';
|
|
4
|
-
import { PACKAGE_ACCESS, normalisePackageAccess } from '../src/package-access';
|
|
5
|
+
import { PACKAGE_ACCESS, normalisePackageAccess, normalizeUserList } from '../src/package-access';
|
|
5
6
|
import { parseConfigurationFile } from './utils';
|
|
6
7
|
|
|
7
8
|
describe('Package access utilities', () => {
|
|
@@ -123,4 +124,30 @@ describe('Package access utilities', () => {
|
|
|
123
124
|
expect(_.isArray(all.publish)).toBeTruthy();
|
|
124
125
|
});
|
|
125
126
|
});
|
|
127
|
+
describe('normaliseUserList', () => {
|
|
128
|
+
test('should normalize user list', () => {
|
|
129
|
+
const groupsList = 'admin superadmin';
|
|
130
|
+
const result = normalizeUserList(groupsList);
|
|
131
|
+
expect(result).toEqual(['admin', 'superadmin']);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('should normalize empty user list', () => {
|
|
135
|
+
const groupsList = '';
|
|
136
|
+
const result = normalizeUserList(groupsList);
|
|
137
|
+
expect(result).toEqual([]);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('should normalize user list array', () => {
|
|
141
|
+
const groupsList = ['admin', 'superadmin'];
|
|
142
|
+
const result = normalizeUserList(groupsList);
|
|
143
|
+
expect(result).toEqual(['admin', 'superadmin']);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('should throw error for invalid user list', () => {
|
|
147
|
+
const groupsList = { group: 'admin' };
|
|
148
|
+
expect(() => {
|
|
149
|
+
normalizeUserList(groupsList);
|
|
150
|
+
}).toThrow('CONFIG: bad package acl (array or string expected): {"group":"admin"}');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
126
153
|
});
|
package/test/token.spec.ts
CHANGED
package/test/uplinks.spec.ts
CHANGED
package/test/utils.spec.ts
CHANGED