Wac and requester refactor

main
Jackson Morgan 6 months ago
parent a879b00b44
commit 453ee230f3
  1. 108
      packages/connected-solid/src/.ldo/solid.context.ts
  2. 233
      packages/connected-solid/src/.ldo/solid.schema.ts
  3. 37
      packages/connected-solid/src/.ldo/solid.shapeTypes.ts
  4. 84
      packages/connected-solid/src/.ldo/solid.typings.ts
  5. 78
      packages/connected-solid/src/.ldo/wac.context.ts
  6. 169
      packages/connected-solid/src/.ldo/wac.schema.ts
  7. 19
      packages/connected-solid/src/.ldo/wac.shapeTypes.ts
  8. 73
      packages/connected-solid/src/.ldo/wac.typings.ts
  9. 43
      packages/connected-solid/src/.shapes/solid.shex
  10. 23
      packages/connected-solid/src/.shapes/wac.shex
  11. 4
      packages/connected-solid/src/SolidConnectedPlugin.ts
  12. 18
      packages/connected-solid/src/requester/requests/createDataResource.ts
  13. 22
      packages/connected-solid/src/requester/requests/readResource.ts
  14. 2
      packages/connected-solid/src/requester/results/error/HttpErrorResult.ts
  15. 2
      packages/connected-solid/src/requester/results/success/ReadSuccess.ts
  16. 49
      packages/connected-solid/src/resources/SolidResource.ts
  17. 19
      packages/connected-solid/src/test.ts
  18. 32
      packages/connected-solid/src/util/rdfUtils.ts
  19. 81
      packages/connected-solid/src/wac/getWacRule.ts
  20. 56
      packages/connected-solid/src/wac/getWacUri.ts
  21. 15
      packages/connected-solid/src/wac/results/GetWacRuleSuccess.ts
  22. 19
      packages/connected-solid/src/wac/results/GetWacUriSuccess.ts
  23. 15
      packages/connected-solid/src/wac/results/SetWacRuleSuccess.ts
  24. 10
      packages/connected-solid/src/wac/results/WacRuleAbsent.ts
  25. 70
      packages/connected-solid/src/wac/setWacRule.ts

@ -0,0 +1,108 @@
import { LdoJsonldContext } from "@ldo/ldo";
/**
* =============================================================================
* solidContext: JSONLD Context for solid
* =============================================================================
*/
export const solidContext: LdoJsonldContext = {
type: {
"@id": "@type",
"@isCollection": true,
},
Container: {
"@id": "http://www.w3.org/ns/ldp#Container",
"@context": {
type: {
"@id": "@type",
"@isCollection": true,
},
modified: {
"@id": "http://purl.org/dc/terms/modified",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
contains: {
"@id": "http://www.w3.org/ns/ldp#contains",
"@type": "@id",
"@isCollection": true,
},
mtime: {
"@id": "http://www.w3.org/ns/posix/stat#mtime",
"@type": "http://www.w3.org/2001/XMLSchema#decimal",
},
size: {
"@id": "http://www.w3.org/ns/posix/stat#size",
"@type": "http://www.w3.org/2001/XMLSchema#integer",
},
},
},
Resource: {
"@id": "http://www.w3.org/ns/ldp#Resource",
"@context": {
type: {
"@id": "@type",
"@isCollection": true,
},
modified: {
"@id": "http://purl.org/dc/terms/modified",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
contains: {
"@id": "http://www.w3.org/ns/ldp#contains",
"@type": "@id",
"@isCollection": true,
},
mtime: {
"@id": "http://www.w3.org/ns/posix/stat#mtime",
"@type": "http://www.w3.org/2001/XMLSchema#decimal",
},
size: {
"@id": "http://www.w3.org/ns/posix/stat#size",
"@type": "http://www.w3.org/2001/XMLSchema#integer",
},
},
},
modified: {
"@id": "http://purl.org/dc/terms/modified",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
contains: {
"@id": "http://www.w3.org/ns/ldp#contains",
"@type": "@id",
"@isCollection": true,
},
Resource2: {
"@id": "http://www.w3.org/ns/iana/media-types/text/turtle#Resource",
"@context": {
type: {
"@id": "@type",
"@isCollection": true,
},
modified: {
"@id": "http://purl.org/dc/terms/modified",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
mtime: {
"@id": "http://www.w3.org/ns/posix/stat#mtime",
"@type": "http://www.w3.org/2001/XMLSchema#decimal",
},
size: {
"@id": "http://www.w3.org/ns/posix/stat#size",
"@type": "http://www.w3.org/2001/XMLSchema#integer",
},
},
},
mtime: {
"@id": "http://www.w3.org/ns/posix/stat#mtime",
"@type": "http://www.w3.org/2001/XMLSchema#decimal",
},
size: {
"@id": "http://www.w3.org/ns/posix/stat#size",
"@type": "http://www.w3.org/2001/XMLSchema#integer",
},
storage: {
"@id": "http://www.w3.org/ns/pim/space#storage",
"@type": "@id",
"@isCollection": true,
},
};

@ -0,0 +1,233 @@
import { Schema } from "shexj";
/**
* =============================================================================
* solidSchema: ShexJ Schema for solid
* =============================================================================
*/
export const solidSchema: Schema = {
type: "Schema",
shapes: [
{
id: "http://www.w3.org/ns/lddps#Container",
type: "ShapeDecl",
shapeExpr: {
type: "Shape",
expression: {
id: "http://www.w3.org/ns/lddps#ContainerShape",
type: "EachOf",
expressions: [
{
type: "TripleConstraint",
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
valueExpr: {
type: "NodeConstraint",
values: [
"http://www.w3.org/ns/ldp#Container",
"http://www.w3.org/ns/ldp#Resource",
],
},
min: 0,
max: -1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "A container on a Solid server",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://purl.org/dc/terms/modified",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#string",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "Date modified",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/ldp#contains",
valueExpr: "http://www.w3.org/ns/lddps#Resource",
min: 0,
max: -1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "Defines a Solid Resource",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/posix/stat#mtime",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#decimal",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "?",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/posix/stat#size",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#integer",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "size of this container",
},
},
],
},
],
},
extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
},
},
{
id: "http://www.w3.org/ns/lddps#Resource",
type: "ShapeDecl",
shapeExpr: {
type: "Shape",
expression: {
id: "http://www.w3.org/ns/lddps#ResourceShape",
type: "EachOf",
expressions: [
{
type: "TripleConstraint",
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
valueExpr: {
type: "NodeConstraint",
values: [
"http://www.w3.org/ns/ldp#Resource",
"http://www.w3.org/ns/iana/media-types/text/turtle#Resource",
],
},
min: 0,
max: -1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "Any resource on a Solid server",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://purl.org/dc/terms/modified",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#string",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "Date modified",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/posix/stat#mtime",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#decimal",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "?",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/posix/stat#size",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#integer",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "size of this container",
},
},
],
},
],
},
extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
},
},
{
id: "http://www.w3.org/ns/lddps#ProfileWithStorage",
type: "ShapeDecl",
shapeExpr: {
type: "Shape",
expression: {
id: "http://www.w3.org/ns/lddps#ProfileWithStorageShape",
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/pim/space#storage",
valueExpr: {
type: "NodeConstraint",
nodeKind: "iri",
},
min: 0,
max: -1,
},
extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
},
},
],
};

@ -0,0 +1,37 @@
import { ShapeType } from "@ldo/ldo";
import { solidSchema } from "./solid.schema";
import { solidContext } from "./solid.context";
import { Container, Resource, ProfileWithStorage } from "./solid.typings";
/**
* =============================================================================
* LDO ShapeTypes solid
* =============================================================================
*/
/**
* Container ShapeType
*/
export const ContainerShapeType: ShapeType<Container> = {
schema: solidSchema,
shape: "http://www.w3.org/ns/lddps#Container",
context: solidContext,
};
/**
* Resource ShapeType
*/
export const ResourceShapeType: ShapeType<Resource> = {
schema: solidSchema,
shape: "http://www.w3.org/ns/lddps#Resource",
context: solidContext,
};
/**
* ProfileWithStorage ShapeType
*/
export const ProfileWithStorageShapeType: ShapeType<ProfileWithStorage> = {
schema: solidSchema,
shape: "http://www.w3.org/ns/lddps#ProfileWithStorage",
context: solidContext,
};

@ -0,0 +1,84 @@
import { LdoJsonldContext, LdSet } from "@ldo/ldo";
/**
* =============================================================================
* Typescript Typings for solid
* =============================================================================
*/
/**
* Container Type
*/
export interface Container {
"@id"?: string;
"@context"?: LdoJsonldContext;
/**
* A container on a Solid server
*/
type?: LdSet<
| {
"@id": "Container";
}
| {
"@id": "Resource";
}
>;
/**
* Date modified
*/
modified?: string;
/**
* Defines a Solid Resource
*/
contains?: LdSet<Resource>;
/**
* ?
*/
mtime?: number;
/**
* size of this container
*/
size?: number;
}
/**
* Resource Type
*/
export interface Resource {
"@id"?: string;
"@context"?: LdoJsonldContext;
/**
* Any resource on a Solid server
*/
type?: LdSet<
| {
"@id": "Resource";
}
| {
"@id": "Resource2";
}
>;
/**
* Date modified
*/
modified?: string;
/**
* ?
*/
mtime?: number;
/**
* size of this container
*/
size?: number;
}
/**
* ProfileWithStorage Type
*/
export interface ProfileWithStorage {
"@id"?: string;
"@context"?: LdoJsonldContext;
storage?: LdSet<{
"@id": string;
}>;
}

@ -0,0 +1,78 @@
import { LdoJsonldContext } from "@ldo/ldo";
/**
* =============================================================================
* wacContext: JSONLD Context for wac
* =============================================================================
*/
export const wacContext: LdoJsonldContext = {
type: {
"@id": "@type",
},
Authorization: {
"@id": "http://www.w3.org/ns/auth/acl#Authorization",
"@context": {
type: {
"@id": "@type",
},
accessTo: {
"@id": "http://www.w3.org/ns/auth/acl#accessTo",
"@type": "@id",
},
default: {
"@id": "http://www.w3.org/ns/auth/acl#default",
"@type": "@id",
},
agent: {
"@id": "http://www.w3.org/ns/auth/acl#agent",
"@type": "@id",
"@isCollection": true,
},
agentGroup: {
"@id": "http://www.w3.org/ns/auth/acl#agentGroup",
"@type": "@id",
"@isCollection": true,
},
agentClass: {
"@id": "http://www.w3.org/ns/auth/acl#agentClass",
"@isCollection": true,
},
mode: {
"@id": "http://www.w3.org/ns/auth/acl#mode",
"@isCollection": true,
},
},
},
accessTo: {
"@id": "http://www.w3.org/ns/auth/acl#accessTo",
"@type": "@id",
},
default: {
"@id": "http://www.w3.org/ns/auth/acl#default",
"@type": "@id",
},
agent: {
"@id": "http://www.w3.org/ns/auth/acl#agent",
"@type": "@id",
"@isCollection": true,
},
agentGroup: {
"@id": "http://www.w3.org/ns/auth/acl#agentGroup",
"@type": "@id",
"@isCollection": true,
},
agentClass: {
"@id": "http://www.w3.org/ns/auth/acl#agentClass",
"@isCollection": true,
},
AuthenticatedAgent: "http://www.w3.org/ns/auth/acl#AuthenticatedAgent",
Agent: "http://xmlns.com/foaf/0.1/Agent",
mode: {
"@id": "http://www.w3.org/ns/auth/acl#mode",
"@isCollection": true,
},
Read: "http://www.w3.org/ns/auth/acl#Read",
Write: "http://www.w3.org/ns/auth/acl#Write",
Append: "http://www.w3.org/ns/auth/acl#Append",
Control: "http://www.w3.org/ns/auth/acl#Control",
};

@ -0,0 +1,169 @@
import { Schema } from "shexj";
/**
* =============================================================================
* wacSchema: ShexJ Schema for wac
* =============================================================================
*/
export const wacSchema: Schema = {
type: "Schema",
shapes: [
{
id: "http://www.w3.org/ns/auth/acls#Authorization",
type: "ShapeDecl",
shapeExpr: {
type: "Shape",
expression: {
id: "http://www.w3.org/ns/auth/acls#AuthorizationShape",
type: "EachOf",
expressions: [
{
type: "TripleConstraint",
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
valueExpr: {
type: "NodeConstraint",
values: ["http://www.w3.org/ns/auth/acl#Authorization"],
},
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "Denotes this as an acl:Authorization",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/auth/acl#accessTo",
valueExpr: {
type: "NodeConstraint",
nodeKind: "iri",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "The subject of this authorization",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/auth/acl#default",
valueExpr: {
type: "NodeConstraint",
nodeKind: "iri",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "The container subject of this authorization",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/auth/acl#agent",
valueExpr: {
type: "NodeConstraint",
nodeKind: "iri",
},
min: 0,
max: -1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value:
"An agent is a person, social entity or software identified by a URI, e.g., a WebID denotes an agent",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/auth/acl#agentGroup",
valueExpr: {
type: "NodeConstraint",
nodeKind: "iri",
},
min: 0,
max: -1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value:
"Denotes a group of agents being given the access permission",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/auth/acl#agentClass",
valueExpr: {
type: "NodeConstraint",
values: [
"http://www.w3.org/ns/auth/acl#AuthenticatedAgent",
"http://xmlns.com/foaf/0.1/Agent",
],
},
min: 0,
max: -1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value:
"An agent class is a class of persons or entities identified by a URI.",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://www.w3.org/ns/auth/acl#mode",
valueExpr: {
type: "NodeConstraint",
values: [
"http://www.w3.org/ns/auth/acl#Read",
"http://www.w3.org/ns/auth/acl#Write",
"http://www.w3.org/ns/auth/acl#Append",
"http://www.w3.org/ns/auth/acl#Control",
],
},
min: 0,
max: -1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value:
"Denotes a class of operations that the agents can perform on a resource.",
},
},
],
},
],
},
extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
},
},
],
};

@ -0,0 +1,19 @@
import { ShapeType } from "@ldo/ldo";
import { wacSchema } from "./wac.schema";
import { wacContext } from "./wac.context";
import { Authorization } from "./wac.typings";
/**
* =============================================================================
* LDO ShapeTypes wac
* =============================================================================
*/
/**
* Authorization ShapeType
*/
export const AuthorizationShapeType: ShapeType<Authorization> = {
schema: wacSchema,
shape: "http://www.w3.org/ns/auth/acls#Authorization",
context: wacContext,
};

@ -0,0 +1,73 @@
import { LdoJsonldContext, LdSet } from "@ldo/ldo";
/**
* =============================================================================
* Typescript Typings for wac
* =============================================================================
*/
/**
* Authorization Type
*/
export interface Authorization {
"@id"?: string;
"@context"?: LdoJsonldContext;
/**
* Denotes this as an acl:Authorization
*/
type: {
"@id": "Authorization";
};
/**
* The subject of this authorization
*/
accessTo?: {
"@id": string;
};
/**
* The container subject of this authorization
*/
default?: {
"@id": string;
};
/**
* An agent is a person, social entity or software identified by a URI, e.g., a WebID denotes an agent
*/
agent?: LdSet<{
"@id": string;
}>;
/**
* Denotes a group of agents being given the access permission
*/
agentGroup?: LdSet<{
"@id": string;
}>;
/**
* An agent class is a class of persons or entities identified by a URI.
*/
agentClass?: LdSet<
| {
"@id": "AuthenticatedAgent";
}
| {
"@id": "Agent";
}
>;
/**
* Denotes a class of operations that the agents can perform on a resource.
*/
mode?: LdSet<
| {
"@id": "Read";
}
| {
"@id": "Write";
}
| {
"@id": "Append";
}
| {
"@id": "Control";
}
>;
}

@ -0,0 +1,43 @@
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ldp: <http://www.w3.org/ns/ldp#>
PREFIX ldps: <http://www.w3.org/ns/lddps#>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX stat: <http://www.w3.org/ns/posix/stat#>
PREFIX tur: <http://www.w3.org/ns/iana/media-types/text/turtle#>
PREFIX pim: <http://www.w3.org/ns/pim/space#>
ldps:Container EXTRA a {
$ldps:ContainerShape (
a [ ldp:Container ldp:Resource ]*
// rdfs:comment "A container on a Solid server";
dct:modified xsd:string?
// rdfs:comment "Date modified";
ldp:contains @ldps:Resource*
// rdfs:comment "Defines a Solid Resource";
stat:mtime xsd:decimal?
// rdfs:comment "?";
stat:size xsd:integer?
// rdfs:comment "size of this container";
)
}
ldps:Resource EXTRA a {
$ldps:ResourceShape (
a [ ldp:Resource tur:Resource ]*
// rdfs:comment "Any resource on a Solid server";
dct:modified xsd:string?
// rdfs:comment "Date modified";
stat:mtime xsd:decimal?
// rdfs:comment "?";
stat:size xsd:integer?
// rdfs:comment "size of this container";
)
}
ldps:ProfileWithStorage EXTRA a {
$ldps:ProfileWithStorageShape (
pim:storage IRI *;
)
}

@ -0,0 +1,23 @@
PREFIX acl: <http://www.w3.org/ns/auth/acl#>
PREFIX acls: <http://www.w3.org/ns/auth/acls#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
acls:Authorization EXTRA a {
$acls:AuthorizationShape (
a [ acl:Authorization ]
// rdfs:comment "Denotes this as an acl:Authorization";
acl:accessTo IRI?
// rdfs:comment "The subject of this authorization";
acl:default IRI?
// rdfs:comment "The container subject of this authorization";
acl:agent IRI*
// rdfs:comment "An agent is a person, social entity or software identified by a URI, e.g., a WebID denotes an agent";
acl:agentGroup IRI*
// rdfs:comment "Denotes a group of agents being given the access permission";
acl:agentClass [ acl:AuthenticatedAgent foaf:Agent ]*
// rdfs:comment "An agent class is a class of persons or entities identified by a URI.";
acl:mode [ acl:Read acl:Write acl:Append acl:Control ]*
// rdfs:comment "Denotes a class of operations that the agents can perform on a resource.";
)
}

@ -27,12 +27,14 @@ export interface SolidConnectedPlugin
export const solidConnectedPlugin: SolidConnectedPlugin = { export const solidConnectedPlugin: SolidConnectedPlugin = {
name: "solid", name: "solid",
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore This functions when its user-facing
getResource: function ( getResource: function (
uri: SolidLeafUri | SolidContainerUri, uri: SolidLeafUri | SolidContainerUri,
context: ConnectedContext<SolidConnectedPlugin[]>, context: ConnectedContext<SolidConnectedPlugin[]>,
): SolidLeaf | SolidContainer { ): SolidLeaf | SolidContainer {
if (isSolidContainerUri(uri)) { if (isSolidContainerUri(uri)) {
return new SolidContainer(uri, context.solid); return new SolidContainer(uri, context);
} else { } else {
return new SolidLeaf(uri, context); return new SolidLeaf(uri, context);
} }

@ -206,7 +206,10 @@ export async function createDataResource(
if (overwrite) { if (overwrite) {
const deleteResult = await deleteResource(resource, options); const deleteResult = await deleteResource(resource, options);
// Return if it wasn't deleted // Return if it wasn't deleted
if (deleteResult.isError) return deleteResult; if (deleteResult.isError)
return deleteResult as
| DeleteResultError<SolidLeaf>
| DeleteResultError<SolidContainer>;
didOverwrite = deleteResult.resourceExisted; didOverwrite = deleteResult.resourceExisted;
} else { } else {
// Perform a read to check if it exists // Perform a read to check if it exists
@ -232,13 +235,20 @@ export async function createDataResource(
}); });
const httpError = HttpErrorResult.checkResponse(resource, response); const httpError = HttpErrorResult.checkResponse(resource, response);
if (httpError) return httpError; if (httpError)
return httpError as
| HttpErrorResultType<SolidContainer>
| HttpErrorResultType<SolidLeaf>;
if (options?.dataset) { if (options?.dataset) {
addResourceRdfToContainer(resource.uri, options.dataset); addResourceRdfToContainer(resource.uri, options.dataset);
} }
return new CreateSuccess(resource, didOverwrite); return new CreateSuccess(resource, didOverwrite) as
| CreateSuccess<SolidLeaf>
| CreateSuccess<SolidContainer>;
} catch (err) { } catch (err) {
return UnexpectedResourceError.fromThrown(resource, err); return UnexpectedResourceError.fromThrown(resource, err) as
| UnexpectedResourceError<SolidContainer>
| UnexpectedResourceError<SolidLeaf>;
} }
} }

@ -115,10 +115,15 @@ export async function readResource(
); );
} }
return new AbsentReadSuccess(resource, false); return new AbsentReadSuccess(resource, false) as
| AbsentReadSuccess<SolidLeaf>
| AbsentReadSuccess<SolidContainer>;
} }
const httpErrorResult = HttpErrorResult.checkResponse(resource, response); const httpErrorResult = HttpErrorResult.checkResponse(resource, response);
if (httpErrorResult) return httpErrorResult; if (httpErrorResult)
return httpErrorResult as
| HttpErrorResultType<SolidLeaf>
| HttpErrorResultType<SolidContainer>;
// Add this resource to the container // Add this resource to the container
if (options?.dataset) { if (options?.dataset) {
@ -130,7 +135,9 @@ export async function readResource(
return new NoncompliantPodError( return new NoncompliantPodError(
resource, resource,
"Resource requests must return a content-type header.", "Resource requests must return a content-type header.",
); ) as
| NoncompliantPodError<SolidContainer>
| NoncompliantPodError<SolidLeaf>;
} }
if (contentType.startsWith("text/turtle")) { if (contentType.startsWith("text/turtle")) {
@ -142,7 +149,10 @@ export async function readResource(
options.dataset, options.dataset,
resource.uri, resource.uri,
); );
if (result) return result; if (result)
return new NoncompliantPodError(resource, result.message) as
| NoncompliantPodError<SolidLeaf>
| NoncompliantPodError<SolidContainer>;
} }
if (resource.type === "container") { if (resource.type === "container") {
const result = checkHeadersForRootContainer(resource, response.headers); const result = checkHeadersForRootContainer(resource, response.headers);
@ -164,6 +174,8 @@ export async function readResource(
); );
} }
} catch (err) { } catch (err) {
return UnexpectedResourceError.fromThrown(resource, err); return UnexpectedResourceError.fromThrown(resource, err) as
| UnexpectedResourceError<SolidLeaf>
| UnexpectedResourceError<SolidContainer>;
} }
} }

@ -70,7 +70,7 @@ export abstract class HttpErrorResult<
static checkResponse<ResourceType extends Resource>( static checkResponse<ResourceType extends Resource>(
resource: ResourceType, resource: ResourceType,
response: Response, response: Response,
) { ): HttpErrorResultType<ResourceType> | undefined {
if (ServerHttpError.is(response)) { if (ServerHttpError.is(response)) {
return new ServerHttpError(resource, response); return new ServerHttpError(resource, response);
} }

@ -61,7 +61,7 @@ export class DataReadSuccess extends ReadSuccess<SolidLeaf> {
* retrieved was a container resource. * retrieved was a container resource.
*/ */
export class ContainerReadSuccess extends ReadSuccess<SolidContainer> { export class ContainerReadSuccess extends ReadSuccess<SolidContainer> {
type: "containerReadSuccess"; type = "containerReadSuccess" as const;
/** /**
* True if this container is a root container * True if this container is a root container
*/ */

@ -49,6 +49,8 @@ import { setWacRuleForAclUri } from "../wac/setWacRule";
import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError"; import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
import type { SolidNotificationMessage } from "../notifications/SolidNotificationMessage"; import type { SolidNotificationMessage } from "../notifications/SolidNotificationMessage";
import type { CreateSuccess } from "../requester/results/success/CreateSuccess"; import type { CreateSuccess } from "../requester/results/success/CreateSuccess";
import { GetWacUriSuccess } from "../wac/results/GetWacUriSuccess";
import { GetWacRuleSuccess } from "../wac/results/GetWacRuleSuccess";
/** /**
* Statuses shared between both Leaf and Container * Statuses shared between both Leaf and Container
@ -592,18 +594,14 @@ export abstract class SolidResource
*/ */
protected async getWacUri(options?: { protected async getWacUri(options?: {
ignoreCache: boolean; ignoreCache: boolean;
}): Promise<GetWacUriResult> { }): Promise<GetWacUriResult<SolidLeaf | SolidContainer>> {
const thisAsLeafOrContainer = this as unknown as SolidLeaf | SolidContainer;
// Get the wacUri if not already present // Get the wacUri if not already present
if (!options?.ignoreCache && this.wacUri) { if (!options?.ignoreCache && this.wacUri) {
return { return new GetWacUriSuccess(thisAsLeafOrContainer, this.wacUri);
type: "getWacUriSuccess",
wacUri: this.wacUri,
isError: false,
uri: this.uri,
};
} }
const wacUriResult = await getWacUri(this.uri, { const wacUriResult = await getWacUri(thisAsLeafOrContainer, {
fetch: this.context.solid.fetch, fetch: this.context.solid.fetch,
}); });
if (wacUriResult.isError) { if (wacUriResult.isError) {
@ -643,15 +641,14 @@ export abstract class SolidResource
*/ */
async getWac(options?: { async getWac(options?: {
ignoreCache: boolean; ignoreCache: boolean;
}): Promise<GetWacUriError | GetWacRuleResult> { }): Promise<
| GetWacUriError<SolidContainer | SolidLeaf>
| GetWacRuleResult<SolidContainer | SolidLeaf>
> {
const thisAsLeafOrContainer = this as unknown as SolidLeaf | SolidContainer;
// Return the wac rule if it's already cached // Return the wac rule if it's already cached
if (!options?.ignoreCache && this.wacRule) { if (!options?.ignoreCache && this.wacRule) {
return { return new GetWacRuleSuccess(thisAsLeafOrContainer, this.wacRule);
type: "getWacRuleSuccess",
uri: this.uri,
isError: false,
wacRule: this.wacRule,
};
} }
// Get the wac uri // Get the wac uri
@ -659,9 +656,13 @@ export abstract class SolidResource
if (wacUriResult.isError) return wacUriResult; if (wacUriResult.isError) return wacUriResult;
// Get the wac rule // Get the wac rule
const wacResult = await getWacRuleWithAclUri(wacUriResult.wacUri, { const wacResult = await getWacRuleWithAclUri(
fetch: this.context.solid.fetch, wacUriResult.wacUri,
}); thisAsLeafOrContainer,
{
fetch: this.context.solid.fetch,
},
);
if (wacResult.isError) return wacResult; if (wacResult.isError) return wacResult;
// If the wac rules was successfully found // If the wac rules was successfully found
if (wacResult.type === "getWacRuleSuccess") { if (wacResult.type === "getWacRuleSuccess") {
@ -674,7 +675,7 @@ export abstract class SolidResource
if (parentResource?.isError) return parentResource; if (parentResource?.isError) return parentResource;
if (!parentResource) { if (!parentResource) {
return new NoncompliantPodError( return new NoncompliantPodError(
this, thisAsLeafOrContainer,
`Resource "${this.uri}" has no Effective ACL resource`, `Resource "${this.uri}" has no Effective ACL resource`,
); );
} }
@ -714,14 +715,20 @@ export abstract class SolidResource
* }); * });
* ``` * ```
*/ */
async setWac(wacRule: WacRule): Promise<GetWacUriError | SetWacRuleResult> { async setWac(
wacRule: WacRule,
): Promise<
| GetWacUriError<SolidLeaf | SolidContainer>
| SetWacRuleResult<SolidLeaf | SolidContainer>
> {
const thisAsLeafOrContainer = this as unknown as SolidLeaf | SolidContainer;
const wacUriResult = await this.getWacUri(); const wacUriResult = await this.getWacUri();
if (wacUriResult.isError) return wacUriResult; if (wacUriResult.isError) return wacUriResult;
const result = await setWacRuleForAclUri( const result = await setWacRuleForAclUri(
wacUriResult.wacUri, wacUriResult.wacUri,
wacRule, wacRule,
this.uri, thisAsLeafOrContainer,
{ {
fetch: this.context.solid.fetch, fetch: this.context.solid.fetch,
}, },

@ -1,19 +0,0 @@
import { ConnectedLdoDataset } from "@ldo/connected";
import { solidConnectedPlugin } from "./SolidConnectedPlugin";
import { createDatasetFactory } from "@ldo/dataset";
import { createTransactionDatasetFactory } from "@ldo/subscribable-dataset";
const dataset = new ConnectedLdoDataset(
[solidConnectedPlugin],
createDatasetFactory(),
createTransactionDatasetFactory(),
);
const stringId: string = "blah";
const allResources = dataset.getResource(stringId);
const containerResource = dataset.getResource("https://example.com/container/");
const leafResource = dataset.getResource(
"https://example.com/container/index.ttl",
);
const nextGraphResource = dataset.getResource("did:ng:cool");

@ -2,10 +2,11 @@ import type { LdoDataset } from "@ldo/ldo";
import { parseRdf } from "@ldo/ldo"; import { parseRdf } from "@ldo/ldo";
import { namedNode, quad as createQuad } from "@rdfjs/data-model"; import { namedNode, quad as createQuad } from "@rdfjs/data-model";
import type { Dataset } from "@rdfjs/types"; import type { Dataset } from "@rdfjs/types";
import type { ContainerUri } from "./uriTypes"; import type { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
import { isContainerUri } from "./uriTypes"; import { ErrorResult } from "@ldo/connected";
import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError"; import { UnexpectedResourceError } from "@ldo/connected";
import { UnexpectedResourceError } from "../requester/results/error/ErrorResult"; import type { SolidContainerUri } from "../types";
import { isSolidContainerUri } from "./isSolidUri";
export const ldpContains = namedNode("http://www.w3.org/ns/ldp#contains"); export const ldpContains = namedNode("http://www.w3.org/ns/ldp#contains");
export const rdfType = namedNode( export const rdfType = namedNode(
@ -24,7 +25,7 @@ export const ldpBasicContainer = namedNode(
* @param uri - the child URI * @param uri - the child URI
* @returns A parent URI or undefined if not possible * @returns A parent URI or undefined if not possible
*/ */
export function getParentUri(uri: string): ContainerUri | undefined { export function getParentUri(uri: string): SolidContainerUri | undefined {
const urlObject = new URL(uri); const urlObject = new URL(uri);
const pathItems = urlObject.pathname.split("/"); const pathItems = urlObject.pathname.split("/");
if ( if (
@ -38,7 +39,7 @@ export function getParentUri(uri: string): ContainerUri | undefined {
} }
pathItems.pop(); pathItems.pop();
urlObject.pathname = `${pathItems.join("/")}/`; urlObject.pathname = `${pathItems.join("/")}/`;
return urlObject.toString() as ContainerUri; return urlObject.toString() as SolidContainerUri;
} }
/** /**
@ -93,7 +94,7 @@ export function addResourceRdfToContainer(
const resourceNode = namedNode(resourceUri); const resourceNode = namedNode(resourceUri);
dataset.add(createQuad(parentNode, ldpContains, resourceNode, parentNode)); dataset.add(createQuad(parentNode, ldpContains, resourceNode, parentNode));
dataset.add(createQuad(resourceNode, rdfType, ldpResource, parentNode)); dataset.add(createQuad(resourceNode, rdfType, ldpResource, parentNode));
if (isContainerUri(resourceUri)) { if (isSolidContainerUri(resourceUri)) {
dataset.add( dataset.add(
createQuad(resourceNode, rdfType, ldpBasicContainer, parentNode), createQuad(resourceNode, rdfType, ldpBasicContainer, parentNode),
); );
@ -115,10 +116,10 @@ export async function addRawTurtleToDataset(
rawTurtle: string, rawTurtle: string,
dataset: Dataset, dataset: Dataset,
baseUri: string, baseUri: string,
): Promise<undefined | NoncompliantPodError> { ): Promise<undefined | Error> {
const rawTurtleResult = await rawTurtleToDataset(rawTurtle, baseUri); const rawTurtleResult = await rawTurtleToDataset(rawTurtle, baseUri);
if (rawTurtleResult.isError) return rawTurtleResult; if (rawTurtleResult instanceof Error) return rawTurtleResult;
const loadedDataset = rawTurtleResult.dataset; const loadedDataset = rawTurtleResult;
const graphNode = namedNode(baseUri); const graphNode = namedNode(baseUri);
// Destroy all triples that were once a part of this resouce // Destroy all triples that were once a part of this resouce
dataset.deleteMatches(undefined, undefined, undefined, graphNode); dataset.deleteMatches(undefined, undefined, undefined, graphNode);
@ -133,17 +134,16 @@ export async function addRawTurtleToDataset(
export async function rawTurtleToDataset( export async function rawTurtleToDataset(
rawTurtle: string, rawTurtle: string,
baseUri: string, baseUri: string,
): Promise<{ isError: false; dataset: LdoDataset } | NoncompliantPodError> { ): Promise<LdoDataset | Error> {
try { try {
const loadedDataset = await parseRdf(rawTurtle, { const loadedDataset = await parseRdf(rawTurtle, {
baseIRI: baseUri, baseIRI: baseUri,
}); });
return { isError: false, dataset: loadedDataset }; return loadedDataset;
} catch (err) { } catch (err) {
const error = UnexpectedResourceError.fromThrown(baseUri, err); const message = err instanceof Error ? err.message : "";
return new NoncompliantPodError( return new Error(
baseUri, `Request returned noncompliant turtle: ${message}\n${rawTurtle}`,
`Request returned noncompliant turtle: ${error.message}\n${rawTurtle}`,
); );
} }
} }

@ -1,24 +1,29 @@
import type { GetWacRuleSuccess } from "./results/GetWacRuleSuccess"; import { GetWacRuleSuccess } from "./results/GetWacRuleSuccess";
import { guaranteeFetch } from "../../util/guaranteeFetch"; import { AuthorizationShapeType } from "../.ldo/wac.shapeTypes";
import type { BasicRequestOptions } from "../../requester/requests/requestOptions";
import type { HttpErrorResultType } from "../../requester/results/error/HttpErrorResult";
import { HttpErrorResult } from "../../requester/results/error/HttpErrorResult";
import type { NoncompliantPodError } from "../../requester/results/error/NoncompliantPodError";
import type { UnexpectedResourceError } from "../../requester/results/error/ErrorResult";
import { rawTurtleToDataset } from "../../util/rdfUtils";
import { AuthorizationShapeType } from "../../.ldo/wac.shapeTypes";
import type { AccessModeList, WacRule } from "./WacRule"; import type { AccessModeList, WacRule } from "./WacRule";
import type { Authorization } from "../../.ldo/wac.typings"; import type { Authorization } from "../.ldo/wac.typings";
import type { WacRuleAbsent } from "./results/WacRuleAbsent"; import { WacRuleAbsent } from "./results/WacRuleAbsent";
import {
HttpErrorResult,
type HttpErrorResultType,
} from "../requester/results/error/HttpErrorResult";
import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
import type { UnexpectedResourceError } from "@ldo/connected";
import type { SolidLeaf } from "../resources/SolidLeaf";
import type { SolidContainer } from "../resources/SolidContainer";
import { guaranteeFetch } from "../util/guaranteeFetch";
import type { BasicRequestOptions } from "../requester/requests/requestOptions";
import { rawTurtleToDataset } from "../util/rdfUtils";
export type GetWacRuleError = export type GetWacRuleError<ResourceType extends SolidContainer | SolidLeaf> =
| HttpErrorResultType | HttpErrorResultType<ResourceType>
| NoncompliantPodError | NoncompliantPodError<ResourceType>
| UnexpectedResourceError; | UnexpectedResourceError<ResourceType>;
export type GetWacRuleResult =
| GetWacRuleSuccess export type GetWacRuleResult<ResourceType extends SolidContainer | SolidLeaf> =
| GetWacRuleError | GetWacRuleSuccess<ResourceType>
| WacRuleAbsent; | GetWacRuleError<ResourceType>
| WacRuleAbsent<ResourceType>;
/** /**
* Given the URI of an ACL document, return the Web Access Control (WAC) rules * Given the URI of an ACL document, return the Web Access Control (WAC) rules
@ -28,26 +33,39 @@ export type GetWacRuleResult =
*/ */
export async function getWacRuleWithAclUri( export async function getWacRuleWithAclUri(
aclUri: string, aclUri: string,
resource: SolidContainer,
options?: BasicRequestOptions,
): Promise<GetWacRuleResult<SolidContainer>>;
export async function getWacRuleWithAclUri(
aclUri: string,
resource: SolidLeaf,
options?: BasicRequestOptions, options?: BasicRequestOptions,
): Promise<GetWacRuleResult> { ): Promise<GetWacRuleResult<SolidLeaf>>;
export async function getWacRuleWithAclUri(
aclUri: string,
resource: SolidLeaf | SolidContainer,
options?: BasicRequestOptions,
): Promise<GetWacRuleResult<SolidLeaf | SolidContainer>>;
export async function getWacRuleWithAclUri(
aclUri: string,
resource: SolidLeaf | SolidContainer,
options?: BasicRequestOptions,
): Promise<GetWacRuleResult<SolidLeaf | SolidContainer>> {
const fetch = guaranteeFetch(options?.fetch); const fetch = guaranteeFetch(options?.fetch);
const response = await fetch(aclUri); const response = await fetch(aclUri);
const errorResult = HttpErrorResult.checkResponse(aclUri, response); const errorResult = HttpErrorResult.checkResponse(resource, response);
if (errorResult) return errorResult; if (errorResult) return errorResult;
if (response.status === 404) { if (response.status === 404) {
return { return new WacRuleAbsent(resource);
type: "wacRuleAbsent",
uri: aclUri,
isError: false,
};
} }
// Parse Turtle // Parse Turtle
const rawTurtle = await response.text(); const rawTurtle = await response.text();
const rawTurtleResult = await rawTurtleToDataset(rawTurtle, aclUri); const rawTurtleResult = await rawTurtleToDataset(rawTurtle, aclUri);
if (rawTurtleResult.isError) return rawTurtleResult; if (rawTurtleResult instanceof Error)
const dataset = rawTurtleResult.dataset; return new NoncompliantPodError(resource, rawTurtleResult.message);
const dataset = rawTurtleResult;
const authorizations = dataset const authorizations = dataset
.usingType(AuthorizationShapeType) .usingType(AuthorizationShapeType)
.matchSubject( .matchSubject(
@ -109,10 +127,5 @@ export async function getWacRuleWithAclUri(
}); });
}); });
return { return new GetWacRuleSuccess(resource, wacRule);
type: "getWacRuleSuccess",
uri: aclUri,
isError: false,
wacRule,
};
} }

@ -1,22 +1,26 @@
import type { GetWacUriSuccess } from "./results/GetWacUriSuccess";
import type { HttpErrorResultType } from "../../requester/results/error/HttpErrorResult";
import { import {
HttpErrorResult, HttpErrorResult,
NotFoundHttpError, NotFoundHttpError,
} from "../../requester/results/error/HttpErrorResult"; } from "../requester/results/error/HttpErrorResult";
import { UnexpectedResourceError } from "../../requester/results/error/ErrorResult"; import type { HttpErrorResultType } from "../requester/results/error/HttpErrorResult";
import { guaranteeFetch } from "../../util/guaranteeFetch"; import { GetWacUriSuccess } from "./results/GetWacUriSuccess";
import type { BasicRequestOptions } from "../../requester/requests/requestOptions";
import { NoncompliantPodError } from "../../requester/results/error/NoncompliantPodError";
import { parse as parseLinkHeader } from "http-link-header"; import { parse as parseLinkHeader } from "http-link-header";
import type { LeafUri } from "../../util/uriTypes"; import { UnexpectedResourceError } from "@ldo/connected";
import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
import type { SolidContainer } from "../resources/SolidContainer";
import type { SolidLeaf } from "../resources/SolidLeaf";
import type { BasicRequestOptions } from "../requester/requests/requestOptions";
import { guaranteeFetch } from "../util/guaranteeFetch";
import type { SolidLeafUri } from "../types";
export type GetWacUriError = export type GetWacUriError<ResourceType extends SolidContainer | SolidLeaf> =
| HttpErrorResultType | HttpErrorResultType<ResourceType>
| NotFoundHttpError | NotFoundHttpError<ResourceType>
| NoncompliantPodError | NoncompliantPodError<ResourceType>
| UnexpectedResourceError; | UnexpectedResourceError<ResourceType>;
export type GetWacUriResult = GetWacUriSuccess | GetWacUriError; export type GetWacUriResult<ResourceType extends SolidContainer | SolidLeaf> =
| GetWacUriSuccess<ResourceType>
| GetWacUriError<ResourceType>;
/** /**
* Get the URI for the WAC rules of a specific resource * Get the URI for the WAC rules of a specific resource
@ -25,19 +29,19 @@ export type GetWacUriResult = GetWacUriSuccess | GetWacUriError;
* @returns GetWacUriResult * @returns GetWacUriResult
*/ */
export async function getWacUri( export async function getWacUri(
resourceUri: string, resource: SolidLeaf | SolidContainer,
options?: BasicRequestOptions, options?: BasicRequestOptions,
): Promise<GetWacUriResult> { ): Promise<GetWacUriResult<SolidLeaf | SolidContainer>> {
try { try {
const fetch = guaranteeFetch(options?.fetch); const fetch = guaranteeFetch(options?.fetch);
const response = await fetch(resourceUri, { const response = await fetch(resource.uri, {
method: "head", method: "head",
}); });
const errorResult = HttpErrorResult.checkResponse(resourceUri, response); const errorResult = HttpErrorResult.checkResponse(resource, response);
if (errorResult) return errorResult; if (errorResult) return errorResult;
if (NotFoundHttpError.is(response)) { if (NotFoundHttpError.is(response)) {
return new NotFoundHttpError( return new NotFoundHttpError(
resourceUri, resource,
response, response,
"Could not get access control rules because the resource does not exist.", "Could not get access control rules because the resource does not exist.",
); );
@ -46,7 +50,7 @@ export async function getWacUri(
const linkHeader = response.headers.get("link"); const linkHeader = response.headers.get("link");
if (!linkHeader) { if (!linkHeader) {
return new NoncompliantPodError( return new NoncompliantPodError(
resourceUri, resource,
"No link header present in request.", "No link header present in request.",
); );
} }
@ -54,17 +58,13 @@ export async function getWacUri(
const aclUris = parsedLinkHeader.get("rel", "acl"); const aclUris = parsedLinkHeader.get("rel", "acl");
if (aclUris.length !== 1) { if (aclUris.length !== 1) {
return new NoncompliantPodError( return new NoncompliantPodError(
resourceUri, resource,
`There must be one link with a rel="acl"`, `There must be one link with a rel="acl"`,
); );
} }
return {
type: "getWacUriSuccess", return new GetWacUriSuccess(resource, aclUris[0].uri as SolidLeafUri);
isError: false,
uri: resourceUri,
wacUri: aclUris[0].uri as LeafUri,
};
} catch (err: unknown) { } catch (err: unknown) {
return UnexpectedResourceError.fromThrown(resourceUri, err); return UnexpectedResourceError.fromThrown(resource, err);
} }
} }

@ -1,13 +1,22 @@
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; import { ResourceSuccess } from "@ldo/connected";
import type { WacRule } from "../WacRule"; import type { WacRule } from "../WacRule";
import type { SolidLeaf } from "../../resources/SolidLeaf";
import type { SolidContainer } from "../../resources/SolidContainer";
/** /**
* Returned when a WAC rule is successfully retrieved * Returned when a WAC rule is successfully retrieved
*/ */
export interface GetWacRuleSuccess extends ResourceSuccess { export class GetWacRuleSuccess<
type: "getWacRuleSuccess"; ResourceType extends SolidLeaf | SolidContainer,
> extends ResourceSuccess<ResourceType> {
type = "getWacRuleSuccess" as const;
/** /**
* The rule that was retrieved * The rule that was retrieved
*/ */
wacRule: WacRule; wacRule: WacRule;
constructor(resoure: ResourceType, wacRule: WacRule) {
super(resoure);
this.wacRule = wacRule;
}
} }

@ -1,13 +1,22 @@
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; import { ResourceSuccess } from "@ldo/connected";
import type { LeafUri } from "../../../util/uriTypes"; import type { SolidLeafUri } from "../../types";
import type { SolidContainer } from "../../resources/SolidContainer";
import type { SolidLeaf } from "../../resources/SolidLeaf";
/** /**
* Returned when the URI for a resources ACL document was successfully retried * Returned when the URI for a resources ACL document was successfully retried
*/ */
export interface GetWacUriSuccess extends ResourceSuccess { export class GetWacUriSuccess<
type: "getWacUriSuccess"; ResourceType extends SolidContainer | SolidLeaf,
> extends ResourceSuccess<ResourceType> {
type = "getWacUriSuccess" as const;
/** /**
* The URI of the ACL document * The URI of the ACL document
*/ */
wacUri: LeafUri; wacUri: SolidLeafUri;
constructor(resource: ResourceType, wacUri: SolidLeafUri) {
super(resource);
this.wacUri = wacUri;
}
} }

@ -1,13 +1,22 @@
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; import { ResourceSuccess } from "@ldo/connected";
import type { WacRule } from "../WacRule"; import type { WacRule } from "../WacRule";
import type { SolidContainer } from "../../resources/SolidContainer";
import type { SolidLeaf } from "../../resources/SolidLeaf";
/** /**
* Returned when rules were successfully written * Returned when rules were successfully written
*/ */
export interface SetWacRuleSuccess extends ResourceSuccess { export class SetWacRuleSuccess<
type: "setWacRuleSuccess"; ResourceType extends SolidLeaf | SolidContainer,
> extends ResourceSuccess<ResourceType> {
type = "setWacRuleSuccess" as const;
/** /**
* The written rule * The written rule
*/ */
wacRule: WacRule; wacRule: WacRule;
constructor(resource: ResourceType, wacRule: WacRule) {
super(resource);
this.wacRule = wacRule;
}
} }

@ -1,8 +1,12 @@
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; import { ResourceSuccess } from "@ldo/connected";
import type { SolidLeaf } from "../../resources/SolidLeaf";
import type { SolidContainer } from "../../resources/SolidContainer";
/** /**
* Returned if no WAC rule was returned from the server * Returned if no WAC rule was returned from the server
*/ */
export interface WacRuleAbsent extends ResourceSuccess { export class WacRuleAbsent<
type: "wacRuleAbsent"; ResourceType extends SolidLeaf | SolidContainer,
> extends ResourceSuccess<ResourceType> {
type = "wacRuleAbsent" as const;
} }

@ -1,20 +1,27 @@
import { createLdoDataset } from "@ldo/ldo"; import { createLdoDataset } from "@ldo/ldo";
import type { BasicRequestOptions } from "../../requester/requests/requestOptions"; import type { AccessModeList, WacRule } from "./WacRule";
import type { UnexpectedResourceError } from "../../requester/results/error/ErrorResult"; import { SetWacRuleSuccess } from "./results/SetWacRuleSuccess";
import type { Authorization } from "../.ldo/wac.typings";
import { AuthorizationShapeType } from "../.ldo/wac.shapeTypes";
import { v4 } from "uuid";
import { guaranteeFetch } from "../util/guaranteeFetch";
import type { SolidLeafUri } from "../types";
import type { SolidLeaf } from "../resources/SolidLeaf";
import type { SolidContainer } from "../resources/SolidContainer";
import { import {
HttpErrorResult, HttpErrorResult,
type HttpErrorResultType, type HttpErrorResultType,
} from "../../requester/results/error/HttpErrorResult"; } from "../requester/results/error/HttpErrorResult";
import { isContainerUri, type LeafUri } from "../../util/uriTypes"; import type { UnexpectedResourceError } from "@ldo/connected";
import type { AccessModeList, WacRule } from "./WacRule"; import type { BasicRequestOptions } from "../requester/requests/requestOptions";
import type { SetWacRuleSuccess } from "./results/SetWacRuleSuccess"; import { isContainerUri } from "@ldo/solid";
import type { Authorization } from "../../.ldo/wac.typings";
import { AuthorizationShapeType } from "../../.ldo/wac.shapeTypes";
import { v4 } from "uuid";
import { guaranteeFetch } from "../../util/guaranteeFetch";
export type SetWacRuleError = HttpErrorResultType | UnexpectedResourceError; export type SetWacRuleError<ResourceType extends SolidContainer | SolidLeaf> =
export type SetWacRuleResult = SetWacRuleSuccess | SetWacRuleError; | HttpErrorResultType<ResourceType>
| UnexpectedResourceError<ResourceType>;
export type SetWacRuleResult<ResourceType extends SolidContainer | SolidLeaf> =
| SetWacRuleSuccess<ResourceType>
| SetWacRuleError<ResourceType>;
/** /**
* Given the URI of an ACL document and some WAC rules, set the WAC rules of * Given the URI of an ACL document and some WAC rules, set the WAC rules of
@ -26,11 +33,29 @@ export type SetWacRuleResult = SetWacRuleSuccess | SetWacRuleError;
* @returns SetWacRuleResult * @returns SetWacRuleResult
*/ */
export async function setWacRuleForAclUri( export async function setWacRuleForAclUri(
aclUri: LeafUri, aclUri: SolidLeafUri,
newRule: WacRule,
resource: SolidContainer,
options?: BasicRequestOptions,
): Promise<SetWacRuleResult<SolidContainer>>;
export async function setWacRuleForAclUri(
aclUri: SolidLeafUri,
newRule: WacRule,
resource: SolidLeaf,
options?: BasicRequestOptions,
): Promise<SetWacRuleResult<SolidLeaf>>;
export async function setWacRuleForAclUri(
aclUri: SolidLeafUri,
newRule: WacRule,
resource: SolidContainer | SolidLeaf,
options?: BasicRequestOptions,
): Promise<SetWacRuleResult<SolidContainer | SolidLeaf>>;
export async function setWacRuleForAclUri(
aclUri: SolidLeafUri,
newRule: WacRule, newRule: WacRule,
accessTo: string, resource: SolidContainer | SolidLeaf,
options?: BasicRequestOptions, options?: BasicRequestOptions,
): Promise<SetWacRuleResult> { ): Promise<SetWacRuleResult<SolidContainer | SolidLeaf>> {
const fetch = guaranteeFetch(options?.fetch); const fetch = guaranteeFetch(options?.fetch);
// The rule map keeps track of all the rules that are currently being used // The rule map keeps track of all the rules that are currently being used
// so that similar rules can be grouped together // so that similar rules can be grouped together
@ -56,9 +81,9 @@ export async function setWacRuleForAclUri(
if (accessModeList.write) authorization.mode?.add({ "@id": "Write" }); if (accessModeList.write) authorization.mode?.add({ "@id": "Write" });
if (accessModeList.append) authorization.mode?.add({ "@id": "Append" }); if (accessModeList.append) authorization.mode?.add({ "@id": "Append" });
if (accessModeList.control) authorization.mode?.add({ "@id": "Control" }); if (accessModeList.control) authorization.mode?.add({ "@id": "Control" });
authorization.accessTo = { "@id": accessTo }; authorization.accessTo = { "@id": resource.uri };
if (isContainerUri(accessTo)) { if (isContainerUri(resource.uri)) {
authorization.default = { "@id": accessTo }; authorization.default = { "@id": resource.uri };
} }
ruleMap[accessModeListHash] = authorization; ruleMap[accessModeListHash] = authorization;
} }
@ -88,15 +113,10 @@ export async function setWacRuleForAclUri(
}, },
body: dataset.toString(), body: dataset.toString(),
}); });
const errorResult = HttpErrorResult.checkResponse(aclUri, response); const errorResult = HttpErrorResult.checkResponse(resource, response);
if (errorResult) return errorResult; if (errorResult) return errorResult;
return { return new SetWacRuleSuccess(resource, newRule);
type: "setWacRuleSuccess",
uri: aclUri,
isError: false,
wacRule: newRule,
};
} }
// Hashes the access mode list for use in the rule map // Hashes the access mode list for use in the rule map

Loading…
Cancel
Save