parent
59013086eb
commit
087f57b4f5
@ -1,6 +1,7 @@ |
|||||||
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; |
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; |
||||||
|
import type { LeafUri } from "../../../util/uriTypes"; |
||||||
|
|
||||||
export interface GetWacUriSuccess extends ResourceSuccess { |
export interface GetWacUriSuccess extends ResourceSuccess { |
||||||
type: "getWacUriSuccess"; |
type: "getWacUriSuccess"; |
||||||
wacUri: string; |
wacUri: LeafUri; |
||||||
} |
} |
||||||
|
@ -0,0 +1,100 @@ |
|||||||
|
import { createLdoDataset } from "@ldo/ldo"; |
||||||
|
import type { BasicRequestOptions } from "../../requester/requests/requestOptions"; |
||||||
|
import type { UnexpectedResourceError } from "../../requester/results/error/ErrorResult"; |
||||||
|
import { |
||||||
|
HttpErrorResult, |
||||||
|
type HttpErrorResultType, |
||||||
|
} from "../../requester/results/error/HttpErrorResult"; |
||||||
|
import { isContainerUri, type LeafUri } from "../../util/uriTypes"; |
||||||
|
import type { AccessModeList, WacRule } from "./WacRule"; |
||||||
|
import type { 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"; |
||||||
|
|
||||||
|
export type SetWacRuleError = HttpErrorResultType | UnexpectedResourceError; |
||||||
|
export type SetWacRuleResult = SetWacRuleSuccess | SetWacRuleError; |
||||||
|
|
||||||
|
export async function setWacRuleForAclUri( |
||||||
|
aclUri: LeafUri, |
||||||
|
newRule: WacRule, |
||||||
|
accessTo: string, |
||||||
|
options?: BasicRequestOptions, |
||||||
|
): Promise<SetWacRuleResult> { |
||||||
|
const fetch = guaranteeFetch(options?.fetch); |
||||||
|
// The rule map keeps track of all the rules that are currently being used
|
||||||
|
// so that similar rules can be grouped together
|
||||||
|
const ruleMap: Record<string, Authorization> = {}; |
||||||
|
// The dataset that will eventually be sent to the Pod
|
||||||
|
const dataset = createLdoDataset(); |
||||||
|
|
||||||
|
// Helper function to add rules to the dataset by grouping them in the ruleMap
|
||||||
|
function addRuleToDataset( |
||||||
|
type: "public" | "authenticated" | "agent", |
||||||
|
accessModeList: AccessModeList, |
||||||
|
agentId?: string, |
||||||
|
) { |
||||||
|
const accessModeListHash = hashAccessModeList(accessModeList); |
||||||
|
// No need to add if all access is false
|
||||||
|
if (accessModeListHash === "") return; |
||||||
|
if (!ruleMap[accessModeListHash]) { |
||||||
|
const authorization = dataset |
||||||
|
.usingType(AuthorizationShapeType) |
||||||
|
.fromSubject(`${aclUri}#${v4()}`); |
||||||
|
authorization.type = { "@id": "Authorization" }; |
||||||
|
if (accessModeList.read) authorization.mode?.push({ "@id": "Read" }); |
||||||
|
if (accessModeList.write) authorization.mode?.push({ "@id": "Write" }); |
||||||
|
if (accessModeList.append) authorization.mode?.push({ "@id": "Append" }); |
||||||
|
if (accessModeList.control) |
||||||
|
authorization.mode?.push({ "@id": "Control" }); |
||||||
|
authorization.accessTo = { "@id": accessTo }; |
||||||
|
if (isContainerUri(accessTo)) { |
||||||
|
authorization.default = { "@id": accessTo }; |
||||||
|
} |
||||||
|
ruleMap[accessModeListHash] = authorization; |
||||||
|
} |
||||||
|
const authorization = ruleMap[accessModeListHash]; |
||||||
|
// Add agents to the rule
|
||||||
|
if (type === "public") { |
||||||
|
authorization.agentClass?.push({ "@id": "Agent" }); |
||||||
|
} else if (type === "authenticated") { |
||||||
|
authorization.agentClass?.push({ "@id": "AuthenticatedAgent" }); |
||||||
|
} else if (type === "agent" && agentId) { |
||||||
|
authorization.agent?.push({ "@id": agentId }); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Add each rule to the dataset
|
||||||
|
addRuleToDataset("public", newRule.public); |
||||||
|
addRuleToDataset("authenticated", newRule.authenticated); |
||||||
|
Object.entries(newRule.agent).forEach(([agentUri, accessModeList]) => { |
||||||
|
addRuleToDataset("agent", accessModeList, agentUri); |
||||||
|
}); |
||||||
|
|
||||||
|
// Save to Pod
|
||||||
|
const response = await fetch(aclUri, { |
||||||
|
method: "PUT", |
||||||
|
headers: { |
||||||
|
"content-type": "text/turtle", |
||||||
|
}, |
||||||
|
body: dataset.toString(), |
||||||
|
}); |
||||||
|
const errorResult = HttpErrorResult.checkResponse(aclUri, response); |
||||||
|
if (errorResult) return errorResult; |
||||||
|
|
||||||
|
return { |
||||||
|
type: "setWacRuleSuccess", |
||||||
|
uri: aclUri, |
||||||
|
isError: false, |
||||||
|
wacRule: newRule, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// Hashes the access mode list for use in the rule map
|
||||||
|
function hashAccessModeList(list: AccessModeList): string { |
||||||
|
return Object.entries(list).reduce( |
||||||
|
(agg, [key, isPresent]) => (isPresent ? agg + key : agg), |
||||||
|
"", |
||||||
|
); |
||||||
|
} |
Loading…
Reference in new issue