parent
8632f0dfe3
commit
4d62c244dc
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@ |
||||
import { ContextDefinition } from "jsonld"; |
||||
|
||||
/** |
||||
* ============================================================================= |
||||
* wacContext: JSONLD Context for wac |
||||
* ============================================================================= |
||||
*/ |
||||
export const wacContext: ContextDefinition = { |
||||
type: { |
||||
"@id": "@type", |
||||
}, |
||||
Authorization: "http://www.w3.org/ns/auth/acl#Authorization", |
||||
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", |
||||
"@container": "@set", |
||||
}, |
||||
agentGroup: { |
||||
"@id": "http://www.w3.org/ns/auth/acl#agentGroup", |
||||
"@type": "@id", |
||||
"@container": "@set", |
||||
}, |
||||
agentClass: { |
||||
"@id": "http://www.w3.org/ns/auth/acl#agentClass", |
||||
"@container": "@set", |
||||
}, |
||||
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", |
||||
"@container": "@set", |
||||
}, |
||||
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 { ContextDefinition } from "jsonld"; |
||||
|
||||
/** |
||||
* ============================================================================= |
||||
* Typescript Typings for wac |
||||
* ============================================================================= |
||||
*/ |
||||
|
||||
/** |
||||
* Authorization Type |
||||
*/ |
||||
export interface Authorization { |
||||
"@id"?: string; |
||||
"@context"?: ContextDefinition; |
||||
/** |
||||
* 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?: { |
||||
"@id": string; |
||||
}[]; |
||||
/** |
||||
* Denotes a group of agents being given the access permission |
||||
*/ |
||||
agentGroup?: { |
||||
"@id": string; |
||||
}[]; |
||||
/** |
||||
* An agent class is a class of persons or entities identified by a URI. |
||||
*/ |
||||
agentClass?: ( |
||||
| { |
||||
"@id": "AuthenticatedAgent"; |
||||
} |
||||
| { |
||||
"@id": "Agent"; |
||||
} |
||||
)[]; |
||||
/** |
||||
* Denotes a class of operations that the agents can perform on a resource. |
||||
*/ |
||||
mode?: ( |
||||
| { |
||||
"@id": "Read"; |
||||
} |
||||
| { |
||||
"@id": "Write"; |
||||
} |
||||
| { |
||||
"@id": "Append"; |
||||
} |
||||
| { |
||||
"@id": "Control"; |
||||
} |
||||
)[]; |
||||
} |
@ -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."; |
||||
) |
||||
} |
@ -1,13 +0,0 @@ |
||||
/* istanbul ignore file */ |
||||
|
||||
export async function getAccessRules(): Promise<undefined> { |
||||
throw new Error("Not Implemented"); |
||||
// const [publicAccess, agentAccess] = await Promise.all([
|
||||
// universalAccess.getPublicAccess(uri, { fetch }),
|
||||
// universalAccess.getAgentAccessAll(uri, { fetch }),
|
||||
// ]);
|
||||
// if (agentAccess === null || publicAccess === null) {
|
||||
// return new AccessRuleFetchError(uri);
|
||||
// }
|
||||
// return new AccessRuleResult(uri, publicAccess, agentAccess);
|
||||
} |
@ -1,88 +0,0 @@ |
||||
/* istanbul ignore file */ |
||||
|
||||
import type { AclDataset, WithChangeLog } from "@inrupt/solid-client"; |
||||
import { |
||||
getSolidDatasetWithAcl, |
||||
hasResourceAcl, |
||||
hasFallbackAcl, |
||||
hasAccessibleAcl, |
||||
createAclFromFallbackAcl, |
||||
getResourceAcl, |
||||
setAgentResourceAccess, |
||||
saveAclFor, |
||||
setPublicDefaultAccess, |
||||
setPublicResourceAccess, |
||||
setAgentDefaultAccess, |
||||
} from "@inrupt/solid-client"; |
||||
import { guaranteeFetch } from "../../util/guaranteeFetch"; |
||||
import { isContainerUri } from "../../util/uriTypes"; |
||||
import type { AccessRule } from "../results/success/AccessRule"; |
||||
import type { SetAccessRuleSuccess } from "../results/success/AccessRule"; |
||||
import { AccessRuleFetchError } from "../results/error/AccessControlError"; |
||||
import type { BasicRequestOptions } from "./requestOptions"; |
||||
|
||||
export type SetAccessRulesResult = |
||||
| SetAccessRuleSuccess |
||||
| SetAccessRulesResultError; |
||||
export type SetAccessRulesResultError = AccessRuleFetchError; |
||||
|
||||
export async function setAccessRules( |
||||
uri: string, |
||||
newAccessRules: AccessRule, |
||||
options?: BasicRequestOptions, |
||||
): Promise<SetAccessRulesResult> { |
||||
console.warn("Access Control is stil underdeveloped. Use with caution."); |
||||
const fetch = guaranteeFetch(options?.fetch); |
||||
const isContainer = isContainerUri(uri); |
||||
|
||||
// Code Copied from https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/manage-wac/
|
||||
// Fetch the SolidDataset and its associated ACLs, if available:
|
||||
const myDatasetWithAcl = await getSolidDatasetWithAcl(uri, { fetch }); |
||||
|
||||
// Obtain the SolidDataset's own ACL, if available,
|
||||
// or initialise a new one, if possible:
|
||||
let resourceAcl; |
||||
if (!hasResourceAcl(myDatasetWithAcl)) { |
||||
if (!hasAccessibleAcl(myDatasetWithAcl)) { |
||||
return new AccessRuleFetchError( |
||||
uri, |
||||
"The current user does not have permission to change access rights to this Resource.", |
||||
); |
||||
} |
||||
if (!hasFallbackAcl(myDatasetWithAcl)) { |
||||
return new AccessRuleFetchError( |
||||
"The current user does not have permission to see who currently has access to this Resource.", |
||||
); |
||||
} |
||||
resourceAcl = createAclFromFallbackAcl(myDatasetWithAcl); |
||||
} else { |
||||
resourceAcl = getResourceAcl(myDatasetWithAcl); |
||||
} |
||||
|
||||
// Give someone Control access to the given Resource:
|
||||
|
||||
let updatedAcl: AclDataset & WithChangeLog = resourceAcl; |
||||
if (newAccessRules.public) { |
||||
if (isContainer) { |
||||
updatedAcl = setPublicDefaultAccess(updatedAcl, newAccessRules.public); |
||||
} else { |
||||
updatedAcl = setPublicResourceAccess(updatedAcl, newAccessRules.public); |
||||
} |
||||
} |
||||
if (newAccessRules.agent) { |
||||
const setAgentAccess = isContainer |
||||
? setAgentDefaultAccess |
||||
: setAgentResourceAccess; |
||||
Object.entries(newAccessRules.agent).forEach(([webId, rules]) => { |
||||
updatedAcl = setAgentAccess(updatedAcl, webId, rules); |
||||
}); |
||||
} |
||||
|
||||
// Now save the ACL:
|
||||
await saveAclFor(myDatasetWithAcl, updatedAcl, { fetch }); |
||||
return { |
||||
isError: false, |
||||
uri, |
||||
type: "setAccessRuleSuccess", |
||||
}; |
||||
} |
@ -1,11 +0,0 @@ |
||||
import type { Access } from "@inrupt/solid-client"; |
||||
import type { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export interface AccessRule { |
||||
public?: Access; |
||||
agent?: Record<string, Access>; |
||||
} |
||||
|
||||
export interface SetAccessRuleSuccess extends ResourceSuccess { |
||||
type: "setAccessRuleSuccess"; |
||||
} |
@ -0,0 +1,19 @@ |
||||
export interface AccessModeList { |
||||
read: boolean; |
||||
append: boolean; |
||||
write: boolean; |
||||
control: boolean; |
||||
} |
||||
|
||||
export interface WacRule { |
||||
public: AccessModeList; |
||||
authenticated: AccessModeList; |
||||
agent: Record<string, AccessModeList>; |
||||
} |
||||
|
||||
// export interface SetWacRule {
|
||||
// ruleFor: Resource;
|
||||
// public?: AccessModeList;
|
||||
// authenticated?: AccessModeList;
|
||||
// agent?: Record<string, AccessModeList>;
|
||||
// }
|
@ -0,0 +1,100 @@ |
||||
import type { GetWacRuleSuccess } from "./results/GetWacRuleSuccess"; |
||||
import { guaranteeFetch } from "../../util/guaranteeFetch"; |
||||
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 { Authorization } from "../../.ldo/wac.typings"; |
||||
|
||||
export type GetWacRuleError = |
||||
| HttpErrorResultType |
||||
| NoncompliantPodError |
||||
| UnexpectedResourceError; |
||||
export type GetWacRuleResult = GetWacRuleSuccess | GetWacRuleError; |
||||
|
||||
export async function getWacRuleWithAclUri( |
||||
aclUri: string, |
||||
options?: BasicRequestOptions, |
||||
): Promise<GetWacRuleResult> { |
||||
const fetch = guaranteeFetch(options?.fetch); |
||||
const response = await fetch(aclUri); |
||||
const errorResult = HttpErrorResult.checkResponse(aclUri, response); |
||||
if (errorResult) return errorResult; |
||||
|
||||
// Parse Turtle
|
||||
const rawTurtle = await response.text(); |
||||
const rawTurtleResult = await rawTurtleToDataset(rawTurtle, aclUri); |
||||
if (rawTurtleResult.isError) return rawTurtleResult; |
||||
const dataset = rawTurtleResult.dataset; |
||||
const authorizations = dataset |
||||
.usingType(AuthorizationShapeType) |
||||
.matchSubject( |
||||
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type", |
||||
"http://www.w3.org/ns/auth/acl#Authorization", |
||||
); |
||||
|
||||
const wacRule: WacRule = { |
||||
public: { |
||||
read: false, |
||||
write: false, |
||||
append: false, |
||||
control: false, |
||||
}, |
||||
authenticated: { |
||||
read: false, |
||||
write: false, |
||||
append: false, |
||||
control: false, |
||||
}, |
||||
agent: {}, |
||||
}; |
||||
|
||||
function applyAccessModesToList( |
||||
accessModeList: AccessModeList, |
||||
authorization: Authorization, |
||||
): void { |
||||
authorization.mode?.forEach((mode) => { |
||||
accessModeList[mode["@id"].toLowerCase()] = true; |
||||
}); |
||||
} |
||||
|
||||
authorizations.forEach((authorization) => { |
||||
if ( |
||||
authorization.agentClass?.some( |
||||
(agentClass) => agentClass["@id"] === "Agent", |
||||
) |
||||
) { |
||||
applyAccessModesToList(wacRule.public, authorization); |
||||
applyAccessModesToList(wacRule.authenticated, authorization); |
||||
} |
||||
if ( |
||||
authorization.agentClass?.some( |
||||
(agentClass) => agentClass["@id"] === "AuthenticatedAgent", |
||||
) |
||||
) { |
||||
applyAccessModesToList(wacRule.authenticated, authorization); |
||||
} |
||||
authorization.agent?.forEach((agent) => { |
||||
if (!wacRule.agent[agent["@id"]]) { |
||||
wacRule.agent[agent["@id"]] = { |
||||
read: false, |
||||
write: false, |
||||
append: false, |
||||
control: false, |
||||
}; |
||||
} |
||||
applyAccessModesToList(wacRule.agent[agent["@id"]], authorization); |
||||
}); |
||||
}); |
||||
|
||||
return { |
||||
type: "getWacRuleSuccess", |
||||
uri: aclUri, |
||||
isError: false, |
||||
wacRule, |
||||
}; |
||||
} |
@ -0,0 +1,63 @@ |
||||
import type { GetWacUriSuccess } from "./results/GetWacUriSuccess"; |
||||
import type { HttpErrorResultType } from "../../requester/results/error/HttpErrorResult"; |
||||
import { |
||||
HttpErrorResult, |
||||
NotFoundHttpError, |
||||
} from "../../requester/results/error/HttpErrorResult"; |
||||
import { UnexpectedResourceError } from "../../requester/results/error/ErrorResult"; |
||||
import { guaranteeFetch } from "../../util/guaranteeFetch"; |
||||
import type { BasicRequestOptions } from "../../requester/requests/requestOptions"; |
||||
import { NoncompliantPodError } from "../../requester/results/error/NoncompliantPodError"; |
||||
import { parse as parseLinkHeader } from "http-link-header"; |
||||
|
||||
export type GetWacUriError = |
||||
| HttpErrorResultType |
||||
| NotFoundHttpError |
||||
| NoncompliantPodError |
||||
| UnexpectedResourceError; |
||||
export type GetWacUriResult = GetWacUriSuccess | GetWacUriError; |
||||
|
||||
export async function getWacUri( |
||||
resourceUri: string, |
||||
options?: BasicRequestOptions, |
||||
): Promise<GetWacUriResult> { |
||||
try { |
||||
const fetch = guaranteeFetch(options?.fetch); |
||||
const response = await fetch(resourceUri, { |
||||
method: "head", |
||||
}); |
||||
const errorResult = HttpErrorResult.checkResponse(resourceUri, response); |
||||
if (errorResult) return errorResult; |
||||
if (NotFoundHttpError.is(response)) { |
||||
return new NotFoundHttpError( |
||||
resourceUri, |
||||
response, |
||||
"Could not get access control rules because the resource does not exist.", |
||||
); |
||||
} |
||||
// Get the URI from the link header
|
||||
const linkHeader = response.headers.get("link"); |
||||
if (!linkHeader) { |
||||
return new NoncompliantPodError( |
||||
resourceUri, |
||||
"No link header present in request.", |
||||
); |
||||
} |
||||
const parsedLinkHeader = parseLinkHeader(linkHeader); |
||||
const aclUris = parsedLinkHeader.get("rel", "acl"); |
||||
if (aclUris.length !== 1) { |
||||
return new NoncompliantPodError( |
||||
resourceUri, |
||||
`There must be one link with a rel="acl"`, |
||||
); |
||||
} |
||||
return { |
||||
type: "getWacUriSuccess", |
||||
isError: false, |
||||
uri: resourceUri, |
||||
wacUri: aclUris[0].uri, |
||||
}; |
||||
} catch (err: unknown) { |
||||
return UnexpectedResourceError.fromThrown(resourceUri, err); |
||||
} |
||||
} |
@ -0,0 +1,7 @@ |
||||
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; |
||||
import type { WacRule } from "../WacRule"; |
||||
|
||||
export interface GetWacRuleSuccess extends ResourceSuccess { |
||||
type: "getWacRuleSuccess"; |
||||
wacRule: WacRule; |
||||
} |
@ -0,0 +1,6 @@ |
||||
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; |
||||
|
||||
export interface GetWacUriSuccess extends ResourceSuccess { |
||||
type: "getWacUriSuccess"; |
||||
wacUri: string; |
||||
} |
@ -0,0 +1,7 @@ |
||||
import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult"; |
||||
import type { WacRule } from "../WacRule"; |
||||
|
||||
export interface SetWacRuleSuccess extends ResourceSuccess { |
||||
type: "setWacRuleSuccess"; |
||||
wacRule: WacRule; |
||||
} |
Loading…
Reference in new issue