mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
fix: Support new ETag format in notification states
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { RepresentationMetadata } from '../http/representation/RepresentationMetadata';
|
||||
import { DC } from '../util/Vocabularies';
|
||||
import { getETag, isCurrentETag } from './Conditions';
|
||||
import { getETag, sameResourceState } from './Conditions';
|
||||
import type { Conditions } from './Conditions';
|
||||
|
||||
export interface BasicConditionsOptions {
|
||||
@@ -39,19 +39,21 @@ export class BasicConditions implements Conditions {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper function to see if an ETag matches the provided metadata
|
||||
// eslint-disable-next-line func-style
|
||||
let eTagMatches = (tag: string): boolean => isCurrentETag(tag, metadata);
|
||||
if (strict) {
|
||||
const eTag = getETag(metadata);
|
||||
eTagMatches = (tag: string): boolean => tag === eTag;
|
||||
}
|
||||
const eTag = getETag(metadata);
|
||||
if (eTag) {
|
||||
// Helper function to see if an ETag matches the provided metadata
|
||||
// eslint-disable-next-line func-style
|
||||
let eTagMatches = (tag: string): boolean => sameResourceState(tag, eTag);
|
||||
if (strict) {
|
||||
eTagMatches = (tag: string): boolean => tag === eTag;
|
||||
}
|
||||
|
||||
if (this.matchesETag && !this.matchesETag.includes('*') && !this.matchesETag.some(eTagMatches)) {
|
||||
return false;
|
||||
}
|
||||
if (this.notMatchesETag?.some(eTagMatches)) {
|
||||
return false;
|
||||
if (this.matchesETag && !this.matchesETag.includes('*') && !this.matchesETag.some(eTagMatches)) {
|
||||
return false;
|
||||
}
|
||||
if (this.notMatchesETag?.some(eTagMatches)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// In practice, this will only be undefined on a backend
|
||||
|
||||
@@ -42,31 +42,21 @@ export interface Conditions {
|
||||
export function getETag(metadata: RepresentationMetadata): string | undefined {
|
||||
const modified = metadata.get(DC.terms.modified);
|
||||
const { contentType } = metadata;
|
||||
if (modified && contentType) {
|
||||
if (modified) {
|
||||
const date = new Date(modified.value);
|
||||
return `"${date.getTime()}-${contentType}"`;
|
||||
// It is possible for the content type to be undefined,
|
||||
// such as when only the metadata returned by a `DataAccessor` is used.
|
||||
return `"${date.getTime()}-${contentType ?? ''}"`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether a given ETag corresponds to the current state of the resource,
|
||||
* independent of the representation the ETag corresponds to.
|
||||
* Validates whether 2 ETags correspond to the same state of a resource,
|
||||
* independent of the representation the ETags correspond to.
|
||||
* Assumes ETags are made with the {@link getETag} function.
|
||||
* Since we base the ETag on the last modified date,
|
||||
* we know the ETag still matches as long as that didn't change.
|
||||
*
|
||||
* @param eTag - ETag to validate.
|
||||
* @param metadata - Metadata of the resource.
|
||||
*
|
||||
* @returns `true` if the ETag represents the current state of the resource.
|
||||
*/
|
||||
export function isCurrentETag(eTag: string, metadata: RepresentationMetadata): boolean {
|
||||
const modified = metadata.get(DC.terms.modified);
|
||||
if (!modified) {
|
||||
return false;
|
||||
}
|
||||
const time = eTag.split('-', 1)[0];
|
||||
const date = new Date(modified.value);
|
||||
// `time` will still have the initial`"` of the ETag string
|
||||
return time === `"${date.getTime()}`;
|
||||
export function sameResourceState(eTag1: string, eTag2: string): boolean {
|
||||
// Since we base the ETag on the last modified date,
|
||||
// we know the ETags match as long as the date part is the same.
|
||||
return eTag1.split('-')[0] === eTag2.split('-')[0];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user