check method
The refusal for asset under tenant, or null when it may be fetched.
Implementation
DVSceneAssetRefusal? check(DVSceneAsset asset, {required String tenant}) {
final String ref = asset.reference;
if (ref.isEmpty || ref.contains('\\') || ref.codeUnits.any((int c) => c < 0x20)) {
return const DVSceneAssetRefusal(
'the reference is empty or contains a backslash or control character');
}
final int? ceiling = maxBytes;
if (ceiling != null && asset.byteLength != null && asset.byteLength! > ceiling) {
return DVSceneAssetRefusal(
'the asset declares ${asset.byteLength} bytes, over the $ceiling-byte ceiling');
}
switch (asset.source) {
case DVSceneAssetSource.bundled:
if (ref.contains(':') || ref.startsWith('/') || _climbs(ref)) {
return DVSceneAssetRefusal(
"'$ref' is not a relative bundle key");
}
return null;
case DVSceneAssetSource.stored:
if (ref.startsWith('/') || _climbs(ref)) {
return DVSceneAssetRefusal("'$ref' climbs out of its storage prefix");
}
if (requireDigest && asset.sha256 == null) {
return DVSceneAssetRefusal(
"the stored asset '$ref' has no sha256, so its bytes cannot be verified");
}
if (ref.startsWith(tenantPrefix)) {
final String owner = ref.substring(tenantPrefix.length).split('/').first;
if (owner != tenant) {
return DVSceneAssetRefusal(
"'$ref' belongs to tenant '$owner', not to the current tenant '$tenant'");
}
return null;
}
if (sharedStoragePrefixes.any(ref.startsWith)) return null;
return DVSceneAssetRefusal(
"'$ref' is outside $tenantPrefix$tenant/ and no shared prefix covers it");
case DVSceneAssetSource.network:
final Uri? uri = Uri.tryParse(ref);
if (uri == null || uri.scheme != 'https' || uri.host.isEmpty) {
return DVSceneAssetRefusal("'$ref' is not an https URL");
}
if (uri.userInfo.isNotEmpty) {
return DVSceneAssetRefusal("'$ref' carries credentials in the URL");
}
final String host = uri.host.toLowerCase();
if (!allowedHosts.any((String h) => h.toLowerCase() == host)) {
return DVSceneAssetRefusal(
"the host '$host' is not in the scene asset policy's allowed hosts");
}
if (requireDigest && asset.sha256 == null) {
return DVSceneAssetRefusal(
"the network asset '$ref' has no sha256, so its bytes cannot be verified");
}
return null;
}
}