@push.rocks/smartregistry 2.2.3 → 2.4.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/cargo/classes.cargoregistry.d.ts +7 -1
- package/dist_ts/cargo/classes.cargoregistry.js +42 -4
- package/dist_ts/cargo/classes.cargoupstream.d.ts +44 -0
- package/dist_ts/cargo/classes.cargoupstream.js +129 -0
- package/dist_ts/cargo/index.d.ts +1 -0
- package/dist_ts/cargo/index.js +2 -1
- package/dist_ts/classes.smartregistry.d.ts +33 -2
- package/dist_ts/classes.smartregistry.js +45 -12
- package/dist_ts/composer/classes.composerregistry.d.ts +7 -1
- package/dist_ts/composer/classes.composerregistry.js +34 -3
- package/dist_ts/composer/classes.composerupstream.d.ts +40 -0
- package/dist_ts/composer/classes.composerupstream.js +159 -0
- package/dist_ts/composer/index.d.ts +1 -0
- package/dist_ts/composer/index.js +2 -1
- package/dist_ts/core/classes.authmanager.d.ts +30 -80
- package/dist_ts/core/classes.authmanager.js +63 -337
- package/dist_ts/core/classes.defaultauthprovider.d.ts +78 -0
- package/dist_ts/core/classes.defaultauthprovider.js +311 -0
- package/dist_ts/core/classes.registrystorage.d.ts +70 -4
- package/dist_ts/core/classes.registrystorage.js +165 -5
- package/dist_ts/core/index.d.ts +3 -0
- package/dist_ts/core/index.js +7 -2
- package/dist_ts/core/interfaces.auth.d.ts +83 -0
- package/dist_ts/core/interfaces.auth.js +2 -0
- package/dist_ts/core/interfaces.core.d.ts +38 -0
- package/dist_ts/core/interfaces.storage.d.ts +120 -0
- package/dist_ts/core/interfaces.storage.js +2 -0
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/maven/classes.mavenregistry.d.ts +12 -1
- package/dist_ts/maven/classes.mavenregistry.js +69 -4
- package/dist_ts/maven/classes.mavenupstream.d.ts +45 -0
- package/dist_ts/maven/classes.mavenupstream.js +153 -0
- package/dist_ts/maven/index.d.ts +1 -0
- package/dist_ts/maven/index.js +2 -1
- package/dist_ts/npm/classes.npmregistry.d.ts +3 -1
- package/dist_ts/npm/classes.npmregistry.js +55 -6
- package/dist_ts/npm/classes.npmupstream.d.ts +51 -0
- package/dist_ts/npm/classes.npmupstream.js +206 -0
- package/dist_ts/npm/index.d.ts +1 -0
- package/dist_ts/npm/index.js +2 -1
- package/dist_ts/oci/classes.ociregistry.d.ts +4 -1
- package/dist_ts/oci/classes.ociregistry.js +78 -17
- package/dist_ts/oci/classes.ociupstream.d.ts +62 -0
- package/dist_ts/oci/classes.ociupstream.js +206 -0
- package/dist_ts/oci/index.d.ts +1 -0
- package/dist_ts/oci/index.js +2 -1
- package/dist_ts/plugins.d.ts +4 -1
- package/dist_ts/plugins.js +6 -2
- package/dist_ts/pypi/classes.pypiregistry.d.ts +7 -1
- package/dist_ts/pypi/classes.pypiregistry.js +60 -4
- package/dist_ts/pypi/classes.pypiupstream.d.ts +48 -0
- package/dist_ts/pypi/classes.pypiupstream.js +165 -0
- package/dist_ts/pypi/index.d.ts +1 -0
- package/dist_ts/pypi/index.js +2 -1
- package/dist_ts/rubygems/classes.rubygemsregistry.d.ts +7 -1
- package/dist_ts/rubygems/classes.rubygemsregistry.js +35 -4
- package/dist_ts/rubygems/classes.rubygemsupstream.d.ts +47 -0
- package/dist_ts/rubygems/classes.rubygemsupstream.js +184 -0
- package/dist_ts/rubygems/index.d.ts +1 -0
- package/dist_ts/rubygems/index.js +2 -1
- package/dist_ts/upstream/classes.baseupstream.d.ts +112 -0
- package/dist_ts/upstream/classes.baseupstream.js +411 -0
- package/dist_ts/upstream/classes.circuitbreaker.d.ts +111 -0
- package/dist_ts/upstream/classes.circuitbreaker.js +192 -0
- package/dist_ts/upstream/classes.upstreamcache.d.ts +170 -0
- package/dist_ts/upstream/classes.upstreamcache.js +485 -0
- package/dist_ts/upstream/index.d.ts +6 -0
- package/dist_ts/upstream/index.js +7 -0
- package/dist_ts/upstream/interfaces.upstream.d.ts +169 -0
- package/dist_ts/upstream/interfaces.upstream.js +23 -0
- package/package.json +4 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/cargo/classes.cargoregistry.ts +48 -3
- package/ts/cargo/classes.cargoupstream.ts +159 -0
- package/ts/cargo/index.ts +1 -0
- package/ts/classes.smartregistry.ts +88 -11
- package/ts/composer/classes.composerregistry.ts +39 -2
- package/ts/composer/classes.composerupstream.ts +200 -0
- package/ts/composer/index.ts +1 -0
- package/ts/core/classes.authmanager.ts +74 -412
- package/ts/core/classes.defaultauthprovider.ts +393 -0
- package/ts/core/classes.registrystorage.ts +199 -5
- package/ts/core/index.ts +8 -1
- package/ts/core/interfaces.auth.ts +91 -0
- package/ts/core/interfaces.core.ts +42 -0
- package/ts/core/interfaces.storage.ts +130 -0
- package/ts/index.ts +3 -0
- package/ts/maven/classes.mavenregistry.ts +84 -3
- package/ts/maven/classes.mavenupstream.ts +220 -0
- package/ts/maven/index.ts +1 -0
- package/ts/npm/classes.npmregistry.ts +61 -5
- package/ts/npm/classes.npmupstream.ts +260 -0
- package/ts/npm/index.ts +1 -0
- package/ts/oci/classes.ociregistry.ts +89 -17
- package/ts/oci/classes.ociupstream.ts +263 -0
- package/ts/oci/index.ts +1 -0
- package/ts/plugins.ts +7 -1
- package/ts/pypi/classes.pypiregistry.ts +68 -3
- package/ts/pypi/classes.pypiupstream.ts +211 -0
- package/ts/pypi/index.ts +1 -0
- package/ts/rubygems/classes.rubygemsregistry.ts +40 -3
- package/ts/rubygems/classes.rubygemsupstream.ts +230 -0
- package/ts/rubygems/index.ts +1 -0
- package/ts/upstream/classes.baseupstream.ts +526 -0
- package/ts/upstream/classes.circuitbreaker.ts +238 -0
- package/ts/upstream/classes.upstreamcache.ts +626 -0
- package/ts/upstream/index.ts +11 -0
- package/ts/upstream/interfaces.upstream.ts +195 -0
|
@@ -1,87 +1,62 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DefaultAuthProvider } from './classes.defaultauthprovider.js';
|
|
2
2
|
/**
|
|
3
|
-
* Unified authentication manager for all registry protocols
|
|
4
|
-
*
|
|
3
|
+
* Unified authentication manager for all registry protocols.
|
|
4
|
+
* Delegates to a pluggable IAuthProvider for actual auth operations.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // Use default in-memory provider
|
|
9
|
+
* const auth = new AuthManager(config);
|
|
10
|
+
*
|
|
11
|
+
* // Use custom provider (LDAP, OAuth, etc.)
|
|
12
|
+
* const auth = new AuthManager(config, new LdapAuthProvider(ldapClient));
|
|
13
|
+
* ```
|
|
5
14
|
*/
|
|
6
15
|
export class AuthManager {
|
|
7
16
|
config;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
constructor(config) {
|
|
17
|
+
provider;
|
|
18
|
+
constructor(config, provider) {
|
|
11
19
|
this.config = config;
|
|
20
|
+
// Use provided provider or default in-memory implementation
|
|
21
|
+
this.provider = provider || new DefaultAuthProvider(config);
|
|
12
22
|
}
|
|
13
23
|
/**
|
|
14
24
|
* Initialize the auth manager
|
|
15
25
|
*/
|
|
16
26
|
async init() {
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
if (this.provider.init) {
|
|
28
|
+
await this.provider.init();
|
|
29
|
+
}
|
|
19
30
|
}
|
|
20
31
|
// ========================================================================
|
|
21
|
-
//
|
|
32
|
+
// UNIFIED AUTHENTICATION (Delegated to Provider)
|
|
22
33
|
// ========================================================================
|
|
23
34
|
/**
|
|
24
|
-
*
|
|
25
|
-
* @param
|
|
26
|
-
* @
|
|
27
|
-
* @param scopes - Permission scopes
|
|
28
|
-
* @param readonly - Whether the token is readonly
|
|
29
|
-
* @returns UUID token string
|
|
30
|
-
*/
|
|
31
|
-
async createUuidToken(userId, protocol, scopes, readonly = false) {
|
|
32
|
-
const token = this.generateUuid();
|
|
33
|
-
const authToken = {
|
|
34
|
-
type: protocol,
|
|
35
|
-
userId,
|
|
36
|
-
scopes,
|
|
37
|
-
readonly,
|
|
38
|
-
metadata: {
|
|
39
|
-
created: new Date().toISOString(),
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
this.tokenStore.set(token, authToken);
|
|
43
|
-
return token;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Generic protocol token creation (internal helper)
|
|
47
|
-
* @param userId - User ID
|
|
48
|
-
* @param protocol - Protocol type (npm, maven, composer, etc.)
|
|
49
|
-
* @param readonly - Whether the token is readonly
|
|
50
|
-
* @returns UUID token string
|
|
35
|
+
* Authenticate user credentials
|
|
36
|
+
* @param credentials - Username and password
|
|
37
|
+
* @returns User ID or null
|
|
51
38
|
*/
|
|
52
|
-
async
|
|
53
|
-
|
|
54
|
-
? [`${protocol}:*:*:read`]
|
|
55
|
-
: [`${protocol}:*:*:*`];
|
|
56
|
-
return this.createUuidToken(userId, protocol, scopes, readonly);
|
|
39
|
+
async authenticate(credentials) {
|
|
40
|
+
return this.provider.authenticate(credentials);
|
|
57
41
|
}
|
|
58
42
|
/**
|
|
59
|
-
*
|
|
60
|
-
* @param
|
|
61
|
-
* @param protocol - Expected protocol type
|
|
43
|
+
* Validate any token (NPM, Maven, OCI, PyPI, RubyGems, Composer, Cargo)
|
|
44
|
+
* @param tokenString - Token string (UUID or JWT)
|
|
45
|
+
* @param protocol - Expected protocol type (optional, improves performance)
|
|
62
46
|
* @returns Auth token object or null
|
|
63
47
|
*/
|
|
64
|
-
async
|
|
65
|
-
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
const authToken = this.tokenStore.get(token);
|
|
69
|
-
if (!authToken || authToken.type !== protocol) {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
// Check expiration if set
|
|
73
|
-
if (authToken.expiresAt && authToken.expiresAt < new Date()) {
|
|
74
|
-
this.tokenStore.delete(token);
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
return authToken;
|
|
48
|
+
async validateToken(tokenString, protocol) {
|
|
49
|
+
return this.provider.validateToken(tokenString, protocol);
|
|
78
50
|
}
|
|
79
51
|
/**
|
|
80
|
-
*
|
|
81
|
-
* @param token -
|
|
52
|
+
* Check if token has permission for an action
|
|
53
|
+
* @param token - Auth token (or null for anonymous)
|
|
54
|
+
* @param resource - Resource being accessed (e.g., "npm:package:foo")
|
|
55
|
+
* @param action - Action being performed (read, write, push, pull, delete)
|
|
56
|
+
* @returns true if authorized
|
|
82
57
|
*/
|
|
83
|
-
async
|
|
84
|
-
this.
|
|
58
|
+
async authorize(token, resource, action) {
|
|
59
|
+
return this.provider.authorize(token, resource, action);
|
|
85
60
|
}
|
|
86
61
|
// ========================================================================
|
|
87
62
|
// NPM AUTHENTICATION
|
|
@@ -96,7 +71,7 @@ export class AuthManager {
|
|
|
96
71
|
if (!this.config.npmTokens.enabled) {
|
|
97
72
|
throw new Error('NPM tokens are not enabled');
|
|
98
73
|
}
|
|
99
|
-
return this.
|
|
74
|
+
return this.provider.createToken(userId, 'npm', { readonly });
|
|
100
75
|
}
|
|
101
76
|
/**
|
|
102
77
|
* Validate an NPM token
|
|
@@ -104,14 +79,14 @@ export class AuthManager {
|
|
|
104
79
|
* @returns Auth token object or null
|
|
105
80
|
*/
|
|
106
81
|
async validateNpmToken(token) {
|
|
107
|
-
return this.
|
|
82
|
+
return this.provider.validateToken(token, 'npm');
|
|
108
83
|
}
|
|
109
84
|
/**
|
|
110
85
|
* Revoke an NPM token
|
|
111
86
|
* @param token - NPM UUID token
|
|
112
87
|
*/
|
|
113
88
|
async revokeNpmToken(token) {
|
|
114
|
-
return this.
|
|
89
|
+
return this.provider.revokeToken(token);
|
|
115
90
|
}
|
|
116
91
|
/**
|
|
117
92
|
* List all tokens for a user
|
|
@@ -119,17 +94,10 @@ export class AuthManager {
|
|
|
119
94
|
* @returns List of token info (without actual token values)
|
|
120
95
|
*/
|
|
121
96
|
async listUserTokens(userId) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (authToken.userId === userId) {
|
|
125
|
-
tokens.push({
|
|
126
|
-
key: this.hashToken(token),
|
|
127
|
-
readonly: authToken.readonly || false,
|
|
128
|
-
created: authToken.metadata?.created || 'unknown',
|
|
129
|
-
});
|
|
130
|
-
}
|
|
97
|
+
if (this.provider.listUserTokens) {
|
|
98
|
+
return this.provider.listUserTokens(userId);
|
|
131
99
|
}
|
|
132
|
-
return
|
|
100
|
+
return [];
|
|
133
101
|
}
|
|
134
102
|
// ========================================================================
|
|
135
103
|
// OCI AUTHENTICATION (JWT)
|
|
@@ -139,31 +107,13 @@ export class AuthManager {
|
|
|
139
107
|
* @param userId - User ID
|
|
140
108
|
* @param scopes - Permission scopes
|
|
141
109
|
* @param expiresIn - Expiration time in seconds
|
|
142
|
-
* @returns JWT token string
|
|
110
|
+
* @returns JWT token string
|
|
143
111
|
*/
|
|
144
112
|
async createOciToken(userId, scopes, expiresIn = 3600) {
|
|
145
|
-
if (!this.config.ociTokens
|
|
113
|
+
if (!this.config.ociTokens?.enabled) {
|
|
146
114
|
throw new Error('OCI tokens are not enabled');
|
|
147
115
|
}
|
|
148
|
-
|
|
149
|
-
const payload = {
|
|
150
|
-
iss: this.config.ociTokens.realm,
|
|
151
|
-
sub: userId,
|
|
152
|
-
aud: this.config.ociTokens.service,
|
|
153
|
-
exp: now + expiresIn,
|
|
154
|
-
nbf: now,
|
|
155
|
-
iat: now,
|
|
156
|
-
access: this.scopesToOciAccess(scopes),
|
|
157
|
-
};
|
|
158
|
-
// Create JWT with HMAC-SHA256 signature
|
|
159
|
-
const header = { alg: 'HS256', typ: 'JWT' };
|
|
160
|
-
const headerB64 = Buffer.from(JSON.stringify(header)).toString('base64url');
|
|
161
|
-
const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url');
|
|
162
|
-
const signature = crypto
|
|
163
|
-
.createHmac('sha256', this.config.jwtSecret)
|
|
164
|
-
.update(`${headerB64}.${payloadB64}`)
|
|
165
|
-
.digest('base64url');
|
|
166
|
-
return `${headerB64}.${payloadB64}.${signature}`;
|
|
116
|
+
return this.provider.createToken(userId, 'oci', { scopes, expiresIn });
|
|
167
117
|
}
|
|
168
118
|
/**
|
|
169
119
|
* Validate an OCI JWT token
|
|
@@ -171,68 +121,7 @@ export class AuthManager {
|
|
|
171
121
|
* @returns Auth token object or null
|
|
172
122
|
*/
|
|
173
123
|
async validateOciToken(jwt) {
|
|
174
|
-
|
|
175
|
-
const parts = jwt.split('.');
|
|
176
|
-
if (parts.length !== 3) {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
const [headerB64, payloadB64, signatureB64] = parts;
|
|
180
|
-
// Verify signature
|
|
181
|
-
const expectedSignature = crypto
|
|
182
|
-
.createHmac('sha256', this.config.jwtSecret)
|
|
183
|
-
.update(`${headerB64}.${payloadB64}`)
|
|
184
|
-
.digest('base64url');
|
|
185
|
-
if (signatureB64 !== expectedSignature) {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
// Decode and parse payload
|
|
189
|
-
const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8'));
|
|
190
|
-
// Check expiration
|
|
191
|
-
const now = Math.floor(Date.now() / 1000);
|
|
192
|
-
if (payload.exp && payload.exp < now) {
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
// Check not-before time
|
|
196
|
-
if (payload.nbf && payload.nbf > now) {
|
|
197
|
-
return null;
|
|
198
|
-
}
|
|
199
|
-
// Convert to unified token format
|
|
200
|
-
const scopes = this.ociAccessToScopes(payload.access || []);
|
|
201
|
-
return {
|
|
202
|
-
type: 'oci',
|
|
203
|
-
userId: payload.sub,
|
|
204
|
-
scopes,
|
|
205
|
-
expiresAt: payload.exp ? new Date(payload.exp * 1000) : undefined,
|
|
206
|
-
metadata: {
|
|
207
|
-
iss: payload.iss,
|
|
208
|
-
aud: payload.aud,
|
|
209
|
-
},
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
catch (error) {
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// ========================================================================
|
|
217
|
-
// UNIFIED AUTHENTICATION
|
|
218
|
-
// ========================================================================
|
|
219
|
-
/**
|
|
220
|
-
* Authenticate user credentials
|
|
221
|
-
* @param credentials - Username and password
|
|
222
|
-
* @returns User ID or null
|
|
223
|
-
*/
|
|
224
|
-
async authenticate(credentials) {
|
|
225
|
-
// Mock authentication - in production, verify against database
|
|
226
|
-
const storedPassword = this.userCredentials.get(credentials.username);
|
|
227
|
-
if (!storedPassword) {
|
|
228
|
-
// Auto-register for testing (remove in production)
|
|
229
|
-
this.userCredentials.set(credentials.username, credentials.password);
|
|
230
|
-
return credentials.username;
|
|
231
|
-
}
|
|
232
|
-
if (storedPassword === credentials.password) {
|
|
233
|
-
return credentials.username;
|
|
234
|
-
}
|
|
235
|
-
return null;
|
|
124
|
+
return this.provider.validateToken(jwt, 'oci');
|
|
236
125
|
}
|
|
237
126
|
// ========================================================================
|
|
238
127
|
// MAVEN AUTHENTICATION
|
|
@@ -244,7 +133,7 @@ export class AuthManager {
|
|
|
244
133
|
* @returns Maven UUID token
|
|
245
134
|
*/
|
|
246
135
|
async createMavenToken(userId, readonly = false) {
|
|
247
|
-
return this.
|
|
136
|
+
return this.provider.createToken(userId, 'maven', { readonly });
|
|
248
137
|
}
|
|
249
138
|
/**
|
|
250
139
|
* Validate a Maven token
|
|
@@ -252,14 +141,14 @@ export class AuthManager {
|
|
|
252
141
|
* @returns Auth token object or null
|
|
253
142
|
*/
|
|
254
143
|
async validateMavenToken(token) {
|
|
255
|
-
return this.
|
|
144
|
+
return this.provider.validateToken(token, 'maven');
|
|
256
145
|
}
|
|
257
146
|
/**
|
|
258
147
|
* Revoke a Maven token
|
|
259
148
|
* @param token - Maven UUID token
|
|
260
149
|
*/
|
|
261
150
|
async revokeMavenToken(token) {
|
|
262
|
-
return this.
|
|
151
|
+
return this.provider.revokeToken(token);
|
|
263
152
|
}
|
|
264
153
|
// ========================================================================
|
|
265
154
|
// COMPOSER TOKEN MANAGEMENT
|
|
@@ -271,7 +160,7 @@ export class AuthManager {
|
|
|
271
160
|
* @returns Composer UUID token
|
|
272
161
|
*/
|
|
273
162
|
async createComposerToken(userId, readonly = false) {
|
|
274
|
-
return this.
|
|
163
|
+
return this.provider.createToken(userId, 'composer', { readonly });
|
|
275
164
|
}
|
|
276
165
|
/**
|
|
277
166
|
* Validate a Composer token
|
|
@@ -279,14 +168,14 @@ export class AuthManager {
|
|
|
279
168
|
* @returns Auth token object or null
|
|
280
169
|
*/
|
|
281
170
|
async validateComposerToken(token) {
|
|
282
|
-
return this.
|
|
171
|
+
return this.provider.validateToken(token, 'composer');
|
|
283
172
|
}
|
|
284
173
|
/**
|
|
285
174
|
* Revoke a Composer token
|
|
286
175
|
* @param token - Composer UUID token
|
|
287
176
|
*/
|
|
288
177
|
async revokeComposerToken(token) {
|
|
289
|
-
return this.
|
|
178
|
+
return this.provider.revokeToken(token);
|
|
290
179
|
}
|
|
291
180
|
// ========================================================================
|
|
292
181
|
// CARGO TOKEN MANAGEMENT
|
|
@@ -298,7 +187,7 @@ export class AuthManager {
|
|
|
298
187
|
* @returns Cargo UUID token
|
|
299
188
|
*/
|
|
300
189
|
async createCargoToken(userId, readonly = false) {
|
|
301
|
-
return this.
|
|
190
|
+
return this.provider.createToken(userId, 'cargo', { readonly });
|
|
302
191
|
}
|
|
303
192
|
/**
|
|
304
193
|
* Validate a Cargo token
|
|
@@ -306,14 +195,14 @@ export class AuthManager {
|
|
|
306
195
|
* @returns Auth token object or null
|
|
307
196
|
*/
|
|
308
197
|
async validateCargoToken(token) {
|
|
309
|
-
return this.
|
|
198
|
+
return this.provider.validateToken(token, 'cargo');
|
|
310
199
|
}
|
|
311
200
|
/**
|
|
312
201
|
* Revoke a Cargo token
|
|
313
202
|
* @param token - Cargo UUID token
|
|
314
203
|
*/
|
|
315
204
|
async revokeCargoToken(token) {
|
|
316
|
-
return this.
|
|
205
|
+
return this.provider.revokeToken(token);
|
|
317
206
|
}
|
|
318
207
|
// ========================================================================
|
|
319
208
|
// PYPI AUTHENTICATION
|
|
@@ -325,7 +214,7 @@ export class AuthManager {
|
|
|
325
214
|
* @returns PyPI UUID token
|
|
326
215
|
*/
|
|
327
216
|
async createPypiToken(userId, readonly = false) {
|
|
328
|
-
return this.
|
|
217
|
+
return this.provider.createToken(userId, 'pypi', { readonly });
|
|
329
218
|
}
|
|
330
219
|
/**
|
|
331
220
|
* Validate a PyPI token
|
|
@@ -333,14 +222,14 @@ export class AuthManager {
|
|
|
333
222
|
* @returns Auth token object or null
|
|
334
223
|
*/
|
|
335
224
|
async validatePypiToken(token) {
|
|
336
|
-
return this.
|
|
225
|
+
return this.provider.validateToken(token, 'pypi');
|
|
337
226
|
}
|
|
338
227
|
/**
|
|
339
228
|
* Revoke a PyPI token
|
|
340
229
|
* @param token - PyPI UUID token
|
|
341
230
|
*/
|
|
342
231
|
async revokePypiToken(token) {
|
|
343
|
-
return this.
|
|
232
|
+
return this.provider.revokeToken(token);
|
|
344
233
|
}
|
|
345
234
|
// ========================================================================
|
|
346
235
|
// RUBYGEMS AUTHENTICATION
|
|
@@ -352,7 +241,7 @@ export class AuthManager {
|
|
|
352
241
|
* @returns RubyGems UUID token
|
|
353
242
|
*/
|
|
354
243
|
async createRubyGemsToken(userId, readonly = false) {
|
|
355
|
-
return this.
|
|
244
|
+
return this.provider.createToken(userId, 'rubygems', { readonly });
|
|
356
245
|
}
|
|
357
246
|
/**
|
|
358
247
|
* Validate a RubyGems token
|
|
@@ -360,177 +249,14 @@ export class AuthManager {
|
|
|
360
249
|
* @returns Auth token object or null
|
|
361
250
|
*/
|
|
362
251
|
async validateRubyGemsToken(token) {
|
|
363
|
-
return this.
|
|
252
|
+
return this.provider.validateToken(token, 'rubygems');
|
|
364
253
|
}
|
|
365
254
|
/**
|
|
366
255
|
* Revoke a RubyGems token
|
|
367
256
|
* @param token - RubyGems UUID token
|
|
368
257
|
*/
|
|
369
258
|
async revokeRubyGemsToken(token) {
|
|
370
|
-
return this.
|
|
371
|
-
}
|
|
372
|
-
// ========================================================================
|
|
373
|
-
// UNIFIED AUTHENTICATION
|
|
374
|
-
// ========================================================================
|
|
375
|
-
/**
|
|
376
|
-
* Validate any token (NPM, Maven, OCI, PyPI, RubyGems, Composer, Cargo)
|
|
377
|
-
* Optimized: O(1) lookup when protocol hint provided
|
|
378
|
-
* @param tokenString - Token string (UUID or JWT)
|
|
379
|
-
* @param protocol - Expected protocol type (optional, improves performance)
|
|
380
|
-
* @returns Auth token object or null
|
|
381
|
-
*/
|
|
382
|
-
async validateToken(tokenString, protocol) {
|
|
383
|
-
// OCI uses JWT (contains dots), not UUID - check first if OCI is expected
|
|
384
|
-
if (protocol === 'oci' || tokenString.includes('.')) {
|
|
385
|
-
const ociToken = await this.validateOciToken(tokenString);
|
|
386
|
-
if (ociToken && (!protocol || protocol === 'oci')) {
|
|
387
|
-
return ociToken;
|
|
388
|
-
}
|
|
389
|
-
// If protocol was explicitly OCI but validation failed, return null
|
|
390
|
-
if (protocol === 'oci') {
|
|
391
|
-
return null;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
// UUID-based tokens: single O(1) Map lookup
|
|
395
|
-
if (this.isValidUuid(tokenString)) {
|
|
396
|
-
const authToken = this.tokenStore.get(tokenString);
|
|
397
|
-
if (authToken) {
|
|
398
|
-
// If protocol specified, verify it matches
|
|
399
|
-
if (protocol && authToken.type !== protocol) {
|
|
400
|
-
return null;
|
|
401
|
-
}
|
|
402
|
-
// Check expiration
|
|
403
|
-
if (authToken.expiresAt && authToken.expiresAt < new Date()) {
|
|
404
|
-
this.tokenStore.delete(tokenString);
|
|
405
|
-
return null;
|
|
406
|
-
}
|
|
407
|
-
return authToken;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return null;
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* Check if token has permission for an action
|
|
414
|
-
* @param token - Auth token
|
|
415
|
-
* @param resource - Resource being accessed (e.g., "package:foo" or "repository:bar")
|
|
416
|
-
* @param action - Action being performed (read, write, push, pull, delete)
|
|
417
|
-
* @returns true if authorized
|
|
418
|
-
*/
|
|
419
|
-
async authorize(token, resource, action) {
|
|
420
|
-
if (!token) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
// Check readonly flag
|
|
424
|
-
if (token.readonly && ['write', 'push', 'delete'].includes(action)) {
|
|
425
|
-
return false;
|
|
426
|
-
}
|
|
427
|
-
// Check scopes
|
|
428
|
-
for (const scope of token.scopes) {
|
|
429
|
-
if (this.matchesScope(scope, resource, action)) {
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
return false;
|
|
434
|
-
}
|
|
435
|
-
// ========================================================================
|
|
436
|
-
// HELPER METHODS
|
|
437
|
-
// ========================================================================
|
|
438
|
-
/**
|
|
439
|
-
* Check if a scope matches a resource and action
|
|
440
|
-
* Scope format: "{protocol}:{type}:{name}:{action}"
|
|
441
|
-
* Examples:
|
|
442
|
-
* - "npm:*:*" - All NPM access
|
|
443
|
-
* - "npm:package:foo:*" - All actions on package foo
|
|
444
|
-
* - "npm:package:foo:read" - Read-only on package foo
|
|
445
|
-
* - "oci:repository:*:pull" - Pull from any OCI repo
|
|
446
|
-
*/
|
|
447
|
-
matchesScope(scope, resource, action) {
|
|
448
|
-
const scopeParts = scope.split(':');
|
|
449
|
-
const resourceParts = resource.split(':');
|
|
450
|
-
// Scope must have at least protocol:type:name:action
|
|
451
|
-
if (scopeParts.length < 4) {
|
|
452
|
-
return false;
|
|
453
|
-
}
|
|
454
|
-
const [scopeProtocol, scopeType, scopeName, scopeAction] = scopeParts;
|
|
455
|
-
const [resourceProtocol, resourceType, resourceName] = resourceParts;
|
|
456
|
-
// Check protocol
|
|
457
|
-
if (scopeProtocol !== '*' && scopeProtocol !== resourceProtocol) {
|
|
458
|
-
return false;
|
|
459
|
-
}
|
|
460
|
-
// Check type
|
|
461
|
-
if (scopeType !== '*' && scopeType !== resourceType) {
|
|
462
|
-
return false;
|
|
463
|
-
}
|
|
464
|
-
// Check name
|
|
465
|
-
if (scopeName !== '*' && scopeName !== resourceName) {
|
|
466
|
-
return false;
|
|
467
|
-
}
|
|
468
|
-
// Check action
|
|
469
|
-
if (scopeAction !== '*' && scopeAction !== action) {
|
|
470
|
-
// Map action aliases
|
|
471
|
-
const actionAliases = {
|
|
472
|
-
read: ['pull', 'get'],
|
|
473
|
-
write: ['push', 'put', 'post'],
|
|
474
|
-
};
|
|
475
|
-
const aliases = actionAliases[scopeAction] || [];
|
|
476
|
-
if (!aliases.includes(action)) {
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
return true;
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Convert unified scopes to OCI access array
|
|
484
|
-
*/
|
|
485
|
-
scopesToOciAccess(scopes) {
|
|
486
|
-
const access = [];
|
|
487
|
-
for (const scope of scopes) {
|
|
488
|
-
const parts = scope.split(':');
|
|
489
|
-
if (parts.length >= 4 && parts[0] === 'oci') {
|
|
490
|
-
access.push({
|
|
491
|
-
type: parts[1],
|
|
492
|
-
name: parts[2],
|
|
493
|
-
actions: [parts[3]],
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
return access;
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Convert OCI access array to unified scopes
|
|
501
|
-
*/
|
|
502
|
-
ociAccessToScopes(access) {
|
|
503
|
-
const scopes = [];
|
|
504
|
-
for (const item of access) {
|
|
505
|
-
for (const action of item.actions) {
|
|
506
|
-
scopes.push(`oci:${item.type}:${item.name}:${action}`);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
return scopes;
|
|
510
|
-
}
|
|
511
|
-
/**
|
|
512
|
-
* Generate UUID for NPM tokens
|
|
513
|
-
*/
|
|
514
|
-
generateUuid() {
|
|
515
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
516
|
-
const r = (Math.random() * 16) | 0;
|
|
517
|
-
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
518
|
-
return v.toString(16);
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Check if string is a valid UUID
|
|
523
|
-
*/
|
|
524
|
-
isValidUuid(str) {
|
|
525
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
526
|
-
return uuidRegex.test(str);
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* Hash a token for identification (SHA-512 mock)
|
|
530
|
-
*/
|
|
531
|
-
hashToken(token) {
|
|
532
|
-
// In production, use actual SHA-512
|
|
533
|
-
return `sha512-${token.substring(0, 16)}...`;
|
|
259
|
+
return this.provider.revokeToken(token);
|
|
534
260
|
}
|
|
535
261
|
}
|
|
536
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRobWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmUvY2xhc3Nlcy5hdXRobWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUVqQzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sV0FBVztJQUlGO0lBSFosVUFBVSxHQUE0QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2hELGVBQWUsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLG1DQUFtQztJQUU3RixZQUFvQixNQUFtQjtRQUFuQixXQUFNLEdBQU4sTUFBTSxDQUFhO0lBQUcsQ0FBQztJQUUzQzs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsNkNBQTZDO1FBQzdDLG1EQUFtRDtJQUNyRCxDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLHlEQUF5RDtJQUN6RCwyRUFBMkU7SUFFM0U7Ozs7Ozs7T0FPRztJQUNLLEtBQUssQ0FBQyxlQUFlLENBQzNCLE1BQWMsRUFDZCxRQUEyQixFQUMzQixNQUFnQixFQUNoQixXQUFvQixLQUFLO1FBRXpCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsQyxNQUFNLFNBQVMsR0FBZTtZQUM1QixJQUFJLEVBQUUsUUFBUTtZQUNkLE1BQU07WUFDTixNQUFNO1lBQ04sUUFBUTtZQUNSLFFBQVEsRUFBRTtnQkFDUixPQUFPLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7YUFDbEM7U0FDRixDQUFDO1FBRUYsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNLLEtBQUssQ0FBQyxtQkFBbUIsQ0FDL0IsTUFBYyxFQUNkLFFBQTJCLEVBQzNCLFFBQWlCO1FB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
|
|
262
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRobWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmUvY2xhc3Nlcy5hdXRobWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUV2RTs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLE9BQU8sV0FBVztJQUlaO0lBSEYsUUFBUSxDQUFnQjtJQUVoQyxZQUNVLE1BQW1CLEVBQzNCLFFBQXdCO1FBRGhCLFdBQU0sR0FBTixNQUFNLENBQWE7UUFHM0IsNERBQTREO1FBQzVELElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLElBQUksbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLElBQUk7UUFDZixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzdCLENBQUM7SUFDSCxDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLGlEQUFpRDtJQUNqRCwyRUFBMkU7SUFFM0U7Ozs7T0FJRztJQUNJLEtBQUssQ0FBQyxZQUFZLENBQUMsV0FBeUI7UUFDakQsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsYUFBYSxDQUN4QixXQUFtQixFQUNuQixRQUE0QjtRQUU1QixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksS0FBSyxDQUFDLFNBQVMsQ0FDcEIsS0FBd0IsRUFDeEIsUUFBZ0IsRUFDaEIsTUFBYztRQUVkLE9BQU8sSUFB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
|