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

Make sure I've got the hostURL right #4

Open
crspybits opened this issue Sep 5, 2021 · 11 comments
Open

Make sure I've got the hostURL right #4

crspybits opened this issue Sep 5, 2021 · 11 comments

Comments

@crspybits
Copy link
Member

This is in reference to the hostURL field in SolidCreds 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.

@crspybits
Copy link
Member Author

"preferred storage location." might be the term (see https://gitter.im/solid/app-development)

@crspybits
Copy link
Member Author

crspybits commented Sep 6, 2021

jeff-zucker

"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 <some_container>, and if not found, ask the user. That triple isn't guaranteed to be there but it often is. Also many apps use the publicTypeIndex.ttl to store app location data. That also isn't guaranteed to be there but often is."
(see https://gitter.im/solid/app-development)

"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."

@crspybits
Copy link
Member Author

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".

@AJamesPhillips
Copy link

AJamesPhillips commented Sep 6, 2021

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):

https://github.com/centerofci/data-curator2/blob/main/app/frontend/src/sync/user_info/solid/get_solid_username.ts#L57

@crspybits
Copy link
Member Author

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?

@crspybits
Copy link
Member Author

I'm reading through https://www.w3.org/TR/turtle/ and am confused about the use of semi-colon line terminators in #4 (comment).

@jeff-zucker
Copy link

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/.

@crspybits
Copy link
Member Author

crspybits commented Sep 7, 2021

Parsing the #4 (comment) 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?

@crspybits
Copy link
Member Author

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> .

@crspybits
Copy link
Member Author

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

@crspybits
Copy link
Member Author

This looks promising!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants