@@ -163,7 +163,7 @@ export class ProtocolAuthorization {
163163 ) ;
164164
165165 // Verify expiry
166- ProtocolAuthorization . verifyExpiry ( incomingMessage , ruleSet )
166+ ProtocolAuthorization . verifyExpiration ( incomingMessage , ruleSet ) ;
167167 }
168168
169169 public static async authorizeQueryOrSubscribe (
@@ -730,29 +730,48 @@ export class ProtocolAuthorization {
730730 }
731731
732732 /**
733- * Verifies that reads adhere to the $expiry constraint if provided
734- * @throws {Error } if expiry date is passed.
735- */
736- private static verifyExpiry (
737- incomingMessage : RecordsRead ,
733+ * Verifies that queries and reads adhere to the $expiration constraint if provided
734+ * @throws {Error } if more than one $expiration property is set,
735+ */
736+ private static verifyExpiration (
737+ incomingMessage : RecordsWrite ,
738738 ruleSet : ProtocolRuleSet
739739 ) : void {
740- const ruleExpiry = ruleSet . $expiry ;
741- if ( ! ruleExpiry ) {
740+ const ruleExpiration = ruleSet . $expiration ;
741+ if ( ! ruleExpiration ) {
742742 return ;
743743 }
744744
745- const dateCreated = incomingMessage . message . descriptor . filter ?. dateCreated ;
746- if ( ! dateCreated ) {
747- return ;
745+ const expirationEntries = Object . entries ( ruleExpiration ) ;
746+ if ( expirationEntries . length > 1 ) {
747+ throw new DwnError ( DwnErrorCode . ProtocolsConfigureInvalidExpiration ,
748+ `invalid property: expiration ${ ruleExpiration } cannot set more than one property` ) ;
748749 }
749750
750- const dateExpiry = dateCreated + ruleExpiry ;
751- if ( Date . now ( ) > dateExpiry ) {
752- throw new DwnError ( DwnErrorCode . ProtocolAuthorizationExpiryReached , `dateExpiry ${ dateExpiry } has passed ` ) ;
751+ const { duration , datetime } = ruleExpiration ;
752+ if ( ! duration && ! datetime ) {
753+ throw new DwnError ( DwnErrorCode . ProtocolsConfigureInvalidExpiration , `invalid property ${ ruleExpiration } : must set at least one property ` ) ;
753754 }
754755
755- }
756+ if ( duration && typeof duration === 'number' && duration < 1 ) {
757+ throw new DwnError ( DwnErrorCode . ProtocolsConfigureInvalidExpirationDuration , `invalid property: duration ${ duration } number must must be >= 1` ) ;
758+ } else if ( typeof duration === 'string' ) {
759+ const [ amount , unit ] = duration . split ( '' ) [ 0 ] ;
760+ if ( ( unit === 's' && parseInt ( amount ) < 1 ) ) {
761+ throw new DwnError ( DwnErrorCode . ProtocolsConfigureInvalidExpirationDuration ,
762+ `invalid property: if duration unit ${ unit } = s, amount ${ amount } must >= 1 (i.e. 1s)` ) ;
763+ }
764+ if ( ! / \d { 1 , } ( s | m | h | d | y ) / . test ( duration ) ) {
765+ throw new DwnError ( DwnErrorCode . ProtocolsConfigureInvalidExpirationDuration ,
766+ `invalid property: duration ${ duration } format must be \"<amount><s|m|h|d|y>\" (e.g. 1s, 10d, 5y)` ) ;
767+ }
768+ }
769+
770+ if ( datetime && / ( \d { 4 } ) - ( 0 [ 1 - 9 ] | 1 [ 0 - 2 ] ) - ( 0 [ 1 - 9 ] | [ 1 2 ] \d | 3 [ 0 1 ] ) T ( [ 0 1 ] \d | 2 [ 0 - 3 ] ) : ( [ 0 - 5 ] \d ) : ( [ 0 - 5 ] \d ) Z / . test ( datetime ) ) {
771+ throw new DwnError ( DwnErrorCode . ProtocolsConfigureInvalidExpirationDatetime ,
772+ `invalid format: datetime ${ datetime } does not conform to ISO-8601 UTC format` ) ;
773+ }
774+ } ;
756775
757776 /**
758777 * If the given RecordsWrite is not a role record, this method does nothing and succeeds immediately.
0 commit comments