@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
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import Controller from '@ember/controller';
|
|
2
|
-
import { action } from '@ember/object';
|
|
3
|
-
|
|
4
|
-
export default class PodsExplorerContentController extends Controller {
|
|
5
|
-
@action setOverlayContext(overlayContextApi) {
|
|
6
|
-
this.overlayContextApi = overlayContextApi;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
@action onPressClose() {
|
|
10
|
-
window.history.back();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import Controller from '@ember/controller';
|
|
2
|
-
import { action } from '@ember/object';
|
|
3
|
-
import { inject as service } from '@ember/service';
|
|
4
|
-
import { tracked } from '@glimmer/tracking';
|
|
5
|
-
import { task, timeout } from 'ember-concurrency';
|
|
6
|
-
|
|
7
|
-
export default class PodsExplorerController extends Controller {
|
|
8
|
-
@service hostRouter;
|
|
9
|
-
@service fetch;
|
|
10
|
-
@service notifications;
|
|
11
|
-
@service explorerState;
|
|
12
|
-
@service modalsManager;
|
|
13
|
-
@service crud;
|
|
14
|
-
@tracked cursor = '';
|
|
15
|
-
@tracked pod = '';
|
|
16
|
-
@tracked query = '';
|
|
17
|
-
queryParams = ['cursor', 'pod', 'query'];
|
|
18
|
-
columns = [
|
|
19
|
-
{
|
|
20
|
-
label: 'Name',
|
|
21
|
-
valuePath: 'name',
|
|
22
|
-
width: '75%',
|
|
23
|
-
cellComponent: 'table/cell/pod-content-name',
|
|
24
|
-
onClick: this.viewContents,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
label: 'Type',
|
|
28
|
-
valuePath: 'type',
|
|
29
|
-
cellClassNames: 'capitalize',
|
|
30
|
-
width: '5%',
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
label: 'Size',
|
|
34
|
-
valuePath: 'size',
|
|
35
|
-
width: '5%',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
label: 'Created At',
|
|
39
|
-
valuePath: 'created_at',
|
|
40
|
-
width: '15%',
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
label: '',
|
|
44
|
-
cellComponent: 'table/cell/pod-content-actions',
|
|
45
|
-
ddButtonText: false,
|
|
46
|
-
ddButtonIcon: 'ellipsis-h',
|
|
47
|
-
ddButtonIconPrefix: 'fas',
|
|
48
|
-
ddMenuLabel: 'Actions',
|
|
49
|
-
cellClassNames: 'overflow-visible',
|
|
50
|
-
wrapperClass: 'flex items-center justify-end mx-2',
|
|
51
|
-
width: '10%',
|
|
52
|
-
actions: (content) => {
|
|
53
|
-
return [
|
|
54
|
-
{
|
|
55
|
-
label: content.type === 'folder' ? 'Browse Folder' : 'View Contents',
|
|
56
|
-
fn: this.viewContents,
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
separator: true,
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
label: 'Delete',
|
|
63
|
-
fn: this.deleteSomething,
|
|
64
|
-
},
|
|
65
|
-
];
|
|
66
|
-
},
|
|
67
|
-
sortable: false,
|
|
68
|
-
filterable: false,
|
|
69
|
-
resizable: false,
|
|
70
|
-
searchable: false,
|
|
71
|
-
},
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
@action reload() {
|
|
75
|
-
this.hostRouter.refresh();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
@action back() {
|
|
79
|
-
if (typeof this.cursor === 'string' && this.cursor.length && this.cursor !== this.model.id) {
|
|
80
|
-
const current = this.reverseCursor();
|
|
81
|
-
return this.hostRouter.transitionTo('console.solid-protocol.pods.explorer', current, { queryParams: { cursor: this.cursor, pod: this.pod } });
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
this.hostRouter.transitionTo('console.solid-protocol.pods.index');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
@action viewContents(content) {
|
|
88
|
-
if (content.type === 'folder') {
|
|
89
|
-
return this.hostRouter.transitionTo('console.solid-protocol.pods.explorer', content, { queryParams: { cursor: this.trackCursor(content), pod: this.pod } });
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (content.type === 'file') {
|
|
93
|
-
return this.hostRouter.transitionTo('console.solid-protocol.pods.explorer.content', content);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return this.hostRouter.transitionTo('console.solid-protocol.pods.explorer', this.pod, { queryParams: { cursor: this.trackCursor(content), pod: this.pod } });
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
@action deleteSomething() {
|
|
100
|
-
this.modalsManager.confirm({
|
|
101
|
-
title: 'Are you sure you want to delete this content?',
|
|
102
|
-
body: 'Deleting this Content will remove this content from this pod. This is irreversible!',
|
|
103
|
-
acceptButtonText: 'Delete Forever',
|
|
104
|
-
confirm: () => {},
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@action deleteSelected() {
|
|
109
|
-
const selected = this.table.selectedRows;
|
|
110
|
-
|
|
111
|
-
this.crud.bulkDelete(selected, {
|
|
112
|
-
modelNamePath: 'name',
|
|
113
|
-
acceptButtonText: 'Delete All',
|
|
114
|
-
onSuccess: () => {
|
|
115
|
-
return this.hostRouter.refresh();
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
trackCursor(content) {
|
|
121
|
-
if (typeof this.cursor === 'string' && this.cursor.includes(content.id)) {
|
|
122
|
-
const segments = this.cursor.split(':');
|
|
123
|
-
const currentIndex = segments.findIndex((segment) => segment === content.id);
|
|
124
|
-
|
|
125
|
-
if (currentIndex > -1) {
|
|
126
|
-
const retainedSegments = segments.slice(0, currentIndex + 1);
|
|
127
|
-
this.cursor = retainedSegments.join(':');
|
|
128
|
-
return this.cursor;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
this.cursor = this.cursor ? `${this.cursor}:${content.id}` : content.id;
|
|
133
|
-
return this.cursor;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
reverseCursor() {
|
|
137
|
-
const segments = this.cursor.split(':');
|
|
138
|
-
segments.pop();
|
|
139
|
-
const current = segments[segments.length - 1];
|
|
140
|
-
this.cursor = segments.join(':');
|
|
141
|
-
return current;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
@task({ restartable: true }) *search(event) {
|
|
145
|
-
yield timeout(300);
|
|
146
|
-
const query = typeof event.target.value === 'string' ? event.target.value : '';
|
|
147
|
-
this.hostRouter.transitionTo('console.solid-protocol.pods.explorer', this.model.id, { queryParams: { cursor: this.cursor, query } });
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import Controller from '@ember/controller';
|
|
2
|
-
import { action } from '@ember/object';
|
|
3
|
-
|
|
4
|
-
export default class PodsIndexPodController extends Controller {
|
|
5
|
-
@action setOverlayContext(overlayContextApi) {
|
|
6
|
-
this.overlayContextApi = overlayContextApi;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
@action onPressClose() {
|
|
10
|
-
window.history.back();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import Controller from '@ember/controller';
|
|
2
|
-
import { action } from '@ember/object';
|
|
3
|
-
import { inject as service } from '@ember/service';
|
|
4
|
-
import { tracked } from '@glimmer/tracking';
|
|
5
|
-
import { task, timeout } from 'ember-concurrency';
|
|
6
|
-
|
|
7
|
-
export default class PodsIndexController extends Controller {
|
|
8
|
-
@service hostRouter;
|
|
9
|
-
@service notifications;
|
|
10
|
-
@service filters;
|
|
11
|
-
@service modalsManager;
|
|
12
|
-
@service crud;
|
|
13
|
-
@tracked query = '';
|
|
14
|
-
|
|
15
|
-
columns = [
|
|
16
|
-
{
|
|
17
|
-
label: 'Pod',
|
|
18
|
-
valuePath: 'name',
|
|
19
|
-
width: '80%',
|
|
20
|
-
cellComponent: 'table/cell/anchor',
|
|
21
|
-
onClick: this.explorePod,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
label: 'Size',
|
|
25
|
-
valuePath: 'size',
|
|
26
|
-
width: '5%',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
label: 'Created At',
|
|
30
|
-
valuePath: 'created_at',
|
|
31
|
-
width: '15%',
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
label: '',
|
|
35
|
-
cellComponent: 'table/cell/dropdown',
|
|
36
|
-
ddButtonText: false,
|
|
37
|
-
ddButtonIcon: 'ellipsis-h',
|
|
38
|
-
ddButtonIconPrefix: 'fas',
|
|
39
|
-
ddMenuLabel: 'Pod Actions',
|
|
40
|
-
cellClassNames: 'overflow-visible',
|
|
41
|
-
wrapperClass: 'flex items-center justify-end mx-2',
|
|
42
|
-
width: '10%',
|
|
43
|
-
actions: [
|
|
44
|
-
{
|
|
45
|
-
label: 'Browse',
|
|
46
|
-
fn: this.openPod,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
label: 'Backup',
|
|
50
|
-
fn: this.backupPod,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
label: 'Re-sync',
|
|
54
|
-
fn: this.resyncPod,
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
separator: true,
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
label: 'Delete',
|
|
61
|
-
fn: this.deletePod,
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
sortable: false,
|
|
65
|
-
filterable: false,
|
|
66
|
-
resizable: false,
|
|
67
|
-
searchable: false,
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
@action reload() {
|
|
72
|
-
this.hostRouter.refresh();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@action openPod(pod) {
|
|
76
|
-
this.hostRouter.transitionTo('console.solid-protocol.pods.index.pod', pod);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@action explorePod(pod) {
|
|
80
|
-
this.hostRouter.transitionTo('console.solid-protocol.pods.explorer', pod, { queryParams: { cursor: pod.id, pod: pod.id } });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
@action createPod() {
|
|
84
|
-
this.modalsManager.show('modals/create-pod', {
|
|
85
|
-
title: 'Create a new Pod',
|
|
86
|
-
acceptButtonText: 'Create Pod',
|
|
87
|
-
pod: {
|
|
88
|
-
name: null,
|
|
89
|
-
},
|
|
90
|
-
confirm: () => {},
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@action backupPod() {
|
|
95
|
-
this.modalsManager.confirm({
|
|
96
|
-
title: 'Are you sure you want to create a backup?',
|
|
97
|
-
body: 'Running a backup will create a duplicate Pod with the same contents.',
|
|
98
|
-
acceptButtonText: 'Start Backup',
|
|
99
|
-
confirm: () => {},
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
@action resyncPod() {
|
|
104
|
-
this.modalsManager.confirm({
|
|
105
|
-
title: 'Are you sure you want to re-sync?',
|
|
106
|
-
body: 'Running a re-sync will update all data from Fleetbase to this pod, overwriting the current contents with the latest.',
|
|
107
|
-
acceptButtonText: 'Start Sync',
|
|
108
|
-
confirm: () => {},
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
@action deletePod() {
|
|
113
|
-
this.modalsManager.confirm({
|
|
114
|
-
title: 'Are you sure you want to delete this Pod?',
|
|
115
|
-
body: "Deleting this Pod will destroy this pod and all it's contents. This is irreversible!",
|
|
116
|
-
acceptButtonText: 'Delete Forever',
|
|
117
|
-
confirm: () => {},
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
@action deleteSelectedPods() {
|
|
122
|
-
const selected = this.table.selectedRows;
|
|
123
|
-
|
|
124
|
-
this.crud.bulkDelete(selected, {
|
|
125
|
-
modelNamePath: 'name',
|
|
126
|
-
acceptButtonText: 'Delete All',
|
|
127
|
-
onSuccess: () => {
|
|
128
|
-
return this.hostRouter.refresh();
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
@task({ restartable: true }) *search(event) {
|
|
134
|
-
yield timeout(300);
|
|
135
|
-
this.query = typeof event.target.value === 'string' ? event.target.value : '';
|
|
136
|
-
}
|
|
137
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import Route from '@ember/routing/route';
|
|
2
|
-
import { inject as service } from '@ember/service';
|
|
3
|
-
|
|
4
|
-
export default class PodsExplorerContentRoute extends Route {
|
|
5
|
-
@service fetch;
|
|
6
|
-
|
|
7
|
-
model({ slug }) {
|
|
8
|
-
return this.fetch.get('pods', { slug }, { namespace: 'solid/int/v1' });
|
|
9
|
-
}
|
|
10
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import Route from '@ember/routing/route';
|
|
2
|
-
import { inject as service } from '@ember/service';
|
|
3
|
-
import { action } from '@ember/object';
|
|
4
|
-
|
|
5
|
-
export default class PodsExplorerRoute extends Route {
|
|
6
|
-
@service fetch;
|
|
7
|
-
@service explorerState;
|
|
8
|
-
|
|
9
|
-
queryParmas = {
|
|
10
|
-
query: {
|
|
11
|
-
refreshModel: true,
|
|
12
|
-
},
|
|
13
|
-
pod: {
|
|
14
|
-
refreshModel: false,
|
|
15
|
-
},
|
|
16
|
-
cursor: {
|
|
17
|
-
refreshModel: false,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
@action willTransition(transition) {
|
|
22
|
-
const pod = transition.to.queryParams.pod;
|
|
23
|
-
const cursor = transition.to.queryParams.cursor;
|
|
24
|
-
if (pod && cursor) {
|
|
25
|
-
this.explorerState.trackWithCursor(pod, cursor);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
beforeModel(transition) {
|
|
30
|
-
const pod = transition.to.queryParams.pod;
|
|
31
|
-
const cursor = transition.to.queryParams.cursor;
|
|
32
|
-
if (pod && cursor) {
|
|
33
|
-
this.explorerState.trackWithCursor(pod, cursor);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
model({ id, query }) {
|
|
38
|
-
return this.fetch.get('pods', { id, query }, { namespace: 'solid/int/v1' });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
afterModel(model, transition) {
|
|
42
|
-
this.explorerState.track(transition.to.queryParams.pod, model);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import Route from '@ember/routing/route';
|
|
2
|
-
import { inject as service } from '@ember/service';
|
|
3
|
-
|
|
4
|
-
export default class PodsIndexRoute extends Route {
|
|
5
|
-
@service fetch;
|
|
6
|
-
@service appCache;
|
|
7
|
-
|
|
8
|
-
queryParams = {
|
|
9
|
-
query: {
|
|
10
|
-
refreshModel: true,
|
|
11
|
-
},
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
model(params) {
|
|
15
|
-
return this.fetch.get('pods', params, { namespace: 'solid/int/v1' });
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
afterModel(model) {
|
|
19
|
-
this.appCache.set('solid:pods', model);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<Overlay @isOpen={{true}} @onLoad={{this.setOverlayContext}} @position="right" @noBackdrop={{true}} @fullHeight={{true}} @width="600px" @isResizable={{true}}>
|
|
2
|
-
<Overlay::Header @title={{@model.name}} @hideStatusDot={{true}} @titleWrapperClass="leading-5">
|
|
3
|
-
<div class="flex flex-1 justify-end">
|
|
4
|
-
<Button @type="default" @icon="times" @helpText={{t "common.close"}} @onClick={{this.onPressClose}} />
|
|
5
|
-
</div>
|
|
6
|
-
</Overlay::Header>
|
|
7
|
-
|
|
8
|
-
<Overlay::Body>
|
|
9
|
-
<div class="p-4 space-y-2">
|
|
10
|
-
<div>ID: {{@model.id}}</div>
|
|
11
|
-
<div>Name: {{@model.name}}</div>
|
|
12
|
-
<div>Size: {{@model.size}}</div>
|
|
13
|
-
<div class="mt-2 rounded-md border border-gray-700 p-3 bg-gray-800">
|
|
14
|
-
<div class="font-semibold">Contents:</div>
|
|
15
|
-
<div></div>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
</Overlay::Body>
|
|
19
|
-
</Overlay>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<Overlay @isOpen={{true}} @onLoad={{this.setOverlayContext}} @position="right" @noBackdrop={{true}} @fullHeight={{true}} @width="600px" @isResizable={{true}}>
|
|
2
|
-
<Overlay::Header @title="Pod" @hideStatusDot={{true}} @titleWrapperClass="leading-5">
|
|
3
|
-
<div class="flex flex-1 justify-end">
|
|
4
|
-
<Button @type="default" @icon="times" @helpText={{t "common.close"}} @onClick={{this.onPressClose}} />
|
|
5
|
-
</div>
|
|
6
|
-
</Overlay::Header>
|
|
7
|
-
|
|
8
|
-
<Overlay::Body class="without-padding">
|
|
9
|
-
|
|
10
|
-
</Overlay::Body>
|
|
11
|
-
</Overlay>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<Layout::Section::Header @title="Pods" @searchPlaceholder="Search Pods by Keyword" @searchQuery={{this.query}} @onSearch={{perform this.search}}>
|
|
2
|
-
<Button @icon="refresh" @onClick={{this.reload}} @helpText="Refresh" class="mr-2" />
|
|
3
|
-
{{#if (safe-has this.table "selectedRows")}}
|
|
4
|
-
<DropdownButton @icon="layer-group" @text="Bulk Action" @type="magic" @size="sm" @buttonWrapperClass="mr-2" @contentClass="dropdown-menu" as |dd|>
|
|
5
|
-
<div class="next-dd-menu mt-2 mx-0">
|
|
6
|
-
<div class="px-1">
|
|
7
|
-
<a href="#" class="text-red-500 next-dd-item" {{on "click" (dropdown-fn dd this.deleteSelectedPods)}}>
|
|
8
|
-
Delete Selected Pods
|
|
9
|
-
</a>
|
|
10
|
-
</div>
|
|
11
|
-
</div>
|
|
12
|
-
</DropdownButton>
|
|
13
|
-
{{/if}}
|
|
14
|
-
<Button @icon="plus" @iconPrefix="fas" @type="primary" @text="Create new Pod" class="mr-2" @onClick={{this.createPod}} />
|
|
15
|
-
</Layout::Section::Header>
|
|
16
|
-
<Layout::Section::Body>
|
|
17
|
-
<Table @rows={{@model}} @columns={{this.columns}} @selectable={{true}} @canSelectAll={{true}} @onSetup={{fn (mut this.table)}} @tfootVerticalOffset="53" @tfootVerticalOffsetElements=".next-view-section-subheader" />
|
|
18
|
-
</Layout::Section::Body>
|
|
19
|
-
{{outlet}}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
namespace Fleetbase\Solid\LegacyClient\Identity;
|
|
4
|
-
|
|
5
|
-
use EasyRdf\Graph;
|
|
6
|
-
use Fleetbase\Solid\Client\OIDCClient;
|
|
7
|
-
use Fleetbase\Solid\Client\SolidClient;
|
|
8
|
-
use Fleetbase\Support\Utils;
|
|
9
|
-
use Jumbojett\OpenIDConnectClientException;
|
|
10
|
-
|
|
11
|
-
class IdentityProvider
|
|
12
|
-
{
|
|
13
|
-
/**
|
|
14
|
-
* The Solid client instance.
|
|
15
|
-
*/
|
|
16
|
-
private SolidClient $solidClient;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The OIDC client instance for handling OpenID Connect authentication.
|
|
20
|
-
*/
|
|
21
|
-
private OIDCClient $oidcClient;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Default MIME type for RDF data.
|
|
25
|
-
*/
|
|
26
|
-
private const DEFAULT_MIME_TYPE = 'text/turtle';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* RDF type for LDP Basic Containers.
|
|
30
|
-
*/
|
|
31
|
-
private const LDP_BASIC_CONTAINER = 'http://www.w3.org/ns/ldp#BasicContainer';
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* RDF type for LDP Resources.
|
|
35
|
-
*/
|
|
36
|
-
private const LDP_RESOURCE = 'http://www.w3.org/ns/ldp#Resource';
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* RDF property for OIDC issuer.
|
|
40
|
-
*/
|
|
41
|
-
private const OIDC_ISSUER = 'http://www.w3.org/ns/solid/terms#oidcIssuer';
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Constructs a new IdentityProvider instance.
|
|
45
|
-
*
|
|
46
|
-
* @param SolidClient $solidClient the Solid client instance
|
|
47
|
-
*/
|
|
48
|
-
public function __construct(SolidClient $solidClient)
|
|
49
|
-
{
|
|
50
|
-
$this->solidClient = $solidClient;
|
|
51
|
-
$this->oidcClient = OIDCClient::create($solidClient);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Gets the OIDC client instance.
|
|
56
|
-
*
|
|
57
|
-
* @return OIDCClient the OIDC client instance
|
|
58
|
-
*/
|
|
59
|
-
public function getOidcClient(): OIDCClient
|
|
60
|
-
{
|
|
61
|
-
if (!$this->oidcClient) {
|
|
62
|
-
return OIDCClient::create($this->solidClient);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return $this->oidcClient;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Magic method to delegate method calls to either IdentityProvider or OIDCClient.
|
|
70
|
-
*
|
|
71
|
-
* @param string $name the name of the method being called
|
|
72
|
-
* @param array $arguments the arguments passed to the method
|
|
73
|
-
*
|
|
74
|
-
* @return mixed the result of the method call
|
|
75
|
-
*/
|
|
76
|
-
public function __call(string $name, $arguments)
|
|
77
|
-
{
|
|
78
|
-
if (method_exists($this, $name)) {
|
|
79
|
-
return $this->{$name}(...$arguments);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (method_exists($this->oidcClient, $name)) {
|
|
83
|
-
return $this->oidcClient->{$name}(...$arguments);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
throw new \BadMethodCallException("Method {$name} does not exist.");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
public function registerClient(array $options = []): self
|
|
90
|
-
{
|
|
91
|
-
// Get registration options
|
|
92
|
-
$clientName = data_get($options, 'clientName', $this->oidcClient::CLIENT_NAME);
|
|
93
|
-
$requestParams = data_get($options, 'requestParams', []);
|
|
94
|
-
$requestOptions = data_get($options, 'requestOptions', []);
|
|
95
|
-
$redirectUri = data_get($options, 'redirectUri');
|
|
96
|
-
if (!$redirectUri) {
|
|
97
|
-
$requestCode = data_get($options, 'requestCode');
|
|
98
|
-
$redirectUri = Utils::apiUrl('solid/int/v1/oidc/complete-registration' . $requestCode ? '/' . $requestCode : '', [], 8000);
|
|
99
|
-
}
|
|
100
|
-
$withResponse = data_get($options, 'withResponse');
|
|
101
|
-
|
|
102
|
-
// Get OIDC Config and Registration URL
|
|
103
|
-
$oidcConfig = $this->solidClient->getOpenIdConfiguration();
|
|
104
|
-
$registrationUrl = data_get($oidcConfig, 'registration_endpoint');
|
|
105
|
-
|
|
106
|
-
// Request registration for Client which should handle authentication
|
|
107
|
-
$response = $this->solidClient->post($registrationUrl, ['client_name' => $clientName, 'redirect_uris' => [$redirectUri], ...$requestParams], ['withoutAuth' => true, ...$requestOptions]);
|
|
108
|
-
if ($response->successful()) {
|
|
109
|
-
$clientCredentials = $response->json();
|
|
110
|
-
$this->setClientCredentials($clientName, $clientCredentials);
|
|
111
|
-
if (is_callable($withResponse)) {
|
|
112
|
-
$withResponse($clientCredentials);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
throw new OpenIDConnectClientException('Error registering: Please contact the OpenID Connect provider and obtain a Client ID and Secret directly from them');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return $this;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
public function getClient(array $options = [])
|
|
122
|
-
{
|
|
123
|
-
$clientName = data_get($options, 'clientName', $this->oidcClient::CLIENT_NAME);
|
|
124
|
-
$restoredClient = $this->restoreClientCredentials($clientName);
|
|
125
|
-
if ($restoredClient === null) {
|
|
126
|
-
return $this->registerClient($options);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return $restoredClient;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Retrieves the WebID profile of a user as an RDF graph.
|
|
134
|
-
*
|
|
135
|
-
* @param string $webId the WebID of the user
|
|
136
|
-
* @param array $options additional options for the request
|
|
137
|
-
*
|
|
138
|
-
* @return Graph the user's WebID profile as an RDF graph
|
|
139
|
-
*/
|
|
140
|
-
public function getWebIdProfile(string $webId, array $options = []): Graph
|
|
141
|
-
{
|
|
142
|
-
$response = $this->solidClient->get($webId, $options);
|
|
143
|
-
$format = $response->header('Content-Type');
|
|
144
|
-
|
|
145
|
-
if ($format) {
|
|
146
|
-
// strip parameters (such as charset) if any
|
|
147
|
-
$format = explode(';', $format, 2)[0];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return new Graph($webId, $response->getContent(), $format);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Retrieves the OIDC issuer URL from a WebID profile.
|
|
155
|
-
*
|
|
156
|
-
* @param string $webId the WebID of the user
|
|
157
|
-
* @param array $options additional options for the request
|
|
158
|
-
*
|
|
159
|
-
* @return string the OIDC issuer URL
|
|
160
|
-
*
|
|
161
|
-
* @throws \Exception if the OIDC issuer cannot be found
|
|
162
|
-
*/
|
|
163
|
-
public function getOidcIssuer(string $webId, array $options = []): string
|
|
164
|
-
{
|
|
165
|
-
$graph = $this->getWebIdProfile($webId, $options);
|
|
166
|
-
$issuer = $graph->get($webId, sprintf('<%s>', self::OIDC_ISSUER))->getUri();
|
|
167
|
-
|
|
168
|
-
if (!\is_string($issuer)) {
|
|
169
|
-
throw new \Exception('Unable to find the OIDC issuer associated with this WebID', 1);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return $issuer;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
namespace Fleetbase\Solid\LegacyClient\Identity;
|
|
4
|
-
|
|
5
|
-
use EasyRdf\Graph;
|
|
6
|
-
|
|
7
|
-
class Profile
|
|
8
|
-
{
|
|
9
|
-
private Graph $graph;
|
|
10
|
-
public string $webId;
|
|
11
|
-
public string $name;
|
|
12
|
-
public string $email;
|
|
13
|
-
|
|
14
|
-
public function __construct(Graph $graph)
|
|
15
|
-
{
|
|
16
|
-
$this->graph = $graph;
|
|
17
|
-
}
|
|
18
|
-
}
|