Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: app launcher #30

Merged
merged 41 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
dc86d26
WIP: app launcher
ylebre Dec 28, 2020
d15096b
close div
ylebre Dec 28, 2020
001ae1b
splitting out requirements for file/controller
ylebre Jan 11, 2021
ed65f2e
Merge remote-tracking branch 'origin/master' into app-launcher
ylebre Jan 13, 2021
c2e1c55
add quotes to they are useful as CSP
ylebre Jan 13, 2021
78be975
bugfix for origin (should be a string instead of an array)
ylebre Jan 13, 2021
287dd6c
added outline for the launcher functions
ylebre Jan 13, 2021
5fa0ab4
moving javascript files into vendor folders
ylebre Jan 17, 2021
1655905
added lcobucci/jwt ^3.3 so that it doesn't switch to 4.0.0
poef Jan 22, 2021
c32b4c6
adding solid-acl-parser
ylebre Jan 30, 2021
bfeef07
added appOrigin to poddit
poef Jan 30, 2021
94896c6
added solid-acl-parser
poef Jan 30, 2021
0af1bb0
added draft code to add a .acl file for poddit specifically, needs wo…
poef Jan 30, 2021
dd07545
multiple fixes:
ylebre Jan 30, 2021
7e88f4d
adding solid-typeindex-parser
ylebre Feb 20, 2021
ef7c04f
add type registrations
ylebre Feb 20, 2021
58af6bd
filled in addContainerPermissions
ylebre Feb 20, 2021
53dcecc
add storage url and webid
ylebre Feb 24, 2021
9fa2eaf
add origin for notepod, add empty app example
ylebre Feb 24, 2021
8af3c5f
add webid and storage url
ylebre Feb 24, 2021
9db0679
allow form submit for the requesting client
ylebre Feb 24, 2021
0b8b12a
add vcard@#fn (for inrupt generator)
ylebre Feb 24, 2021
b8d7819
fix missing slash
ylebre Feb 24, 2021
ea0a160
remove cors headers from files, will handle in webserver config instead
ylebre Feb 24, 2021
24d7a31
Merge pull request #36 from pdsinterop/app-launcher-cors
ylebre Feb 24, 2021
f43bebc
add cors headers in init script
ylebre Feb 24, 2021
5a0c1a6
added cors headers to site config
ylebre Feb 28, 2021
51f643b
adding cors config
ylebre Feb 28, 2021
9243dbd
update readme
ylebre Feb 28, 2021
6f5ff1b
Merge remote-tracking branch 'origin/docker' into app-launcher
ylebre Feb 28, 2021
b31d85b
fix optional origin
ylebre Feb 28, 2021
8f28db6
removing codercat jwk-to-pem, replaced with web-token in solid-auth
ylebre Feb 28, 2021
980667d
remove unused parameters, just return ok for now
ylebre Feb 28, 2021
25704a4
add slug to allowed headers
ylebre Feb 28, 2021
84da7c7
pass allowed/trusted clients to WAC
ylebre Mar 1, 2021
75bec3a
remove debug stuff
ylebre Mar 1, 2021
e549f67
fix variable name
ylebre Mar 1, 2021
5aadda5
get a list of allowed origins and pass that to WAC
ylebre Mar 1, 2021
0349f8c
expose headers
ylebre Mar 1, 2021
a111acb
only set policy if an origin is available
ylebre Mar 1, 2021
54cbc38
help finding the script tag
ylebre Mar 1, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions solid/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@
['name' => 'storage#handleDelete', 'url' => '/@{userId}/storage{path}', 'verb' => 'DELETE', 'requirements' => array('path' => '.+')],
['name' => 'storage#handlePatch', 'url' => '/@{userId}/storage{path}', 'verb' => 'PATCH', 'requirements' => array('path' => '.+')],
['name' => 'storage#handleHead', 'url' => '/@{userId}/storage{path}', 'verb' => 'HEAD', 'requirements' => array('path' => '.+')],

['name' => 'app#appLauncher', 'url' => '/launcher/', 'verb' => 'GET'],
]
];
16 changes: 11 additions & 5 deletions solid/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,28 @@
"description": "A WebID-OIDC Identity Provider, to allow interoperability with SolidProject.org",
"type": "project",
"license": "MIT",
"config": {
"platform": {
"php": "7.2"
}
},
"authors": [
{
"name": "Auke van Slooten"
},
{
"name": "Yvo Brevoort"
}
{
"name": "Yvo Brevoort"
}
],
"require": {
"easyrdf/easyrdf": "^0.9.1",
"pdsinterop/flysystem-rdf": "dev-master",
"pdsinterop/solid-auth": "dev-master",
"pdsinterop/solid-crud": "dev-master",
"pdsinterop/flysystem-nextcloud":"dev-master",
"laminas/laminas-diactoros": "^2.4",
"codercat/jwk-to-pem": "^1.0"
"laminas/laminas-diactoros": "^2.4",
"codercat/jwk-to-pem": "^1.0",
"lcobucci/jwt": "^3.3"
},
"require-dev": {
"phpunit/phpunit": "^5.4"
Expand Down
16 changes: 14 additions & 2 deletions solid/css/style.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
#hello {
color: red;
li.solid-app {
padding: 10px;
border: 1px solid #ccc;
margin: 5px;
}
.solid-acl {
padding: 2px 6px;
margin-right: 4px;
border: 1px solid #888;
border-radius: 2px;
display: inline-block;
}
.solid-permissions {
margin-bottom: 10px;
}
336 changes: 336 additions & 0 deletions solid/js/launcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
var launcherApi = {};
var launcher = {};

var loader = function() {
editor.data.load({});
window.removeEventListener("load", loader);
}
window.addEventListener("load", loader);

window.addEventListener("simply-content-loaded", function() {
api = {
fetcher : false,
session : false,
getFetcher : function() {
return new Promise(function(resolve, reject) {
if (!api.fetcher) {
api.fetcher = solidAuthFetcher.customAuthFetcher();
}
resolve(api.fetcher);
});
},
getSession : function() {
if (!api.session) {
api.session = solidAuthFetcher.getSession()
.then(function(session) {
if (session.loggedIn) {
return session;
} else {
return fetcher.login({
// webId: "https://nextcloud.local/index.php/apps/solid/@alice/turtle#me",
oidcIssuer: 'https://nextcloud.local',
redirect: document.location.href
});
}
});
}
return api.session;
},
login : function() {
return api.getFetcher()
.then(function(fetcher) {
return api.getSession()
.then(function() {
return fetcher;
});
});
},
url : "https://nextcloud.local/index.php/apps/solid/@alice/storage/",
get : function(path) {
return api.login()
.then(function(fetcher) {
return fetcher.fetch(api.url + path);
});
},
post : function(path, body) {
return api.login()
.then(function(fetcher) {
return fetcher.fetch(api.url + path, {
method: "POST",
body: body
});
});
},
put : function(path, body) {
return api.login()
.then(function(fetcher) {
return fetcher.fetch(api.url + path, {
method: "PUT",
body: body
});
});
},
delete : function(path) {
return api.login()
.then(function(fetcher) {
return fetcher.fetch(api.url + path, {
method: "DELETE"
});
});
},
patch : function(path, body) {
return api.login()
.then(function(fetcher) {
return fetcher.fetch(api.url + path, {
method: "PATCH",
body: body,
headers: {
"Content-type" : "application/sparql-update"
}
});
});
}
};
launcherApi = {
getApps: function() {
return new Promise(function(resolve, reject) {
var data = document.querySelector("script#apps").innerText;
data = JSON.parse(data);
resolve(data);
});
},
getPrivateTypeIndex() {
return api.get("settings/privateTypeIndex.ttl")
.then(function(response) {
if (response.status === 200) {
return response.text();
}
throw new Error("getPrivateTypeIndex failed", response.status);
})
.then(function(text) {
console.log(text);
});
},
createContainer: function(path) {
return api.get(path)
.then(function(response) {
if (response.status != 200) {
// not found, try to create it;
// Create a dummy file to make sure the container is created.
return api.put(path + ".dummy", "");
}
})
.then(function() {
return api.get(path);
});
},
createFile : function(filepath, contents) {
return api.get(filepath)
.then(function(response) {
if (response.status != 200) {
return api.put(filepath, contents);
}
})
.then(function() {
return api.get(filepath);
});
},
addPodWidePermissions : function(permissions, origin) {
},
addFilePermissions : function(filename, permissions, origin) {
return api.get(filename + ".acl") // FIXME: find the acl file from the Link header;
.then(function(response) {
if (response.status != 200) {
// generate an acl for this file;
} else {
// add permissions to the existing file;
}
})
},
addContainerPermissions : function(container, permissions, origin) {
},
registerClassWithFile : function(resourceClass, filename, public) {
},
registerClassWithContainer : function(resourceClass, container, public) {
}
};

simply.bind = false;

launcher = simply.app({
routes: {
'/#launch/:app' : function(params) {
editor.pageData.app = params.app;
editor.pageData.page = "Launch app";
},
'/' : function(params) {
launcher.actions.getApps();
editor.pageData.page = "Launcher";
editor.pageData.pageTitle = "Solid Apps - Nextcloud";
}
},
commands: {
allowAndLaunch : function(el) {
var launchUrl = el.getAttribute("data-solid-url");
var app = editor.pageData.apps.filter(function(app) {
return app.launchUrl == launchUrl;
})[0];
launcher.actions.preparePod(app);
window.open(app.launchUrl);
},
launch : function(el) {
var launchUrl = el.getAttribute("data-solid-url");
var app = editor.pageData.apps.filter(function(app) {
return app.launchUrl == launchUrl;
})[0];
window.open(app.launchUrl);
}
},
actions: {
getApps : function() {
return launcherApi.getApps()
.then(function(apps) {
editor.pageData.apps = apps;
});
},
preparePod : function(appInfo) {
appInfo.requirements.forEach(function(requirement) {
switch(requirement['type']) {
case "podWide":
// add podwide permissions as requested by this app - add the origin of the app
launcher.actions.addPodWidePermissions(requirement.permissions, appInfo.appOrigin);
break;
case "container":
// add the container
// add permissions for the container
launcher.actions.createContainer(requirement.container);
launcher.actions.addContainerPermissions(requirement.container, requirement.permissions, appInfo.appOrigin);
break;
case "file":
// add the file
// add permissions to the file
launcher.actions.createFile(requirement.filename);
launcher.actions.addFilePermissions(requirement.filename, requirement.permissions, appInfo.appOrigin);
break;
case "class":
// add the class in the correct type registry (public = true)
if (requirement.filename) {
launcher.actions.registerClassWithFile(requirement.class, requirement.filename, requirement.public);
} else if (requirement.container) {
launcher.actions.registerClassWithContainer(requirement.class, requirement.container, requirement.public);
}
break;
default:
// FIXME: unknown requirement, now what?
break;
}
});
},
createContainer : function(containerPath) {
console.log("Create container " + containerPath);
return launcherApi.createContainer(containerPath);
},
createFile : function(filePath) {
console.log("Create file " + filePath);
return launcherApi.createFile(filePath);
},
addPodWidePermissions : function(permissions, origin) {
console.log("Add pod wide permissions");
return launcherApi.addPodWidePermissions(permissions, origin);
},
addFilePermissions : function(filename, permissions, origin) {
console.log("Add file permissions");
return launcherApi.addFilePermissions(filename, permissions, origin);
},
addContainerPermissions : function(container, permissions, origin) {
console.log("Add container permissions");
return launcherApi.addContainerPermissions(container, permissions, origin);
},
registerClassWithFile : function(resourceClass, filename, public) {
console.log("Register class with file ");
return launcherApi.registerClassWithFile(resourceClass, filename, public);
},
registerClassWithContainer : function(resourceClass, container, public) {
console.log("Register class with container ");
return launcherApi.registerClassWithContainer(resourceClass, container, public);
}
}
});

function clone(ob) {
return JSON.parse(JSON.stringify(ob));
}

function updateDataSource(name) {
document.querySelectorAll('[data-simply-data="'+name+'"]').forEach(function(list) {
editor.list.applyDataSource(list, name);
list.dataBindingPaused = 0;
});
};
});

editor.transformers = {
"schemaClass" : {
render : function(data) {
this.simplyData = data;
switch (data) {
case "schema.TextDigitalDocument":
return "text files";
break;
case "http://www.w3.org/2002/01/bookmark#Bookmark":
return "bookmarks";
break;
default:
return "data";
break;
}
},
extract : function(data) {
return this.simplyData;
}
},
"registered" : {
render: function(data) {
this.simplyData = data;
if (data == 1) {
return "✓"; // checkmark
} else {
return "";
}
},
extract: function(data) {
return this.simplyData;
}
},
"grants" : {
render : function(data) {
this.simplyData = data;
switch (data) {
case "acl.Read":
return "Read";
break;
case "acl.Control":
return "Control access";
break;
case "acl.Write":
return "Add and delete";
break;
case "acl.Append":
return "Add";
break;
default:
return data;
break;
}
},
extract : function(data) {
return this.simplyData;
}
}
};

editor.addDataSource("apps", {
load : function(el, callback) {
callback(data);
}
});
Loading