@fleetbase/solid-engine 0.0.3 → 0.0.5
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/ACL_SOLUTION.md +72 -0
- package/CSS_SCOPE_ISSUE.md +140 -0
- package/HOTFIX_SYNTAX_ERROR.md +100 -0
- package/LICENSE.md +651 -21
- package/MANUAL_ACL_SETUP.md +135 -0
- package/README.md +74 -27
- package/REFACTORING_SUMMARY.md +330 -0
- package/VERIFICATION_CHECKLIST.md +82 -0
- package/addon/components/modals/create-solid-folder.hbs +29 -0
- package/addon/components/modals/import-solid-resources.hbs +85 -0
- package/addon/controllers/data/content.js +17 -0
- package/addon/controllers/data/index.js +219 -0
- package/addon/controllers/home.js +84 -0
- package/addon/engine.js +1 -24
- package/addon/extension.js +26 -0
- package/addon/routes/data/content.js +11 -0
- package/addon/routes/data/index.js +17 -0
- package/addon/routes.js +2 -7
- package/addon/styles/solid-engine.css +1 -2
- package/addon/templates/account.hbs +3 -3
- package/addon/templates/application.hbs +2 -12
- package/addon/templates/data/content.hbs +48 -0
- package/addon/templates/{pods/explorer.hbs → data/index.hbs} +6 -5
- package/addon/templates/home.hbs +168 -10
- package/app/components/modals/{backup-pod.js → create-solid-folder.js} +1 -1
- package/app/components/modals/{resync-pod.js → import-solid-resources.js} +1 -1
- package/app/components/modals/{create-pod.js → setup-css-credentials.js} +1 -1
- package/composer.json +5 -11
- package/extension.json +2 -2
- package/index.js +0 -11
- package/package.json +9 -9
- package/server/migrations/2024_12_21_add_css_credentials_to_solid_identities_table.php +32 -0
- package/server/src/Client/OpenIDConnectClient.php +686 -15
- package/server/src/Client/SolidClient.php +104 -8
- package/server/src/Http/Controllers/DataController.php +261 -0
- package/server/src/Http/Controllers/OIDCController.php +42 -8
- package/server/src/Http/Controllers/SolidController.php +179 -85
- package/server/src/Models/SolidIdentity.php +13 -3
- package/server/src/Services/AclService.php +146 -0
- package/server/src/Services/PodService.php +863 -0
- package/server/src/Services/ResourceSyncService.php +336 -0
- package/server/src/Services/VehicleSyncService.php +289 -0
- package/server/src/Support/Utils.php +10 -0
- package/server/src/routes.php +25 -1
- package/addon/components/modals/backup-pod.hbs +0 -3
- package/addon/components/modals/create-pod.hbs +0 -5
- package/addon/components/modals/resync-pod.hbs +0 -3
- package/addon/controllers/pods/explorer/content.js +0 -12
- package/addon/controllers/pods/explorer.js +0 -149
- package/addon/controllers/pods/index/pod.js +0 -12
- package/addon/controllers/pods/index.js +0 -137
- package/addon/routes/pods/explorer/content.js +0 -10
- package/addon/routes/pods/explorer.js +0 -44
- package/addon/routes/pods/index/pod.js +0 -3
- package/addon/routes/pods/index.js +0 -21
- package/addon/templates/pods/explorer/content.hbs +0 -19
- package/addon/templates/pods/index/pod.hbs +0 -11
- package/addon/templates/pods/index.hbs +0 -19
- package/server/src/LegacyClient/Identity/IdentityProvider.php +0 -174
- package/server/src/LegacyClient/Identity/Profile.php +0 -18
- package/server/src/LegacyClient/OIDCClient.php +0 -350
- package/server/src/LegacyClient/Profile/WebID.php +0 -26
- package/server/src/LegacyClient/SolidClient.php +0 -271
|
@@ -7,16 +7,24 @@ use Fleetbase\Http\Requests\AdminRequest;
|
|
|
7
7
|
use Fleetbase\Models\Setting;
|
|
8
8
|
use Fleetbase\Solid\Client\SolidClient;
|
|
9
9
|
use Fleetbase\Solid\Models\SolidIdentity;
|
|
10
|
+
use Fleetbase\Solid\Services\PodService;
|
|
10
11
|
use Fleetbase\Solid\Support\Utils;
|
|
11
12
|
use Illuminate\Http\Request;
|
|
12
|
-
use Illuminate\Support\
|
|
13
|
+
use Illuminate\Support\Facades\Log;
|
|
13
14
|
|
|
14
15
|
class SolidController extends BaseController
|
|
15
16
|
{
|
|
17
|
+
protected PodService $podService;
|
|
18
|
+
|
|
19
|
+
public function __construct(PodService $podService)
|
|
20
|
+
{
|
|
21
|
+
$this->podService = $podService;
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
/**
|
|
17
25
|
* Welcome message only.
|
|
18
26
|
*/
|
|
19
|
-
public function hello()
|
|
27
|
+
public function hello(Request $request)
|
|
20
28
|
{
|
|
21
29
|
return response()->json(
|
|
22
30
|
[
|
|
@@ -30,7 +38,7 @@ class SolidController extends BaseController
|
|
|
30
38
|
{
|
|
31
39
|
$defaultConfig = config('solid.server');
|
|
32
40
|
$savedConfig = Setting::system('solid.server');
|
|
33
|
-
$config = array_merge($defaultConfig, $savedConfig);
|
|
41
|
+
$config = array_merge($defaultConfig, $savedConfig ?? []);
|
|
34
42
|
|
|
35
43
|
return response()->json($config);
|
|
36
44
|
}
|
|
@@ -55,116 +63,202 @@ class SolidController extends BaseController
|
|
|
55
63
|
|
|
56
64
|
public function authenticate(string $identifier)
|
|
57
65
|
{
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
try {
|
|
67
|
+
Log::info('[SOLID AUTH START]', ['identifier' => $identifier]);
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
}
|
|
69
|
+
$identity = SolidIdentity::where('identifier', $identifier)->first();
|
|
63
70
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
if (!$identity) {
|
|
72
|
+
throw new \Exception('Identity not found for identifier: ' . $identifier);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Log::info('[SOLID IDENTITY FOUND]', [
|
|
76
|
+
'identity_id' => $identity->id,
|
|
77
|
+
'redirect_uri' => $identity->getRedirectUri(),
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
$oidc = SolidClient::create(['identity' => $identity])->oidc->register(['saveCredentials' => true]);
|
|
81
|
+
|
|
82
|
+
Log::info('[SOLID OIDC REGISTERED]', ['client_id' => $oidc->getClientID()]);
|
|
83
|
+
|
|
84
|
+
// This will redirect to the authorization server
|
|
85
|
+
return $oidc->authenticate();
|
|
86
|
+
} catch (\Throwable $e) {
|
|
87
|
+
Log::error('[SOLID AUTH ERROR]', [
|
|
88
|
+
'error' => $e->getMessage(),
|
|
89
|
+
'trace' => $e->getTraceAsString(),
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
// Redirect back to frontend with error
|
|
93
|
+
return redirect(Utils::consoleUrl('solid-protocol', ['error' => $e->getMessage()]));
|
|
94
|
+
}
|
|
69
95
|
}
|
|
70
96
|
|
|
71
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Get authentication status and account details.
|
|
99
|
+
*/
|
|
100
|
+
public function getAuthenticationStatus(Request $request)
|
|
72
101
|
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
$solid = new SolidClient(['identity' => $identity]);
|
|
102
|
+
try {
|
|
103
|
+
$identity = SolidIdentity::current();
|
|
76
104
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
105
|
+
if (!$identity || !$identity->getAccessToken()) {
|
|
106
|
+
return response()->json([
|
|
107
|
+
'authenticated' => false,
|
|
108
|
+
'identity' => null,
|
|
109
|
+
'profile' => null,
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
80
112
|
|
|
81
|
-
|
|
82
|
-
$
|
|
83
|
-
}
|
|
113
|
+
// Get WebID and profile information
|
|
114
|
+
$profile = $this->podService->getProfileData($identity);
|
|
84
115
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
'
|
|
88
|
-
|
|
89
|
-
'
|
|
90
|
-
'
|
|
91
|
-
'
|
|
116
|
+
return response()->json([
|
|
117
|
+
'authenticated' => true,
|
|
118
|
+
'identity' => [
|
|
119
|
+
'id' => $identity->id,
|
|
120
|
+
'identifier' => $identity->identifier,
|
|
121
|
+
'created_at' => $identity->created_at,
|
|
122
|
+
'has_access_token' => (bool) $identity->getAccessToken(),
|
|
92
123
|
],
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
);
|
|
100
|
-
|
|
124
|
+
'profile' => $profile,
|
|
125
|
+
]);
|
|
126
|
+
} catch (\Throwable $e) {
|
|
127
|
+
Log::error('[SOLID AUTH STATUS ERROR]', [
|
|
128
|
+
'error' => $e->getMessage(),
|
|
129
|
+
'trace' => $e->getTraceAsString(),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
return response()->json([
|
|
133
|
+
'authenticated' => false,
|
|
134
|
+
'identity' => null,
|
|
135
|
+
'profile' => null,
|
|
136
|
+
'error' => $e->getMessage(),
|
|
137
|
+
]);
|
|
101
138
|
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Logout user by clearing identity tokens.
|
|
143
|
+
*/
|
|
144
|
+
public function logout(Request $request)
|
|
145
|
+
{
|
|
146
|
+
try {
|
|
147
|
+
$identity = SolidIdentity::current();
|
|
102
148
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
dump('IdToken: ' . $solid->identity->getIdToken());
|
|
149
|
+
if ($identity) {
|
|
150
|
+
// Clear token response
|
|
151
|
+
$identity->update(['token_response' => null]);
|
|
107
152
|
|
|
108
|
-
|
|
109
|
-
|
|
153
|
+
// Clear any cached client credentials
|
|
154
|
+
$solid = SolidClient::create(['identity' => $identity]);
|
|
155
|
+
$solid->oidc->clearClientCredentials();
|
|
156
|
+
}
|
|
110
157
|
|
|
111
|
-
|
|
112
|
-
|
|
158
|
+
return response()->json([
|
|
159
|
+
'success' => true,
|
|
160
|
+
'message' => 'Logged out successfully',
|
|
161
|
+
]);
|
|
162
|
+
} catch (\Throwable $e) {
|
|
163
|
+
Log::error('[SOLID LOGOUT ERROR]', [
|
|
164
|
+
'error' => $e->getMessage(),
|
|
165
|
+
]);
|
|
113
166
|
|
|
114
|
-
|
|
115
|
-
|
|
167
|
+
return response()->json([
|
|
168
|
+
'success' => false,
|
|
169
|
+
'error' => $e->getMessage(),
|
|
170
|
+
], 500);
|
|
116
171
|
}
|
|
117
172
|
}
|
|
118
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Get real pods from Solid server.
|
|
176
|
+
*/
|
|
119
177
|
public function getPods(Request $request)
|
|
120
178
|
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
$sort = $request->input('sort', '-created_at');
|
|
124
|
-
$id = $request->input('id');
|
|
125
|
-
$slug = $request->input('slug');
|
|
179
|
+
try {
|
|
180
|
+
$identity = SolidIdentity::current();
|
|
126
181
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
$result = Utils::searchPods($pods, 'slug', $slug);
|
|
182
|
+
if (!$identity || !$identity->getAccessToken()) {
|
|
183
|
+
return response()->json([
|
|
184
|
+
'error' => 'Not authenticated',
|
|
185
|
+
], 401);
|
|
186
|
+
}
|
|
133
187
|
|
|
134
|
-
|
|
135
|
-
|
|
188
|
+
$profile = $this->podService->getProfileData($identity);
|
|
189
|
+
$storageLocations = data_get($profile, 'parsed_profile.storage_locations', []);
|
|
136
190
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
191
|
+
$pods = [];
|
|
192
|
+
foreach ($storageLocations as $storageUrl) {
|
|
193
|
+
try {
|
|
194
|
+
$podResponse = $identity->request('get', $storageUrl);
|
|
195
|
+
if ($podResponse->successful()) {
|
|
196
|
+
$pods[] = [
|
|
197
|
+
'url' => $storageUrl,
|
|
198
|
+
'name' => $this->extractPodName($storageUrl),
|
|
199
|
+
'content' => $podResponse->body(),
|
|
200
|
+
'status' => $podResponse->status(),
|
|
201
|
+
'containers' => $this->parseContainers($podResponse->body()),
|
|
202
|
+
];
|
|
203
|
+
}
|
|
204
|
+
} catch (\Throwable $e) {
|
|
205
|
+
Log::warning('[SOLID POD FETCH ERROR]', [
|
|
206
|
+
'storage_url' => $storageUrl,
|
|
207
|
+
'error' => $e->getMessage(),
|
|
208
|
+
]);
|
|
209
|
+
}
|
|
149
210
|
}
|
|
150
211
|
|
|
151
|
-
return response()->json(
|
|
152
|
-
|
|
212
|
+
return response()->json([
|
|
213
|
+
'pods' => $pods,
|
|
214
|
+
'storage_locations' => $storageLocations,
|
|
215
|
+
]);
|
|
216
|
+
} catch (\Throwable $e) {
|
|
217
|
+
Log::error('[SOLID PODS ERROR]', [
|
|
218
|
+
'error' => $e->getMessage(),
|
|
219
|
+
]);
|
|
153
220
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return Str::contains(strtolower(data_get($pod, 'name')), strtolower($query));
|
|
158
|
-
});
|
|
221
|
+
return response()->json([
|
|
222
|
+
'error' => $e->getMessage(),
|
|
223
|
+
], 500);
|
|
159
224
|
}
|
|
225
|
+
}
|
|
160
226
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Extract pod name from URL.
|
|
229
|
+
*/
|
|
230
|
+
private function extractPodName(string $url): string
|
|
231
|
+
{
|
|
232
|
+
$parts = explode('/', rtrim($url, '/'));
|
|
164
233
|
|
|
165
|
-
|
|
166
|
-
|
|
234
|
+
return end($parts) ?: 'Root Pod';
|
|
235
|
+
}
|
|
167
236
|
|
|
168
|
-
|
|
237
|
+
/**
|
|
238
|
+
* Parse containers from pod content.
|
|
239
|
+
*/
|
|
240
|
+
private function parseContainers(string $content): array
|
|
241
|
+
{
|
|
242
|
+
$containers = [];
|
|
243
|
+
|
|
244
|
+
// Parse LDP containers from RDF
|
|
245
|
+
if (preg_match_all('/<([^>]+)>\s+a\s+ldp:Container/', $content, $matches)) {
|
|
246
|
+
foreach ($matches[1] as $containerUrl) {
|
|
247
|
+
$containers[] = [
|
|
248
|
+
'url' => $containerUrl,
|
|
249
|
+
'name' => $this->extractPodName($containerUrl),
|
|
250
|
+
'type' => 'container',
|
|
251
|
+
];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return $containers;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
public function getAccountIndex()
|
|
259
|
+
{
|
|
260
|
+
$solidIdentity = SolidIdentity::current();
|
|
261
|
+
$accountResponse = $solidIdentity->request('get', '.account');
|
|
262
|
+
dd($accountResponse->json());
|
|
169
263
|
}
|
|
170
264
|
}
|
|
@@ -56,7 +56,17 @@ class SolidIdentity extends Model
|
|
|
56
56
|
|
|
57
57
|
public function getAccessToken(): ?string
|
|
58
58
|
{
|
|
59
|
-
|
|
59
|
+
// Use OIDC token only (proper Solid protocol)
|
|
60
|
+
$oidcToken = data_get($this, 'token_response.access_token');
|
|
61
|
+
|
|
62
|
+
if ($oidcToken) {
|
|
63
|
+
\Illuminate\Support\Facades\Log::info('[USING OIDC TOKEN]', ['has_token' => true]);
|
|
64
|
+
return $oidcToken;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// No token available
|
|
68
|
+
\Illuminate\Support\Facades\Log::warning('[NO ACCESS TOKEN AVAILABLE]');
|
|
69
|
+
return null;
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
public function getRedirectUri(array $query = [], int $port = 8000): string
|
|
@@ -122,9 +132,9 @@ class SolidIdentity extends Model
|
|
|
122
132
|
return $solidIdentity;
|
|
123
133
|
}
|
|
124
134
|
|
|
125
|
-
public function request(string $method, string $uri, array $data = [], array $options = [])
|
|
135
|
+
public function request(string $method, string $uri, string|array $data = [], array $options = [])
|
|
126
136
|
{
|
|
127
|
-
$solidClient = new SolidClient();
|
|
137
|
+
$solidClient = new SolidClient(['identity' => $this]);
|
|
128
138
|
|
|
129
139
|
return $solidClient->requestWithIdentity($this, $method, $uri, $data, $options);
|
|
130
140
|
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Solid\Services;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Solid\Models\SolidIdentity;
|
|
6
|
+
use Illuminate\Support\Facades\Log;
|
|
7
|
+
|
|
8
|
+
class AclService
|
|
9
|
+
{
|
|
10
|
+
protected PodService $podService;
|
|
11
|
+
|
|
12
|
+
public function __construct(PodService $podService)
|
|
13
|
+
{
|
|
14
|
+
$this->podService = $podService;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if the pod root has write/append permissions
|
|
19
|
+
*/
|
|
20
|
+
public function hasWritePermissions(SolidIdentity $identity, string $podUrl): bool
|
|
21
|
+
{
|
|
22
|
+
try {
|
|
23
|
+
$response = $identity->request('get', $podUrl);
|
|
24
|
+
|
|
25
|
+
if (!$response->successful()) {
|
|
26
|
+
Log::warning('[ACL CHECK FAILED]', [
|
|
27
|
+
'pod_url' => $podUrl,
|
|
28
|
+
'status' => $response->status(),
|
|
29
|
+
]);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
$wacAllow = $response->header('WAC-Allow');
|
|
34
|
+
Log::info('[ACL CHECK]', [
|
|
35
|
+
'pod_url' => $podUrl,
|
|
36
|
+
'wac_allow' => $wacAllow,
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
// Check if WAC-Allow header includes write or append
|
|
40
|
+
if ($wacAllow) {
|
|
41
|
+
return str_contains($wacAllow, 'write') || str_contains($wacAllow, 'append');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return false;
|
|
45
|
+
} catch (\Exception $e) {
|
|
46
|
+
Log::error('[ACL CHECK ERROR]', [
|
|
47
|
+
'pod_url' => $podUrl,
|
|
48
|
+
'error' => $e->getMessage(),
|
|
49
|
+
]);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Update the pod root ACL to grant write permissions
|
|
56
|
+
*/
|
|
57
|
+
public function grantWritePermissions(SolidIdentity $identity, string $podUrl, string $webId): bool
|
|
58
|
+
{
|
|
59
|
+
try {
|
|
60
|
+
$aclUrl = rtrim($podUrl, '/') . '/.acl';
|
|
61
|
+
|
|
62
|
+
// Generate ACL Turtle document
|
|
63
|
+
$aclTurtle = $this->generateAclDocument($podUrl, $webId);
|
|
64
|
+
|
|
65
|
+
Log::info('[ACL UPDATE]', [
|
|
66
|
+
'acl_url' => $aclUrl,
|
|
67
|
+
'webid' => $webId,
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
// PUT the ACL document
|
|
71
|
+
$response = $identity->request('put', $aclUrl, $aclTurtle, [
|
|
72
|
+
'headers' => [
|
|
73
|
+
'Content-Type' => 'text/turtle',
|
|
74
|
+
],
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
if ($response->successful()) {
|
|
78
|
+
Log::info('[ACL UPDATED]', [
|
|
79
|
+
'acl_url' => $aclUrl,
|
|
80
|
+
'status' => $response->status(),
|
|
81
|
+
]);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Log::error('[ACL UPDATE FAILED]', [
|
|
86
|
+
'acl_url' => $aclUrl,
|
|
87
|
+
'status' => $response->status(),
|
|
88
|
+
'body' => $response->body(),
|
|
89
|
+
]);
|
|
90
|
+
return false;
|
|
91
|
+
|
|
92
|
+
} catch (\Exception $e) {
|
|
93
|
+
Log::error('[ACL UPDATE ERROR]', [
|
|
94
|
+
'pod_url' => $podUrl,
|
|
95
|
+
'error' => $e->getMessage(),
|
|
96
|
+
'trace' => $e->getTraceAsString(),
|
|
97
|
+
]);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Generate ACL Turtle document
|
|
104
|
+
*/
|
|
105
|
+
protected function generateAclDocument(string $podUrl, string $webId): string
|
|
106
|
+
{
|
|
107
|
+
$podUrl = rtrim($podUrl, '/') . '/';
|
|
108
|
+
|
|
109
|
+
return <<<TURTLE
|
|
110
|
+
@prefix acl: <http://www.w3.org/ns/auth/acl#>.
|
|
111
|
+
|
|
112
|
+
# Full rights for the pod owner
|
|
113
|
+
<#owner>
|
|
114
|
+
a acl:Authorization;
|
|
115
|
+
acl:agent <{$webId}>;
|
|
116
|
+
acl:accessTo <{$podUrl}>;
|
|
117
|
+
acl:default <{$podUrl}>;
|
|
118
|
+
acl:mode acl:Read, acl:Write, acl:Control.
|
|
119
|
+
|
|
120
|
+
# Append and read rights for Fleetbase integration
|
|
121
|
+
<#fleetbase>
|
|
122
|
+
a acl:Authorization;
|
|
123
|
+
acl:agent <{$webId}>;
|
|
124
|
+
acl:accessTo <{$podUrl}>;
|
|
125
|
+
acl:default <{$podUrl}>;
|
|
126
|
+
acl:mode acl:Append, acl:Read.
|
|
127
|
+
|
|
128
|
+
TURTLE;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Ensure pod has write permissions, update ACL if needed
|
|
133
|
+
*/
|
|
134
|
+
public function ensureWritePermissions(SolidIdentity $identity, string $podUrl, string $webId): bool
|
|
135
|
+
{
|
|
136
|
+
// Check if already has write permissions
|
|
137
|
+
if ($this->hasWritePermissions($identity, $podUrl)) {
|
|
138
|
+
Log::info('[ACL OK]', ['pod_url' => $podUrl]);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Need to update ACL
|
|
143
|
+
Log::info('[ACL NEEDS UPDATE]', ['pod_url' => $podUrl]);
|
|
144
|
+
return $this->grantWritePermissions($identity, $podUrl, $webId);
|
|
145
|
+
}
|
|
146
|
+
}
|