@fleetbase/registry-bridge-engine 0.0.1 → 0.0.3
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/addon/components/modals/create-registry-credentials.hbs +5 -0
- package/addon/components/registry-admin-config.hbs +16 -0
- package/addon/components/registry-admin-config.js +36 -0
- package/addon/controllers/developers/credentials.js +106 -0
- package/addon/engine.js +8 -2
- package/addon/routes/developers/credentials.js +8 -1
- package/addon/templates/application.hbs +1 -0
- package/addon/templates/developers/credentials.hbs +13 -1
- package/addon/templates/developers/payments/index.hbs +14 -13
- package/addon/templates/installed.hbs +3 -3
- package/app/components/modals/create-registry-credentials.js +1 -0
- package/app/components/registry-admin-config.js +1 -0
- package/app/controllers/developers/credentials.js +1 -0
- package/composer.json +2 -2
- package/extension.json +1 -1
- package/package.json +5 -5
- package/server/config/registry-bridge.php +2 -1
- package/server/migrations/2024_07_18_151000_add_auth_token_column_to_registry_users_table.php +28 -0
- package/server/src/Http/Controllers/Internal/v1/RegistryAuthController.php +163 -24
- package/server/src/Http/Controllers/Internal/v1/RegistryExtensionBundleController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/RegistryExtensionController.php +59 -1
- package/server/src/Http/Filter/RegistryExtensionFilter.php +1 -1
- package/server/src/Http/Requests/RegistryAuthRequest.php +3 -1
- package/server/src/Http/Resources/RegistryUser.php +0 -12
- package/server/src/Models/RegistryExtension.php +42 -3
- package/server/src/Models/RegistryExtensionBundle.php +1 -1
- package/server/src/Models/RegistryUser.php +111 -1
- package/server/src/Providers/RegistryBridgeServiceProvider.php +16 -31
- package/server/src/Support/Bridge.php +123 -0
- package/server/src/Support/Utils.php +136 -1
- package/server/src/routes.php +45 -31
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
namespace Fleetbase\RegistryBridge\Http\Controllers\Internal\v1;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Exceptions\FleetbaseRequestValidationException;
|
|
6
|
+
use Fleetbase\Models\Setting;
|
|
6
7
|
use Fleetbase\RegistryBridge\Http\Controllers\RegistryBridgeController;
|
|
7
8
|
use Fleetbase\RegistryBridge\Http\Requests\CreateRegistryExtensionRequest;
|
|
8
9
|
use Fleetbase\RegistryBridge\Http\Requests\RegistryExtensionActionRequest;
|
|
9
10
|
use Fleetbase\RegistryBridge\Models\RegistryExtension;
|
|
10
|
-
use Fleetbase\Support\Utils;
|
|
11
|
+
use Fleetbase\RegistryBridge\Support\Utils;
|
|
11
12
|
use Illuminate\Http\Request;
|
|
12
13
|
use Illuminate\Support\Facades\Storage;
|
|
13
14
|
use Illuminate\Support\Facades\Validator;
|
|
@@ -254,4 +255,61 @@ class RegistryExtensionController extends RegistryBridgeController
|
|
|
254
255
|
|
|
255
256
|
return response()->error('Failed to download extension bundle');
|
|
256
257
|
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Retrieve the current registry configuration.
|
|
261
|
+
*
|
|
262
|
+
* This method fetches the current registry host and token from the configuration
|
|
263
|
+
* settings or environment variables and returns them in a JSON response.
|
|
264
|
+
*
|
|
265
|
+
* @return \Illuminate\Http\JsonResponse a JSON response containing the registry host and token
|
|
266
|
+
*/
|
|
267
|
+
public function getConfig()
|
|
268
|
+
{
|
|
269
|
+
$registryHost = config('registry-bridge.registry.host', env('REGISTRY_HOST', 'https://registry.fleetbase.io'));
|
|
270
|
+
$registryToken = config('registry-bridge.registry.token', env('REGISTRY_TOKEN'));
|
|
271
|
+
|
|
272
|
+
return response()->json([
|
|
273
|
+
'host' => $registryHost,
|
|
274
|
+
'token' => $registryToken,
|
|
275
|
+
]);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Save the registry configuration.
|
|
280
|
+
*
|
|
281
|
+
* This method updates the registry host and token based on the provided request input.
|
|
282
|
+
* If no input is provided, it uses the current configuration values or environment variables.
|
|
283
|
+
* The updated configuration is then saved in the settings and returned in a JSON response.
|
|
284
|
+
*
|
|
285
|
+
* @param Request $request the incoming HTTP request containing the new host and token
|
|
286
|
+
*
|
|
287
|
+
* @return \Illuminate\Http\JsonResponse a JSON response containing the updated registry host and token
|
|
288
|
+
*/
|
|
289
|
+
public function saveConfig(Request $request)
|
|
290
|
+
{
|
|
291
|
+
$currentRegistryHost = config('registry-bridge.registry.host', env('REGISTRY_HOST', 'https://registry.fleetbase.io'));
|
|
292
|
+
$currentRegistryToken = config('registry-bridge.registry.token', env('REGISTRY_TOKEN'));
|
|
293
|
+
$registryHost = $request->input('host', $currentRegistryHost);
|
|
294
|
+
$registryToken = $request->input('token', $currentRegistryToken);
|
|
295
|
+
|
|
296
|
+
// Save values in settings and config
|
|
297
|
+
if ($registryHost) {
|
|
298
|
+
Setting::configure('registry-bridge.registry.host', $registryHost);
|
|
299
|
+
config(['registry-bridge.registry.host' => $registryHost]);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if ($registryToken) {
|
|
303
|
+
Setting::configure('registry-bridge.registry.token', $registryToken);
|
|
304
|
+
config(['registry-bridge.registry.token' => $registryToken]);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Reboot registry auth
|
|
308
|
+
Utils::bootRegistryAuth(true);
|
|
309
|
+
|
|
310
|
+
return response()->json([
|
|
311
|
+
'host' => $registryHost,
|
|
312
|
+
'token' => $registryToken,
|
|
313
|
+
]);
|
|
314
|
+
}
|
|
257
315
|
}
|
|
@@ -5,6 +5,7 @@ namespace Fleetbase\RegistryBridge\Http\Requests;
|
|
|
5
5
|
use Fleetbase\Http\Requests\FleetbaseRequest;
|
|
6
6
|
use Fleetbase\Models\User;
|
|
7
7
|
use Illuminate\Support\Facades\Validator;
|
|
8
|
+
use Illuminate\Validation\Rule;
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Request class to handle the addition of new registry users.
|
|
@@ -40,7 +41,8 @@ class RegistryAuthRequest extends FleetbaseRequest
|
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
return [
|
|
43
|
-
'identity' => ['
|
|
44
|
+
'identity' => [Rule::requiredIf($this->isNotFilled('package')), 'valid_identity'],
|
|
45
|
+
'package' => ['nullable'],
|
|
44
46
|
];
|
|
45
47
|
}
|
|
46
48
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
namespace Fleetbase\RegistryBridge\Http\Resources;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Http\Resources\FleetbaseResource;
|
|
6
|
-
use Fleetbase\Models\Group;
|
|
7
6
|
|
|
8
7
|
class RegistryUser extends FleetbaseResource
|
|
9
8
|
{
|
|
@@ -26,15 +25,4 @@ class RegistryUser extends FleetbaseResource
|
|
|
26
25
|
'created_at' => $this->created_at,
|
|
27
26
|
];
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
public function groups(): array
|
|
31
|
-
{
|
|
32
|
-
return collect(['$all', '$authenticated', ...data_get($this->user, 'groups', [])])->map(function ($group) {
|
|
33
|
-
if ($group instanceof Group) {
|
|
34
|
-
return $group->public_id;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return $group;
|
|
38
|
-
})->toArray();
|
|
39
|
-
}
|
|
40
28
|
}
|
|
@@ -10,7 +10,6 @@ use Fleetbase\Models\File;
|
|
|
10
10
|
use Fleetbase\Models\Model;
|
|
11
11
|
use Fleetbase\Models\User;
|
|
12
12
|
use Fleetbase\RegistryBridge\Support\Utils;
|
|
13
|
-
use Fleetbase\Support\Utils as SupportUtils;
|
|
14
13
|
use Fleetbase\Traits\HasApiModelBehavior;
|
|
15
14
|
use Fleetbase\Traits\HasMetaAttributes;
|
|
16
15
|
use Fleetbase\Traits\HasPublicId;
|
|
@@ -627,7 +626,7 @@ class RegistryExtension extends Model
|
|
|
627
626
|
|
|
628
627
|
// Calculate the fee fleetbase takes for faciliation of extension
|
|
629
628
|
$totalAmount = $price->unit_amount;
|
|
630
|
-
$facilitatorFee =
|
|
629
|
+
$facilitatorFee = Utils::calculatePercentage(config('registry-bridge.facilitator_fee', 10), $totalAmount);
|
|
631
630
|
|
|
632
631
|
// Get the stripe client to create the checkout session
|
|
633
632
|
$stripe = Utils::getStripeClient();
|
|
@@ -642,7 +641,7 @@ class RegistryExtension extends Model
|
|
|
642
641
|
],
|
|
643
642
|
],
|
|
644
643
|
'mode' => 'payment',
|
|
645
|
-
'return_url' =>
|
|
644
|
+
'return_url' => Utils::consoleUrl($returnUri) . '?extension_id=' . $this->uuid . '&checkout_session_id={CHECKOUT_SESSION_ID}',
|
|
646
645
|
'payment_intent_data' => [
|
|
647
646
|
'application_fee_amount' => $facilitatorFee,
|
|
648
647
|
'transfer_data' => [
|
|
@@ -653,4 +652,44 @@ class RegistryExtension extends Model
|
|
|
653
652
|
|
|
654
653
|
return $checkoutSession;
|
|
655
654
|
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Determine if the registry user has access to the registry extension.
|
|
658
|
+
*
|
|
659
|
+
* This method checks if the extension requires payment. If it does not,
|
|
660
|
+
* access is granted. If payment is required, it checks if the user's company
|
|
661
|
+
* has made a purchase of the extension.
|
|
662
|
+
*
|
|
663
|
+
* @param RegistryUser $registryUser the registry user to check access for
|
|
664
|
+
*
|
|
665
|
+
* @return bool true if the user has access, false otherwise
|
|
666
|
+
*/
|
|
667
|
+
public function hasAccess(RegistryUser $registryUser): bool
|
|
668
|
+
{
|
|
669
|
+
if (!$this->payment_required) {
|
|
670
|
+
return true;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
return $this->purchases()->where('company_uuid', $registryUser->company_uuid)->exists();
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Determine if the registry user does not have access to the registry extension.
|
|
678
|
+
*
|
|
679
|
+
* This method checks if the extension requires payment. If it does not,
|
|
680
|
+
* access is always denied. If payment is required, it checks if the user's
|
|
681
|
+
* company has not made a purchase of the extension.
|
|
682
|
+
*
|
|
683
|
+
* @param RegistryUser $registryUser the registry user to check access for
|
|
684
|
+
*
|
|
685
|
+
* @return bool true if the user does not have access, false otherwise
|
|
686
|
+
*/
|
|
687
|
+
public function doesntHaveAccess(RegistryUser $registryUser): bool
|
|
688
|
+
{
|
|
689
|
+
if (!$this->payment_required) {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return $this->purchases()->where('company_uuid', $registryUser->company_uuid)->doesntExist();
|
|
694
|
+
}
|
|
656
695
|
}
|
|
@@ -8,8 +8,8 @@ use Fleetbase\Models\File;
|
|
|
8
8
|
use Fleetbase\Models\Model;
|
|
9
9
|
use Fleetbase\Models\User;
|
|
10
10
|
use Fleetbase\RegistryBridge\Exceptions\InstallFailedException;
|
|
11
|
+
use Fleetbase\RegistryBridge\Support\Utils;
|
|
11
12
|
use Fleetbase\Support\SocketCluster\SocketClusterService;
|
|
12
|
-
use Fleetbase\Support\Utils;
|
|
13
13
|
use Fleetbase\Traits\HasApiModelBehavior;
|
|
14
14
|
use Fleetbase\Traits\HasMetaAttributes;
|
|
15
15
|
use Fleetbase\Traits\HasPublicId;
|
|
@@ -41,6 +41,7 @@ class RegistryUser extends Model
|
|
|
41
41
|
'company_uuid',
|
|
42
42
|
'user_uuid',
|
|
43
43
|
'token',
|
|
44
|
+
'registry_token',
|
|
44
45
|
'scope',
|
|
45
46
|
'expires_at',
|
|
46
47
|
'last_used_at',
|
|
@@ -65,7 +66,7 @@ class RegistryUser extends Model
|
|
|
65
66
|
*
|
|
66
67
|
* @var array
|
|
67
68
|
*/
|
|
68
|
-
protected $appends = [];
|
|
69
|
+
protected $appends = ['is_admin'];
|
|
69
70
|
|
|
70
71
|
/**
|
|
71
72
|
* The attributes excluded from the model's JSON form.
|
|
@@ -114,6 +115,54 @@ class RegistryUser extends Model
|
|
|
114
115
|
return $this->belongsTo(User::class);
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
/**
|
|
119
|
+
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
120
|
+
*/
|
|
121
|
+
public function extensions()
|
|
122
|
+
{
|
|
123
|
+
return $this->hasMany(RegistryExtension::class, 'company_uuid', 'company_uuid');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
128
|
+
*/
|
|
129
|
+
public function purchases()
|
|
130
|
+
{
|
|
131
|
+
return $this->hasMany(RegistryExtensionPurchase::class, 'company_uuid', 'company_uuid');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Undocumented function.
|
|
136
|
+
*/
|
|
137
|
+
public function getIsAdminAttribute(): bool
|
|
138
|
+
{
|
|
139
|
+
return $this->user->is_admin === true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Determine if the user is an admin.
|
|
144
|
+
*
|
|
145
|
+
* This method checks if the `is_admin` attribute of the user is set to true.
|
|
146
|
+
*
|
|
147
|
+
* @return bool true if the user is an admin, false otherwise
|
|
148
|
+
*/
|
|
149
|
+
public function isAdmin(): bool
|
|
150
|
+
{
|
|
151
|
+
return $this->is_admin === true;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Determine if the user is not an admin.
|
|
156
|
+
*
|
|
157
|
+
* This method checks if the `is_admin` attribute of the user is set to false.
|
|
158
|
+
*
|
|
159
|
+
* @return bool true if the user is not an admin, false otherwise
|
|
160
|
+
*/
|
|
161
|
+
public function isNotAdmin(): bool
|
|
162
|
+
{
|
|
163
|
+
return $this->is_admin === false;
|
|
164
|
+
}
|
|
165
|
+
|
|
117
166
|
/**
|
|
118
167
|
* Generates a unique token for authenticating with the registry.
|
|
119
168
|
*
|
|
@@ -137,4 +186,65 @@ class RegistryUser extends Model
|
|
|
137
186
|
|
|
138
187
|
return $token;
|
|
139
188
|
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Find a registry user by their username.
|
|
192
|
+
*
|
|
193
|
+
* This method joins the users table with the registry users table to find a
|
|
194
|
+
* registry user by their email or username. If a matching user is found, the
|
|
195
|
+
* corresponding registry user is returned.
|
|
196
|
+
*
|
|
197
|
+
* @param string $username the username to search for
|
|
198
|
+
*
|
|
199
|
+
* @return RegistryUser|null the found registry user, or null if no user is found
|
|
200
|
+
*/
|
|
201
|
+
public static function findFromUsername(string $username): ?RegistryUser
|
|
202
|
+
{
|
|
203
|
+
return static::select('registry_users.*')
|
|
204
|
+
->join('users', function ($join) use ($username) {
|
|
205
|
+
$join->on('users.uuid', '=', 'registry_users.user_uuid')
|
|
206
|
+
->on('users.company_uuid', '=', 'registry_users.company_uuid')
|
|
207
|
+
->where(function ($query) use ($username) {
|
|
208
|
+
$query->where('users.email', $username)
|
|
209
|
+
->orWhere('users.username', $username);
|
|
210
|
+
});
|
|
211
|
+
})
|
|
212
|
+
->first();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Determine if the registry user can access a specific package.
|
|
217
|
+
*
|
|
218
|
+
* This method checks if the package name exists in the list of purchased
|
|
219
|
+
* extensions for the user. It verifies if the package name matches either
|
|
220
|
+
* the `package.json` or `composer.json` name in the metadata of the current bundle
|
|
221
|
+
* of any purchased extension.
|
|
222
|
+
*
|
|
223
|
+
* @param string $packageName the name of the package to check access for
|
|
224
|
+
*
|
|
225
|
+
* @return bool true if the user can access the package, false otherwise
|
|
226
|
+
*/
|
|
227
|
+
public function canAccessPackage(string $packageName): bool
|
|
228
|
+
{
|
|
229
|
+
return $this->purchases()->whereHas('extension', function ($query) use ($packageName) {
|
|
230
|
+
$query->whereHas('currentBundle', function ($query) use ($packageName) {
|
|
231
|
+
$query->where('meta->package.json->name', $packageName)->orWhere('meta->composer.json->name', $packageName);
|
|
232
|
+
});
|
|
233
|
+
})->exists();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Retrieves the user's access groups.
|
|
238
|
+
*
|
|
239
|
+
* This method returns an array of groups that the user belongs to, including
|
|
240
|
+
* the default groups (`$all` and `$authenticated`) and the names of the purchased
|
|
241
|
+
* extension groups. The purchased extension groups are obtained by calling the
|
|
242
|
+
* `getPurchasedExtensionGroups` method.
|
|
243
|
+
*
|
|
244
|
+
* @return array an array of the user's access groups, including default and purchased extension groups
|
|
245
|
+
*/
|
|
246
|
+
public function groups(): array
|
|
247
|
+
{
|
|
248
|
+
return [$this->public_id];
|
|
249
|
+
}
|
|
140
250
|
}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Fleetbase\RegistryBridge\Providers;
|
|
4
4
|
|
|
5
|
+
use Fleetbase\Models\Setting;
|
|
5
6
|
use Fleetbase\Providers\CoreServiceProvider;
|
|
7
|
+
use Fleetbase\RegistryBridge\Support\Utils;
|
|
6
8
|
|
|
7
9
|
if (!class_exists(CoreServiceProvider::class)) {
|
|
8
10
|
throw new \Exception('Registry Bridge cannot be loaded without `fleetbase/core-api` installed!');
|
|
@@ -37,7 +39,6 @@ class RegistryBridgeServiceProvider extends CoreServiceProvider
|
|
|
37
39
|
*/
|
|
38
40
|
public $middleware = [
|
|
39
41
|
'fleetbase.registry' => [
|
|
40
|
-
'throttle:60,1',
|
|
41
42
|
\Illuminate\Session\Middleware\StartSession::class,
|
|
42
43
|
\Fleetbase\Http\Middleware\AuthenticateOnceWithBasicAuth::class,
|
|
43
44
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
|
@@ -71,47 +72,31 @@ class RegistryBridgeServiceProvider extends CoreServiceProvider
|
|
|
71
72
|
*/
|
|
72
73
|
public function boot()
|
|
73
74
|
{
|
|
74
|
-
|
|
75
|
+
Utils::bootRegistryAuth();
|
|
75
76
|
$this->registerCommands();
|
|
76
77
|
$this->registerMiddleware();
|
|
77
78
|
$this->registerExpansionsFrom(__DIR__ . '/../Expansions');
|
|
78
79
|
$this->loadRoutesFrom(__DIR__ . '/../routes.php');
|
|
79
80
|
$this->loadMigrationsFrom(__DIR__ . '/../../migrations');
|
|
80
81
|
$this->mergeConfigFrom(__DIR__ . '/../../config/registry-bridge.php', 'registry-bridge');
|
|
82
|
+
$this->mergeConfigFromSettings();
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
* Initializes and sets up the npm registry authentication configuration.
|
|
85
|
-
*
|
|
86
|
-
* This method constructs the registry authentication string from configuration settings,
|
|
87
|
-
* checks for the existence of an npmrc file in the user's home directory, and creates it
|
|
88
|
-
* with the registry authentication string if it doesn't already exist.
|
|
89
|
-
*
|
|
90
|
-
* The registry configuration and token are pulled from the application's configuration files.
|
|
91
|
-
* It ensures the path to the .npmrc file is correctly formed regardless of trailing slashes
|
|
92
|
-
* in the HOME directory path or the registry host configuration.
|
|
93
|
-
*
|
|
94
|
-
* @param bool $reset - Overwrites existing file, "resetting" the .npmrc
|
|
95
|
-
*
|
|
96
|
-
* @return void
|
|
97
|
-
*/
|
|
98
|
-
public static function bootRegistryAuth(bool $reset = false)
|
|
85
|
+
public function mergeConfigFromSettings()
|
|
99
86
|
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
87
|
+
if (Setting::doesntHaveConnection()) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
$registryHost = Setting::getByKey('registry-bridge.registry.host');
|
|
92
|
+
$registryToken = Setting::getByKey('registry-bridge.registry.token');
|
|
93
|
+
|
|
94
|
+
if ($registryHost) {
|
|
95
|
+
config(['registry-bridge.registry.host' => $registryHost->value]);
|
|
105
96
|
}
|
|
106
97
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
$registryString = implode(PHP_EOL, [
|
|
110
|
-
'registry=https://registry.npmjs.org/',
|
|
111
|
-
'@fleetbase:registry=' . rtrim(config('registry-bridge.registry.host'), '/') . '/',
|
|
112
|
-
]) . PHP_EOL;
|
|
113
|
-
if (!file_exists($registryPath) || $reset === true) {
|
|
114
|
-
file_put_contents($registryPath, $registryString);
|
|
98
|
+
if ($registryToken) {
|
|
99
|
+
config(['registry-bridge.registry.token' => $registryToken->value]);
|
|
115
100
|
}
|
|
116
101
|
}
|
|
117
102
|
}
|
|
@@ -2,7 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Fleetbase\RegistryBridge\Support;
|
|
4
4
|
|
|
5
|
+
use Fleetbase\Models\User;
|
|
6
|
+
use Fleetbase\RegistryBridge\Models\RegistryUser;
|
|
7
|
+
use Fleetbase\Support\Auth;
|
|
5
8
|
use Illuminate\Support\Facades\Http;
|
|
9
|
+
use Illuminate\Support\Facades\Storage;
|
|
10
|
+
use Illuminate\Support\Str;
|
|
11
|
+
use Symfony\Component\Process\Exception\ProcessFailedException;
|
|
12
|
+
use Symfony\Component\Process\Process;
|
|
6
13
|
|
|
7
14
|
class Bridge
|
|
8
15
|
{
|
|
@@ -50,4 +57,120 @@ class Bridge
|
|
|
50
57
|
{
|
|
51
58
|
return Http::withOptions($options)->post(static::createUrl($uri), $parameters);
|
|
52
59
|
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Logs in to the npm registry using the provided user and retrieves the authentication token.
|
|
63
|
+
*
|
|
64
|
+
* This method uses the npm-cli-login tool to authenticate with the npm registry using the
|
|
65
|
+
* provided user's credentials, retrieves the authentication token from the .npmrc file,
|
|
66
|
+
* and associates it with the currently authenticated user in the application. The registry
|
|
67
|
+
* token is stored in the database for the user's current session.
|
|
68
|
+
*
|
|
69
|
+
* @param User $user the fleetbase user model containing the username and email
|
|
70
|
+
* @param string $password the npm password for the user
|
|
71
|
+
*
|
|
72
|
+
* @return RegistryUser the RegistryUser model containing the registry token and associated data
|
|
73
|
+
*
|
|
74
|
+
* @throws \Exception If there is no active session, the .npmrc file is not found, the auth token is not found, or the npm login fails.
|
|
75
|
+
*/
|
|
76
|
+
public static function loginWithUser(User $user, string $password): RegistryUser
|
|
77
|
+
{
|
|
78
|
+
return static::login($user->username, $password, $user->email);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Logs in to the fleetbase registry and retrieves the authentication token.
|
|
83
|
+
*
|
|
84
|
+
* This method uses the npm-cli-login tool to authenticate with the fleetbase registry,
|
|
85
|
+
* retrieves the authentication token from the .npmrc file, and associates it with
|
|
86
|
+
* the currently authenticated user in the application. The registry token is stored
|
|
87
|
+
* in the database for the user's current session.
|
|
88
|
+
*
|
|
89
|
+
* @param string $username the npm username
|
|
90
|
+
* @param string $password the npm password
|
|
91
|
+
* @param string $email the npm email
|
|
92
|
+
*
|
|
93
|
+
* @return RegistryUser the RegistryUser model containing the registry token and associated data
|
|
94
|
+
*
|
|
95
|
+
* @throws \Exception If there is no active session, the .npmrc file is not found, the auth token is not found, or the npm login fails.
|
|
96
|
+
*/
|
|
97
|
+
public static function login(string $username, string $password, string $email): RegistryUser
|
|
98
|
+
{
|
|
99
|
+
// Session is required
|
|
100
|
+
if (session()->missing(['company', 'user'])) {
|
|
101
|
+
throw new \Exception('No active session to create registry token for.');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Get registry
|
|
105
|
+
$registry = static::createUrl();
|
|
106
|
+
|
|
107
|
+
// Set .npmrc path
|
|
108
|
+
$npmrcPath = 'tmp/.npmrc-' . session('user');
|
|
109
|
+
|
|
110
|
+
// Create .npmrc file
|
|
111
|
+
Storage::disk('local')->put($npmrcPath, '');
|
|
112
|
+
|
|
113
|
+
// Prepare command
|
|
114
|
+
$process = new Process([
|
|
115
|
+
'npm-cli-login',
|
|
116
|
+
'-u', $username,
|
|
117
|
+
'-p', $password,
|
|
118
|
+
'-e', $email,
|
|
119
|
+
'-r', $registry,
|
|
120
|
+
'-s', 'false',
|
|
121
|
+
'--config-path', storage_path('app/' . $npmrcPath),
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
// Set timeout
|
|
125
|
+
$process->setTimeout(60);
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
// Run the process
|
|
129
|
+
$process->mustRun();
|
|
130
|
+
|
|
131
|
+
// Check if .npmrc file exists
|
|
132
|
+
if (!Storage::drive('local')->exists($npmrcPath)) {
|
|
133
|
+
throw new \Exception('.npmrc file not found');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Remove protocol from registry URL for matching
|
|
137
|
+
$registryHost = preg_replace('/^https?:\/\//', '', $registry);
|
|
138
|
+
|
|
139
|
+
// Read the .npmrc file to get the auth token
|
|
140
|
+
$npmrcContent = Storage::drive('local')->get($npmrcPath);
|
|
141
|
+
$lines = explode("\n", $npmrcContent);
|
|
142
|
+
$authToken = null;
|
|
143
|
+
|
|
144
|
+
foreach ($lines as $line) {
|
|
145
|
+
$line = trim($line);
|
|
146
|
+
if (Str::contains($line, $registryHost) && Str::contains($line, '_authToken=')) {
|
|
147
|
+
$parts = explode('_authToken=', $line);
|
|
148
|
+
if (count($parts) === 2) {
|
|
149
|
+
$authToken = trim($parts[1], ' "');
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Delete .npmrc file
|
|
156
|
+
Storage::drive('local')->delete($npmrcPath);
|
|
157
|
+
|
|
158
|
+
if ($authToken) {
|
|
159
|
+
// Get current authenticated user
|
|
160
|
+
$user = Auth::getUserFromSession();
|
|
161
|
+
|
|
162
|
+
// Create or update registry user for current session
|
|
163
|
+
$registryUser = RegistryUser::updateOrCreate(
|
|
164
|
+
['company_uuid' => session('company'), 'user_uuid' => $user->uuid],
|
|
165
|
+
['registry_token' => $authToken, 'scope' => '*', 'expires_at' => now()->addYear(), 'name' => $user->public_id . ' developer token']
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
return $registryUser;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
throw new \Exception('Auth token not found in .npmrc');
|
|
172
|
+
} catch (ProcessFailedException $exception) {
|
|
173
|
+
throw new \Exception('npm login failed: ' . $exception->getMessage());
|
|
174
|
+
}
|
|
175
|
+
}
|
|
53
176
|
}
|