Skip to content

Commit

Permalink
pushing latest changes for expiration
Browse files Browse the repository at this point in the history
  • Loading branch information
Bnonni committed Apr 27, 2024
1 parent 968f052 commit 05f431a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 28 deletions.
21 changes: 12 additions & 9 deletions json-schemas/interface-methods/protocol-rule-set.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,21 @@
"additionalProperties": false,
"properties": {
"duration": {
"type": "number",
"minimum": 1,
"$comment": "Amount of milliseconds to add to dateCreated to determine expiration date"
},
"timespan": {
"type": "string",
"minimum": "1s",
"$comment": "Amount of time concatenated to time unit to convert and add to dateCreated to determine expiration date. e.g. 30s, 45m, 10h, 2D, 3W, 6M, 2Y"
"oneOf": [
{
"type": "string",
"$comment": "A number and a time unit formatted as <amount><unit> representing an amount of time to wait before expiration. Smallest possible <amount><unit> value is 1s. s = seconds, m = minutes, h = hours, d = days, y = years. e.g. 30s, 45m, 10h, 2d, 2y"
},
{
"type": "number",
"minimum": 1,
"$comment": "Amount of milliseconds to wait before expiration."
}
]
},
"datetime": {
"type": "string",
"$comment": "Explicit expiration date and time in ISO8601 format YYYY-MM-DDThh:mm:ssZ."
"$comment": "Explicit expiration datetime string in ISO-8601 UTC format (YYYY-MM-DDThh:mm:ssZ). e.g. 1970-01-01T00:00:00Z"
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/core/dwn-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export enum DwnErrorCode {
PrivateKeySignerUnsupportedCurve = 'PrivateKeySignerUnsupportedCurve',
ProtocolAuthorizationActionNotAllowed = 'ProtocolAuthorizationActionNotAllowed',
ProtocolAuthorizationActionRulesNotFound = 'ProtocolAuthorizationActionRulesNotFound',
ProtocolAuthorizationExpiryReached = 'ProtocolAuthorizationExpiryReached',
ProtocolAuthorizationExpirationPassed = 'ProtocolAuthorizationExpirationPassed',
ProtocolAuthorizationIncorrectDataFormat = 'ProtocolAuthorizationIncorrectDataFormat',
ProtocolAuthorizationIncorrectContextId = 'ProtocolAuthorizationIncorrectContextId',
ProtocolAuthorizationIncorrectProtocolPath = 'ProtocolAuthorizationIncorrectProtocolPath',
Expand All @@ -75,7 +75,9 @@ export enum DwnErrorCode {
ProtocolAuthorizationRoleMissingRecipient = 'ProtocolAuthorizationRoleMissingRecipient',
ProtocolsConfigureDuplicateActorInRuleSet = 'ProtocolsConfigureDuplicateActorInRuleSet',
ProtocolsConfigureDuplicateRoleInRuleSet = 'ProtocolsConfigureDuplicateRoleInRuleSet',
ProtocolsConfigureInvalidExpiry = 'ProtocolsConfigureInvalidExpiry',
ProtocolsConfigureInvalidExpiration = 'ProtocolsConfigureInvalidExpiration',
ProtocolsConfigureInvalidExpirationDuration = 'ProtocolsConfigureInvalidExpirationDuration',
ProtocolsConfigureInvalidExpirationDatetime = 'ProtocolsConfigureInvalidExpirationDatetime',
ProtocolsConfigureInvalidSize = 'ProtocolsConfigureInvalidSize',
ProtocolsConfigureInvalidActionMissingOf = 'ProtocolsConfigureInvalidActionMissingOf',
ProtocolsConfigureInvalidActionOfNotAllowed = 'ProtocolsConfigureInvalidActionOfNotAllowed',
Expand Down
49 changes: 34 additions & 15 deletions src/core/protocol-authorization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export class ProtocolAuthorization {
);

// Verify expiry
ProtocolAuthorization.verifyExpiry(incomingMessage, ruleSet)
ProtocolAuthorization.verifyExpiration(incomingMessage, ruleSet);
}

public static async authorizeQueryOrSubscribe(
Expand Down Expand Up @@ -691,29 +691,48 @@ export class ProtocolAuthorization {
}

/**
* Verifies that reads adhere to the $expiry constraint if provided
* @throws {Error} if expiry date is passed.
*/
private static verifyExpiry(
incomingMessage: RecordsRead,
* Verifies that queries and reads adhere to the $expiration constraint if provided
* @throws {Error} if more than one $expiration property is set,
*/
private static verifyExpiration(
incomingMessage: RecordsWrite,
ruleSet: ProtocolRuleSet
): void {
const ruleExpiry = ruleSet.$expiry;
if (!ruleExpiry) {
const ruleExpiration = ruleSet.$expiration;
if (!ruleExpiration) {
return;
}

const dateCreated = incomingMessage.message.descriptor.filter?.dateCreated;
if (!dateCreated) {
return;
const expirationEntries = Object.entries(ruleExpiration);
if (expirationEntries.length > 1) {
throw new DwnError(DwnErrorCode.ProtocolsConfigureInvalidExpiration,
`invalid property: expiration ${ruleExpiration} cannot set more than one property`);
}

const dateExpiry = dateCreated + ruleExpiry;
if (Date.now() > dateExpiry) {
throw new DwnError(DwnErrorCode.ProtocolAuthorizationExpiryReached, `dateExpiry ${dateExpiry} has passed`);
const { duration, datetime } = ruleExpiration;
if (!duration && !datetime) {
throw new DwnError(DwnErrorCode.ProtocolsConfigureInvalidExpiration, `invalid property ${ruleExpiration}: must set at least one property`);
}

}
if (duration && typeof duration === 'number' && duration < 1) {
throw new DwnError(DwnErrorCode.ProtocolsConfigureInvalidExpirationDuration, `invalid property: duration ${duration} number must must be >= 1`);
} else if (typeof duration === 'string') {
const [amount, unit] = duration.split('')[0];
if ((unit === 's' && parseInt(amount) < 1)) {
throw new DwnError(DwnErrorCode.ProtocolsConfigureInvalidExpirationDuration,
`invalid property: if duration unit ${unit} = s, amount ${amount} must >= 1 (i.e. 1s)`);
}
if (!/\d{1,}(s|m|h|d|y)/.test(duration)) {
throw new DwnError(DwnErrorCode.ProtocolsConfigureInvalidExpirationDuration,
`invalid property: duration ${duration} format must be \"<amount><s|m|h|d|y>\" (e.g. 1s, 10d, 5y)`);
}
}

if (datetime && /(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):([0-5]\d):([0-5]\d)Z/.test(datetime)) {
throw new DwnError(DwnErrorCode.ProtocolsConfigureInvalidExpirationDatetime,
`invalid format: datetime ${datetime} does not conform to ISO-8601 UTC format`);
}
};

/**
* If the given RecordsWrite is not a role record, this method does nothing and succeeds immediately.
Expand Down
7 changes: 5 additions & 2 deletions src/types/protocols-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,12 @@ export type ProtocolRuleSet = {
}

/**
* If $expiry is set, the record expiry in ms.
* If $expiration is set, the record expiration in ms.
*/
$expiry?: number;
$expiration?: {
duration?: string | number;
datetime?: string;
};

// JSON Schema verifies that properties other than properties prefixed with $ will actually have type ProtocolRuleSet
[key: string]: any;
Expand Down

0 comments on commit 05f431a

Please sign in to comment.