Skip to content

Commit

Permalink
fix: ACL is still better in the inrupt API than universal access
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximvdw committed Feb 10, 2025
1 parent fcce5a3 commit eba0511
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 53 deletions.
115 changes: 63 additions & 52 deletions src/common/SolidService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ import {
hasAcl,
saveAclFor,
WithAcl,
setAgentResourceAccess,
setGroupDefaultAccess,
setGroupResourceAccess,
createAcl,
AclDataset,
setPublicResourceAccess,
setPublicDefaultAccess,
} from '@inrupt/solid-client';
import { fetch } from 'cross-fetch';
import {
Expand Down Expand Up @@ -563,7 +570,6 @@ export abstract class SolidService extends RemoteService {
...dataset,
internal_resourceInfo: resourceInfo,
} as SolidDataset;
console.log((dataset as any).internal_changeLog.additions);
saveSolidDatasetInContainer(containerURL.href, dataset, options).then(resolve).catch(reject);
} else {
saveSolidDatasetAt(documentURL.href, dataset, options).then(resolve).catch(reject);
Expand Down Expand Up @@ -591,78 +597,83 @@ export abstract class SolidService extends RemoteService {
/**
* Set access control list for a specific object
* @param {IriString} uri URI of the object
* @param {Partial<AccessModes & { default?: boolean, public?: boolean }>} access Access modes
* @param {Partial<AccessModes & { default?: boolean, public?: boolean, group?: boolean }>} access Access modes
* @param {string} [webId] WebID to set access for
* @param {SolidSession} [session] Session to use
*/
setAccess(
uri: IriString,
access: Partial<AccessModes & { default?: boolean; public?: boolean }>,
access: Partial<AccessModes & { default?: boolean; public?: boolean; group?: boolean }>,
webId: string = foaf.Agent,
session?: SolidSession,
): Promise<void> {
return new Promise((resolve, reject) => {
universalAccess
.setAgentAccess(
uri,
webId,
access,
session
? {
fetch: session.fetch,
}
: this.session,
)
.then(() => {
if (access.public) {
// Set public access
return this.setPublicAccess(uri, access, session);
getSolidDatasetWithAcl(uri, session ? { fetch: session.fetch } : this.session)
.then((dataset: SolidDataset & WithServerResourceInfo & WithAcl) => {
let acl: AclDataset;
// Get or access Acl
if (!hasAcl(dataset)) {
acl = getResourceAcl(dataset);
} else {
resolve();
acl = createAcl(dataset as any);
}
})
.then(() => {
if (access.default) {
// Set default access
// Get ACL dataset
return getSolidDatasetWithAcl(uri, session ? { fetch: session.fetch } : this.session);

access.group = access.group || webId === foaf.Agent || webId === 'public';

// Resource access
if (access.group) {
acl = setGroupResourceAccess(acl, webId, {
read: access.read,
append: access.append,
write: access.write,
control: access.controlWrite,
});
} else {
resolve();
acl = setAgentResourceAccess(acl, webId, {
read: access.read,
append: access.append,
write: access.write,
control: access.controlWrite,
});
}
})
.then((dataset: SolidDataset & WithServerResourceInfo & WithAcl) => {
if (hasAcl(dataset)) {
let acl = getResourceAcl(dataset);

// Set public access
if (access.public) {
acl = setPublicResourceAccess(acl, {
read: access.read,
append: access.append,
write: access.write,
control: access.controlWrite,
});
}
if (access.public && access.default) {
acl = setPublicDefaultAccess(acl, {
read: access.read,
append: access.append,
write: access.write,
control: access.controlWrite,
});
}

// Set default group access
if (access.group && access.default) {
acl = setGroupDefaultAccess(acl, webId, {
read: access.read,
append: access.append,
write: access.write,
control: access.controlWrite,
});
} else if (access.default) {
acl = setAgentDefaultAccess(acl, webId, {
read: access.read,
append: access.append,
write: access.write,
control: access.controlWrite,
});
return saveAclFor(dataset as any, acl, session ? { fetch: session.fetch } : this.session);
} else {
resolve();
}
})
.then(() => {
resolve();
})
.catch(reject);
});
}

setPublicAccess(uri: IriString, access: Partial<AccessModes>, session?: SolidSession): Promise<void> {
return new Promise((resolve, reject) => {
universalAccess
.setPublicAccess(
uri,
access,
session
? {
fetch: session.fetch,
}
: this.session,
)
return saveAclFor(dataset as any, acl, session ? { fetch: session.fetch } : this.session);
})
.then(() => {
resolve();
})
Expand Down
11 changes: 10 additions & 1 deletion test/specs/solid.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ describe('SolidService', () => {
const service = solidServices[0];
const session = service.session;
let containerURL: IriString = "http://localhost:3000/test1/abc/";
let uri = "";
service.createContainer(session, containerURL).then(() => {
// Set access rights
return service.setAccess(containerURL, {
Expand All @@ -176,9 +177,17 @@ describe('SolidService', () => {
const store = RDFSerializer.serializeToStore(obj);
return service2.saveDataset(session2, `http://localhost:3000/test1/abc/${new Date().getTime()}.ttl`, store, true);
}).then((dataset) => {
const uri = dataset.internal_resourceInfo.sourceIri;
uri = dataset.internal_resourceInfo.sourceIri;
// Verify that the item has content
return service.getDatasetStore(session, uri);
}).then((store) => {
expect(store).to.not.be.undefined;
expect(store.size).to.be.greaterThan(0);
// Service 2 should be able to read the content
// Verify that the item has content
const service2 = solidServices[1];
const session2 = service2.session;
return service2.getDatasetStore(session2, uri);
}).then((store) => {
expect(store).to.not.be.undefined;
expect(store.size).to.be.greaterThan(0);
Expand Down

0 comments on commit eba0511

Please sign in to comment.