Open crspybits opened 3 years ago
"preferred storage location." might be the term (see https://gitter.im/solid/app-development)
"I think that "preferred storage location" is good; "where in your pod do you want app data for this app stored" if you want something more explanatory. You could also try looking in the profile for a triple like <#me> pim:storage
"You get the WebID returned from the login so you don't need to ask the user for it ... I think you should ask in the forum about the general approach - I've given you the strict spec view but others may have more flexible solutions. Look at Noel de Martin's software - he does a bunch of this kind of onbording."
MacBook-Pro-4:~ chris$ curl https://crspybits.solidcommunity.net/profile/card#me
Gives:
@prefix : <#>.
@prefix acl: <http://www.w3.org/ns/auth/acl#>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix ldp: <http://www.w3.org/ns/ldp#>.
@prefix schema: <http://schema.org/>.
@prefix solid: <http://www.w3.org/ns/solid/terms#>.
@prefix space: <http://www.w3.org/ns/pim/space#>.
@prefix pro: <./>.
@prefix inbox: </inbox/>.
@prefix crs: </>.
pro:card a foaf:PersonalProfileDocument; foaf:maker :me; foaf:primaryTopic :me.
:me
a schema:Person, foaf:Person;
acl:trustedApp
[
acl:mode acl:Append, acl:Read, acl:Write;
acl:origin <biz.spasticmuffin.neebla.demo://>
],
[
acl:mode acl:Append, acl:Read, acl:Write;
acl:origin <biz.spasticmuffin.neebla.solidsignin://>
],
[
acl:mode acl:Append, acl:Read, acl:Write;
acl:origin <biz.spasticmuffin.solid.demo://>
],
[
acl:mode acl:Append, acl:Read, acl:Write;
acl:origin <com.wm.pod-browser://>
],
[
acl:mode acl:Append, acl:Read, acl:Write;
acl:origin <https://ramen.noeldemartin.com>
];
ldp:inbox inbox:;
space:preferencesFile </settings/prefs.ttl>;
space:storage crs:;
solid:account crs:;
solid:privateTypeIndex </settings/privateTypeIndex.ttl>;
solid:publicTypeIndex </settings/publicTypeIndex.ttl>;
foaf:name "Chris".
I don't understand RDF very well yet but I believe your storage is set there. See where it says space:storage crs:;
I am very unconfident about this but I think the :;
part means: "the value of this thing is the location of this file itself".
Try running this code and see if you get your pod URL (technically IRI):
Thanks, @AJamesPhillips for this!!
For me, getIri
is the key method in your example. I don't know why, but for some reason, I'm not finding docs on that in the inrupt docs-- https://docs.inrupt.com/developer-tools/api/javascript/solid-client/ when I search for this term.
Of course, this not made easier as I'm not using Javascript. (I'm doing Swift on an iOS mobile client also Swift on a backend server). That said, it would be useful to me to know exactly what getIri
is doing and how getSolidDataset
and getThing
work. I may need to recreate these or find a Swift library that does the same.
I did find getSolidDataSet and getThing and will study those.
Also-- it looks like you are getting a webid from your user prior to the screen you show here: https://files.gitter.im/5b8fe069d73408ce4fa7007e/gLKW/image.png
I'm curious about how you got the OIDC provider. Is that something the user also enters before?
I'm reading through https://www.w3.org/TR/turtle/ and am confused about the use of semi-colon line terminators in https://github.com/SyncServerII/ServerSolidAccount/issues/4#issuecomment-913840126.
space:storage crs:;
Things that have colons are prefixes which are all defined at the top. So where it it says "@prefix crs: </>." That means whenever you see crs: below, I mean </>. And </> means the root folder of the current host. <> means the current file location.
So the full statement is :
<https://crspybits.solidcommunity.net/profile/card#me>
<http://www.w3.org/ns/pim/space#storage>
<https://crspybits.solidcommunity.net/>
In other words, your Pod root is https://crspybits.solidcommunity.net/.
Parsing the https://github.com/SyncServerII/ServerSolidAccount/issues/4#issuecomment-913840126 result with Serd
(I used https://github.com/crspybits/serd-parser, forked from https://github.com/kasei/serd-parser and updated for Swift 5.3).
//
// RDFTestingApp.swift
// RDFTesting
//
// Created by Christopher G Prince on 9/6/21.
//
import SwiftUI
import SerdParser
@main
struct RDFTestingApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear() {
testRDF_fromFile()
testRDF_fromString()
}
}
}
func testRDF_fromFile() {
// extract all foaf:name triples from a file.
guard let testTTLFile = Bundle.main.url(forResource: "test", withExtension: "ttl") else {
print("Could not get `test.ttl` URL")
return
}
let parser = SerdParser()
do {
let count = try parser.parse(file: testTTLFile.path) { (s, p, o) in
handleTriple(s: s, p: p, o: o)
}
print("\(count) triples processed")
} catch let error {
print("Error: \(error)")
}
}
func testRDF_fromString() {
// extract all foaf:name triples from a string.
guard let testTTLFile = Bundle.main.url(forResource: "test", withExtension: "ttl") else {
print("Could not get `test.ttl` URL")
return
}
guard let data = try? Data(contentsOf: testTTLFile) else {
print("Could not load data from `test.ttl` URL")
return
}
guard let rtfString = String(data: data, encoding: .utf8) else {
print("Could not load get string from data")
return
}
let parser = SerdParser()
do {
let count = try parser.parse(string: rtfString) { (s, p, o) in
handleTriple(s: s, p: p, o: o)
}
print("\(count) triples processed")
} catch let error {
print("Error: \(error)")
}
}
func handleTriple(s: RDFTerm, p: RDFTerm, o: RDFTerm) {
if case .iri("http://xmlns.com/foaf/0.1/name") = p {
print("\(s) has name \(o) .")
}
else if case .iri("http://www.w3.org/ns/pim/space#storage") = p {
print("storage: s: \(s); p: \(p): \(o)")
let object: RDFTerm = o
switch object {
case .blank(let str):
print("storage: blank: \(str)")
case .datatype(let s1, let s2):
print("storage: datatype: \(s1), \(s2)")
case .iri(let str):
print("storage: iri: \(str)")
case .language(let s1, let s2):
print("storage: language: \(s1), \(s2)")
}
}
}
}
Output:
storage: s: <#me>; p: <http://www.w3.org/ns/pim/space#storage>: </>
storage: iri: /
<#me> has name "Chris" .
37 triples processed
storage: s: <#me>; p: <http://www.w3.org/ns/pim/space#storage>: </>
storage: iri: /
<#me> has name "Chris" .
37 triples processed
Not fully sure how to interpret these results. Should it be the host
of https://crspybits.solidcommunity.net/profile/card#me
?
Let's see what happens with
MacBook-Pro-4:~ chris$ curl https://pod.inrupt.com/crspybits/profile/card#me
@prefix as: <https://www.w3.org/ns/activitystreams#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix acp: <http://www.w3.org/ns/solid/acp#> .
<https://pod.inrupt.com/crspybits/profile/card>
rdf:type ldp:RDFSource ;
rdf:type ldp:RDFSource ;
rdf:type foaf:PersonalProfileDocument ;
foaf:primaryTopic <https://pod.inrupt.com/crspybits/profile/card#me> ;
foaf:maker <https://pod.inrupt.com/crspybits/profile/card#me> .
<https://pod.inrupt.com/crspybits/profile/card#me>
<http://www.w3.org/ns/pim/space#preferencesFile> <https://pod.inrupt.com/crspybits/settings/prefs.ttl> ;
<http://www.w3.org/ns/solid/terms#account> <https://pod.inrupt.com/crspybits/> ;
<http://www.w3.org/ns/solid/terms#oidcIssuer> <https://broker.pod.inrupt.com/> ;
<http://www.w3.org/ns/solid/terms#privateTypeIndex> <https://pod.inrupt.com/crspybits/settings/privateTypeIndex.ttl> ;
rdf:type foaf:Person ;
<http://www.w3.org/ns/pim/space#storage> <https://pod.inrupt.com/crspybits/> ;
rdf:type <http://schema.org/Person> ;
foaf:name "crspybits" ;
ldp:inbox <https://pod.inrupt.com/crspybits/inbox/> ;
<http://www.w3.org/ns/solid/terms#publicTypeIndex> <https://pod.inrupt.com/crspybits/settings/publicTypeIndex.ttl> .
Running it with the same Swift code, I get:
storage: s: <https://pod.inrupt.com/crspybits/profile/card#me>; p: <http://www.w3.org/ns/pim/space#storage>: <https://pod.inrupt.com/crspybits/>
storage: iri: https://pod.inrupt.com/crspybits/
<https://pod.inrupt.com/crspybits/profile/card#me> has name "crspybits" .
15 triples processed
storage: s: <https://pod.inrupt.com/crspybits/profile/card#me>; p: <http://www.w3.org/ns/pim/space#storage>: <https://pod.inrupt.com/crspybits/>
storage: iri: https://pod.inrupt.com/crspybits/
<https://pod.inrupt.com/crspybits/profile/card#me> has name "crspybits" .
15 triples processed
This looks promising!
This is in reference to the
hostURL
field inSolidCreds
but has implications for my entire auth chain of code for Solid.The conversation here https://forum.solidproject.org/t/basic-question-about-url-to-use-when-making-a-request/4605/22
revealed that I can't just use the "host" of a URL for a WebID to get the base url to use when making HTTP requests of a Solid Pod. While this works for https://crspybits.inrupt.net/profile/card#me (i.e., the host component of the URL is https://crspybits.inrupt.net/), it does not work for https://pod.inrupt.com/crspybits/profile/card#me where the host is https://pod.inrupt.com.
There are several actions needed here:
1) In my
iOSSolid
package, it looks like I need to overtly ask the user for this base URL, in addition to asking for the issuer URL. Not sure what terminology should be used.2) In the current package, I'm not sure about the
Host
header passed in HTTP requests. I'm not sure if this should be this base URL or if it should truly be the host component.3) I need to run a test of the current package making use of a webid like https://pod.inrupt.com/crspybits/profile/card#me to make sure it works in those cases.