solid-logic 1.3.13 → 1.3.14-e8adc14a

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.
Files changed (135) hide show
  1. package/.babelrc +0 -0
  2. package/.eslintrc.js +0 -0
  3. package/.github/workflows/ci.yml +39 -5
  4. package/.github/workflows/release.yml +0 -0
  5. package/LICENSE +0 -0
  6. package/README.md +0 -0
  7. package/jest.config.js +4 -1
  8. package/lib/acl/aclLogic.d.ts +32 -0
  9. package/lib/acl/aclLogic.d.ts.map +1 -0
  10. package/lib/acl/aclLogic.js +132 -0
  11. package/lib/acl/aclLogic.js.map +1 -0
  12. package/lib/authSession/authSession.d.ts +3 -0
  13. package/lib/authSession/authSession.d.ts.map +1 -0
  14. package/lib/authSession/authSession.js +8 -0
  15. package/lib/authSession/authSession.js.map +1 -0
  16. package/lib/authn/SolidAuthnLogic.d.ts +26 -5
  17. package/lib/authn/SolidAuthnLogic.d.ts.map +1 -1
  18. package/lib/authn/SolidAuthnLogic.js +167 -5
  19. package/lib/authn/SolidAuthnLogic.js.map +1 -1
  20. package/lib/authn/authUtil.d.ts +17 -0
  21. package/lib/authn/authUtil.d.ts.map +1 -0
  22. package/lib/authn/authUtil.js +88 -0
  23. package/lib/authn/authUtil.js.map +1 -0
  24. package/lib/chat/ChatLogic.d.ts +2 -2
  25. package/lib/chat/ChatLogic.d.ts.map +1 -1
  26. package/lib/chat/ChatLogic.js +2 -2
  27. package/lib/chat/ChatLogic.js.map +1 -1
  28. package/lib/chat/determineChatContainer.d.ts +0 -0
  29. package/lib/chat/determineChatContainer.d.ts.map +0 -0
  30. package/lib/chat/determineChatContainer.js +0 -0
  31. package/lib/chat/determineChatContainer.js.map +0 -0
  32. package/lib/inbox/InboxLogic.d.ts +2 -2
  33. package/lib/inbox/InboxLogic.d.ts.map +1 -1
  34. package/lib/inbox/InboxLogic.js +0 -0
  35. package/lib/inbox/InboxLogic.js.map +1 -1
  36. package/lib/index.d.ts +14 -67
  37. package/lib/index.d.ts.map +1 -1
  38. package/lib/index.js +39 -387
  39. package/lib/index.js.map +1 -1
  40. package/lib/issuer/issuerLogic.d.ts +8 -0
  41. package/lib/issuer/issuerLogic.d.ts.map +1 -0
  42. package/lib/issuer/issuerLogic.js +53 -0
  43. package/lib/issuer/issuerLogic.js.map +1 -0
  44. package/lib/logic/CustomError.d.ts +17 -0
  45. package/lib/logic/CustomError.d.ts.map +1 -0
  46. package/lib/logic/CustomError.js +73 -0
  47. package/lib/logic/CustomError.js.map +1 -0
  48. package/lib/logic/SolidLogic.d.ts +49 -0
  49. package/lib/logic/SolidLogic.d.ts.map +1 -0
  50. package/lib/logic/SolidLogic.js +317 -0
  51. package/lib/logic/SolidLogic.js.map +1 -0
  52. package/lib/logic/solidLogicSingleton.d.ts +4 -0
  53. package/lib/logic/solidLogicSingleton.d.ts.map +1 -0
  54. package/lib/logic/solidLogicSingleton.js +80 -0
  55. package/lib/logic/solidLogicSingleton.js.map +1 -0
  56. package/lib/profile/ProfileLogic.d.ts +2 -3
  57. package/lib/profile/ProfileLogic.d.ts.map +1 -1
  58. package/lib/profile/ProfileLogic.js +0 -0
  59. package/lib/profile/ProfileLogic.js.map +1 -1
  60. package/lib/typeIndex/typeIndexLogic.d.ts +22 -0
  61. package/lib/typeIndex/typeIndexLogic.d.ts.map +1 -0
  62. package/lib/typeIndex/typeIndexLogic.js +302 -0
  63. package/lib/typeIndex/typeIndexLogic.js.map +1 -0
  64. package/lib/types.d.ts +31 -0
  65. package/lib/types.d.ts.map +1 -0
  66. package/lib/{authn/index.js → types.js} +1 -1
  67. package/lib/types.js.map +1 -0
  68. package/lib/util/UtilityLogic.d.ts +2 -2
  69. package/lib/util/UtilityLogic.d.ts.map +1 -1
  70. package/lib/util/UtilityLogic.js +0 -0
  71. package/lib/util/UtilityLogic.js.map +1 -1
  72. package/lib/{debug.d.ts → util/debug.d.ts} +0 -0
  73. package/lib/util/debug.d.ts.map +1 -0
  74. package/lib/{debug.js → util/debug.js} +0 -0
  75. package/lib/util/debug.js.map +1 -0
  76. package/lib/{uri.d.ts → util/uri.d.ts} +0 -0
  77. package/lib/util/uri.d.ts.map +1 -0
  78. package/lib/{uri.js → util/uri.js} +0 -0
  79. package/lib/util/uri.js.map +1 -0
  80. package/package.json +6 -4
  81. package/renovate.json +0 -0
  82. package/src/acl/aclLogic.ts +137 -0
  83. package/src/authSession/authSession.ts +13 -0
  84. package/src/authn/SolidAuthnLogic.ts +114 -9
  85. package/src/authn/authUtil.ts +67 -0
  86. package/src/chat/ChatLogic.ts +4 -4
  87. package/src/chat/determineChatContainer.ts +0 -0
  88. package/src/inbox/InboxLogic.ts +2 -14
  89. package/src/index.ts +29 -308
  90. package/src/issuer/issuerLogic.ts +40 -0
  91. package/src/logic/CustomError.ts +25 -0
  92. package/src/logic/SolidLogic.ts +265 -0
  93. package/src/logic/solidLogicSingleton.ts +20 -0
  94. package/src/profile/ProfileLogic.ts +2 -3
  95. package/src/typeIndex/typeIndexLogic.ts +170 -0
  96. package/src/types.ts +43 -0
  97. package/src/util/UtilityLogic.ts +2 -14
  98. package/src/{debug.ts → util/debug.ts} +0 -0
  99. package/src/{uri.ts → util/uri.ts} +0 -0
  100. package/test/aclLogic.test.ts +15 -0
  101. package/test/authUtil.test.ts +23 -0
  102. package/{src/chat/integration.test.ts → test/chatLogic.test.ts} +7 -9
  103. package/test/helpers/setup.ts +13 -0
  104. package/{src/inbox/unit.test.ts → test/inboxLogic.test.ts} +5 -6
  105. package/test/logic.test.ts +28 -0
  106. package/test/solidAuthLogic.test.ts +49 -0
  107. package/test/typeIndexLogic.test.ts +26 -0
  108. package/{src/util/unit.test.ts → test/utilityLogic.test.ts} +3 -4
  109. package/tsconfig.json +0 -0
  110. package/jest.setup.ts +0 -2
  111. package/lib/authn/NoAuthnLogic.d.ts +0 -9
  112. package/lib/authn/NoAuthnLogic.d.ts.map +0 -1
  113. package/lib/authn/NoAuthnLogic.js +0 -17
  114. package/lib/authn/NoAuthnLogic.js.map +0 -1
  115. package/lib/authn/index.d.ts +0 -5
  116. package/lib/authn/index.d.ts.map +0 -1
  117. package/lib/authn/index.js.map +0 -1
  118. package/lib/chat/integration.test.d.ts +0 -2
  119. package/lib/chat/integration.test.d.ts.map +0 -1
  120. package/lib/chat/integration.test.js +0 -318
  121. package/lib/chat/integration.test.js.map +0 -1
  122. package/lib/debug.d.ts.map +0 -1
  123. package/lib/debug.js.map +0 -1
  124. package/lib/inbox/unit.test.d.ts +0 -2
  125. package/lib/inbox/unit.test.d.ts.map +0 -1
  126. package/lib/inbox/unit.test.js +0 -264
  127. package/lib/inbox/unit.test.js.map +0 -1
  128. package/lib/uri.d.ts.map +0 -1
  129. package/lib/uri.js.map +0 -1
  130. package/lib/util/unit.test.d.ts +0 -2
  131. package/lib/util/unit.test.d.ts.map +0 -1
  132. package/lib/util/unit.test.js +0 -200
  133. package/lib/util/unit.test.js.map +0 -1
  134. package/src/authn/NoAuthnLogic.ts +0 -16
  135. package/src/authn/index.ts +0 -5
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Simple Access Control
3
+ *
4
+ * This function sets up a simple default ACL for a resource, with
5
+ * RWC for the owner, and a specified access (default none) for the public.
6
+ * In all cases owner has read write control.
7
+ * Parameter lists modes allowed to public
8
+ *
9
+ * @param options
10
+ * @param options.public eg ['Read', 'Write']
11
+ *
12
+ * @returns Resolves with aclDoc uri on successful write
13
+ */
14
+
15
+ import { graph, NamedNode, Namespace, serialize } from "rdflib"
16
+ import solidNamespace from 'solid-namespace'
17
+ import * as $rdf from 'rdflib'
18
+ import { solidLogicSingleton } from "../logic/solidLogicSingleton"
19
+ import { ACL_LINK } from "../util/UtilityLogic"
20
+
21
+ export const ns = solidNamespace($rdf)
22
+
23
+ export function setACLUserPublic (
24
+ docURI: string,
25
+ me: NamedNode,
26
+ options: {
27
+ defaultForNew?: boolean,
28
+ public?: []
29
+ }
30
+ ): Promise<NamedNode> {
31
+ const aclDoc = solidLogicSingleton.store.any(
32
+ solidLogicSingleton.store.sym(docURI),
33
+ ACL_LINK
34
+ )
35
+
36
+ return Promise.resolve()
37
+ .then(() => {
38
+ if (aclDoc) {
39
+ return aclDoc as NamedNode
40
+ }
41
+
42
+ return fetchACLRel(docURI).catch(err => {
43
+ throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)
44
+ })
45
+ })
46
+ .then(aclDoc => {
47
+ const aclText = genACLText(docURI, me, aclDoc.uri, options)
48
+ if (!solidLogicSingleton.store.fetcher) {
49
+ throw new Error('Cannot PUT this, store has no fetcher')
50
+ }
51
+ return solidLogicSingleton.store.fetcher
52
+ .webOperation('PUT', aclDoc.uri, {
53
+ data: aclText,
54
+ contentType: 'text/turtle'
55
+ })
56
+ .then(result => {
57
+ if (!result.ok) {
58
+ throw new Error('Error writing ACL text: ' + result.error)
59
+ }
60
+
61
+ return aclDoc
62
+ })
63
+ })
64
+ }
65
+
66
+ /**
67
+ * @param docURI
68
+ * @returns
69
+ */
70
+ function fetchACLRel (docURI: string): Promise<NamedNode> {
71
+ const fetcher = solidLogicSingleton.store.fetcher
72
+ if (!fetcher) {
73
+ throw new Error('Cannot fetch ACL rel, store has no fetcher')
74
+ }
75
+
76
+ return fetcher.load(docURI).then(result => {
77
+ if (!result.ok) {
78
+ throw new Error('fetchACLRel: While loading:' + (result as any).error)
79
+ }
80
+
81
+ const aclDoc = solidLogicSingleton.store.any(
82
+ solidLogicSingleton.store.sym(docURI),
83
+ ACL_LINK
84
+ )
85
+
86
+ if (!aclDoc) {
87
+ throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)
88
+ }
89
+
90
+ return aclDoc as NamedNode
91
+ })
92
+ }
93
+
94
+ /**
95
+ * @param docURI
96
+ * @param me
97
+ * @param aclURI
98
+ * @param options
99
+ *
100
+ * @returns Serialized ACL
101
+ */
102
+ export function genACLText (
103
+ docURI: string,
104
+ me: NamedNode,
105
+ aclURI: string,
106
+ options: {
107
+ defaultForNew?: boolean,
108
+ public?: []
109
+ } = {}
110
+ ): string | undefined {
111
+ const optPublic = options.public || []
112
+ const g = graph()
113
+ const auth = Namespace('http://www.w3.org/ns/auth/acl#')
114
+ let a = g.sym(`${aclURI}#a1`)
115
+ const acl = g.sym(aclURI)
116
+ const doc = g.sym(docURI)
117
+ g.add(a, ns.rdf('type'), auth('Authorization'), acl)
118
+ g.add(a, auth('accessTo'), doc, acl)
119
+ if (options.defaultForNew) {
120
+ g.add(a, auth('default'), doc, acl)
121
+ }
122
+ g.add(a, auth('agent'), me, acl)
123
+ g.add(a, auth('mode'), auth('Read'), acl)
124
+ g.add(a, auth('mode'), auth('Write'), acl)
125
+ g.add(a, auth('mode'), auth('Control'), acl)
126
+
127
+ if (optPublic.length) {
128
+ a = g.sym(`${aclURI}#a2`)
129
+ g.add(a, ns.rdf('type'), auth('Authorization'), acl)
130
+ g.add(a, auth('accessTo'), doc, acl)
131
+ g.add(a, auth('agentClass'), ns.foaf('Agent'), acl)
132
+ for (let p = 0; p < optPublic.length; p++) {
133
+ g.add(a, auth('mode'), auth(optPublic[p]), acl) // Like 'Read' etc
134
+ }
135
+ }
136
+ return serialize(acl, g, aclURI)
137
+ }
@@ -0,0 +1,13 @@
1
+ import {
2
+ Session,
3
+ getClientAuthenticationWithDependencies
4
+ } from '@inrupt/solid-client-authn-browser'
5
+
6
+ export const authSession = new Session(
7
+ {
8
+ clientAuthentication: getClientAuthenticationWithDependencies({})
9
+ },
10
+ 'mySession'
11
+ )
12
+
13
+
@@ -1,18 +1,123 @@
1
- import { NamedNode, sym } from "rdflib";
2
- import { AuthnLogic } from "./index";
1
+ import { namedNode, NamedNode, sym } from "rdflib";
2
+ import { appContext, offlineTestID } from "./authUtil";
3
+ import * as debug from '../util/debug'
3
4
  import { Session } from "@inrupt/solid-client-authn-browser";
4
-
5
- /**
6
- * Implements AuthnLogic relying on solid-auth-client
7
- */
5
+ import { AuthenticationContext, AuthnLogic } from "../types";
8
6
  export class SolidAuthnLogic implements AuthnLogic {
9
- private session?: Session;
7
+ private session: Session;
10
8
 
11
9
  constructor(solidAuthSession: Session) {
12
10
  this.session = solidAuthSession;
13
11
  }
12
+
13
+ // we created authSession getter because we want to access it as authn.authSession externally
14
+ get authSession():Session { return this.session }
14
15
 
15
16
  currentUser(): NamedNode | null {
16
- return this.session?.info.webId ? sym(this.session.info.webId) : null;
17
+ const app = appContext()
18
+ if (app.viewingNoAuthPage) {
19
+ return sym(app.webId)
20
+ }
21
+ if (this.session.info.webId && this.session.info.isLoggedIn) {
22
+ return sym(this.session.info.webId)
23
+ }
24
+ return offlineTestID() // null unless testing
25
+ }
26
+
27
+ /**
28
+ * Retrieves currently logged in webId from either
29
+ * defaultTestUser or SolidAuth
30
+ * Also activates a session after login
31
+ * @param [setUserCallback] Optional callback
32
+ * @returns Resolves with webId uri, if no callback provided
33
+ */
34
+ async checkUser<T> (
35
+ setUserCallback?: (me: NamedNode | null) => T
36
+ ): Promise<NamedNode | T | null> {
37
+ // Save hash for "restorePreviousSession"
38
+ const preLoginRedirectHash = new URL(window.location.href).hash
39
+ if (preLoginRedirectHash) {
40
+ window.localStorage.setItem('preLoginRedirectHash', preLoginRedirectHash)
41
+ }
42
+ this.session.onSessionRestore((url) => {
43
+ if (document.location.toString() !== url) history.replaceState(null, '', url)
44
+ })
45
+
46
+ /**
47
+ * Handle a successful authentication redirect
48
+ */
49
+ await this.session
50
+ .handleIncomingRedirect({
51
+ restorePreviousSession: true,
52
+ url: window.location.href
53
+ })
54
+
55
+ // Check to see if a hash was stored in local storage
56
+ const postLoginRedirectHash = window.localStorage.getItem('preLoginRedirectHash')
57
+ if (postLoginRedirectHash) {
58
+ const curUrl = new URL(window.location.href)
59
+ if (curUrl.hash !== postLoginRedirectHash) {
60
+ if (history.pushState) {
61
+ // console.log('Setting window.location.has using pushState')
62
+ history.pushState(null, document.title, postLoginRedirectHash)
63
+ } else {
64
+ // console.warn('Setting window.location.has using location.hash')
65
+ location.hash = postLoginRedirectHash
66
+ }
67
+ curUrl.hash = postLoginRedirectHash
68
+ }
69
+ // See https://stackoverflow.com/questions/3870057/how-can-i-update-window-location-hash-without-jumping-the-document
70
+ // window.location.href = curUrl.toString()// @@ See https://developer.mozilla.org/en-US/docs/Web/API/Window/location
71
+ window.localStorage.setItem('preLoginRedirectHash', '')
72
+ }
73
+
74
+ // Check to see if already logged in / have the WebID
75
+ let me = offlineTestID()
76
+ if (me) {
77
+ return Promise.resolve(setUserCallback ? setUserCallback(me) : me)
78
+ }
79
+
80
+ const webId = this.webIdFromSession(this.session.info)
81
+ if (webId) {
82
+ me = this.saveUser(webId)
83
+ }
84
+
85
+ if (me) {
86
+ debug.log(`(Logged in as ${me} by authentication)`)
87
+ }
88
+
89
+ return Promise.resolve(setUserCallback ? setUserCallback(me) : me)
90
+ }
91
+
92
+ /**
93
+ * Saves `webId` in `context.me`
94
+ * @param webId
95
+ * @param context
96
+ *
97
+ * @returns Returns the WebID, after setting it
98
+ */
99
+ saveUser (
100
+ webId: NamedNode | string | null,
101
+ context?: AuthenticationContext
102
+ ): NamedNode | null {
103
+ let webIdUri: string
104
+ if (webId) {
105
+ webIdUri = (typeof webId === 'string') ? webId : webId.uri
106
+ const me = namedNode(webIdUri)
107
+ if (context) {
108
+ context.me = me
109
+ }
110
+ return me
111
+ }
112
+ return null
17
113
  }
18
- }
114
+
115
+ /**
116
+ * @returns {Promise<string|null>} Resolves with WebID URI or null
117
+ */
118
+ webIdFromSession (session?: { webId?: string, isLoggedIn: boolean }): string | null {
119
+ const webId = session?.webId && session.isLoggedIn ? session.webId : null
120
+ return webId
121
+ }
122
+
123
+ }
@@ -0,0 +1,67 @@
1
+ import { NamedNode, sym } from "rdflib"
2
+ import * as debug from '../util/debug'
3
+
4
+ /**
5
+ * find a user or app's context as set in window.SolidAppContext
6
+ * this is a const, not a function, because we have problems to jest mock it otherwise
7
+ * see: https://github.com/facebook/jest/issues/936#issuecomment-545080082 for more
8
+ * @return {any} - an appContext object
9
+ */
10
+ export const appContext = ():any => {
11
+ let { SolidAppContext }: any = window
12
+ SolidAppContext ||= {}
13
+ SolidAppContext.viewingNoAuthPage = false
14
+ if (SolidAppContext.noAuth && window.document) {
15
+ const currentPage = window.document.location.href
16
+ if (currentPage.startsWith(SolidAppContext.noAuth)) {
17
+ SolidAppContext.viewingNoAuthPage = true
18
+ const params = new URLSearchParams(window.document.location.search)
19
+ if (params) {
20
+ let viewedPage = SolidAppContext.viewedPage = params.get('uri') || null
21
+ if (viewedPage) {
22
+ viewedPage = decodeURI(viewedPage)
23
+ if (!viewedPage.startsWith(SolidAppContext.noAuth)) {
24
+ const ary = viewedPage.split(/\//)
25
+ SolidAppContext.idp = ary[0] + '//' + ary[2]
26
+ SolidAppContext.viewingNoAuthPage = false
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ return SolidAppContext
33
+ }
34
+
35
+ /**
36
+ * Returns `sym($SolidTestEnvironment.username)` if
37
+ * `$SolidTestEnvironment.username` is defined as a global
38
+ * or
39
+ * returns testID defined in the HTML page
40
+ * @returns {NamedNode|null}
41
+ */
42
+ export function offlineTestID (): NamedNode | null {
43
+ const { $SolidTestEnvironment }: any = window
44
+ if (
45
+ typeof $SolidTestEnvironment !== 'undefined' &&
46
+ $SolidTestEnvironment.username
47
+ ) {
48
+ // Test setup
49
+ debug.log('Assuming the user is ' + $SolidTestEnvironment.username)
50
+ return sym($SolidTestEnvironment.username)
51
+ }
52
+ // hack that makes SolidOS work in offline mode by adding the webId directly in html
53
+ // example usage: https://github.com/solid/mashlib/blob/29b8b53c46bf02e0e219f0bacd51b0e9951001dd/test/contact/local.html#L37
54
+ if (
55
+ typeof document !== 'undefined' &&
56
+ document.location &&
57
+ ('' + document.location).slice(0, 16) === 'http://localhost'
58
+ ) {
59
+ const div = document.getElementById('appTarget')
60
+ if (!div) return null
61
+ const id = div.getAttribute('testID')
62
+ if (!id) return null
63
+ debug.log('Assuming user is ' + id)
64
+ return sym(id)
65
+ }
66
+ return null
67
+ }
@@ -1,7 +1,7 @@
1
- import { LiveStore, NamedNode, Node, st, term } from "rdflib";
2
- import { SolidNamespace } from "../index";
1
+ import { NamedNode, Node, st, term, LiveStore } from "rdflib";
3
2
  import { ProfileLogic } from "../profile/ProfileLogic";
4
- import { newThing } from "../uri";
3
+ import { SolidNamespace } from "../types";
4
+ import { newThing } from "../util/uri";
5
5
  import { determineChatContainer } from "./determineChatContainer";
6
6
 
7
7
  const CHAT_LOCATION_IN_CONTAINER = "index.ttl#this";
@@ -225,7 +225,7 @@ export class ChatLogic {
225
225
  }
226
226
  const inviteBody = `
227
227
  <> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;
228
- ${this.ns.rdf("seeAlso")} <${chatThing.value}> .
228
+ ${this.ns.rdf("seeAlso")} <${chatThing.value}> .
229
229
  `;
230
230
 
231
231
  const inviteResponse = await this.store.fetcher?.webOperation(
File without changes
@@ -1,19 +1,7 @@
1
- // import { v4 as uuid } from "uuid";
2
- import { LiveStore, NamedNode, Node, st, term } from "rdflib";
3
- import { SolidNamespace } from "../index";
1
+ import { NamedNode, LiveStore } from "rdflib";
4
2
  import { ProfileLogic } from "../profile/ProfileLogic";
3
+ import { SolidNamespace } from "../types";
5
4
  import { UtilityLogic } from "../util/UtilityLogic";
6
- // import { newThing } from "../uri";
7
-
8
- interface NewPaneOptions {
9
- me?: NamedNode;
10
- newInstance?: NamedNode;
11
- newBase: string;
12
- }
13
-
14
- interface CreatedPaneOptions {
15
- newInstance: NamedNode;
16
- }
17
5
 
18
6
  /**
19
7
  * Inbox-related logic