resource policy trusted destinations (#875)

* **New Features**
  * Added a Resource Policy editor for each input, supporting trusted hostnames and private network ranges.
  * Resource URLs now retain their source input and use authenticated links where supported.
  * Resource caching is scoped to the policy authorizing access.

* **Bug Fixes**
  * Invalid or unsupported resource values are safely discarded.
  * Redirects and destination addresses are rechecked against the applicable policy.

* **Breaking Changes**
  * Private DNS destinations require approved hosts and networks; private IP literals require an approved network.
  * Input and alias names must be non-empty and globally unique.
This commit is contained in:
euzu
2026-09-22 15:02:22 +02:00
committed by GitHub
parent fbc1e669fe
commit 2adc18adbc
55 changed files with 3575 additions and 309 deletions
+12 -2
View File
@@ -952,6 +952,7 @@ mod tests {
match_names,
config: Box::new(IcsEpgSourceConfig::default()),
},
input_name: None,
}])
}
@@ -1040,6 +1041,7 @@ mod tests {
priority: 0,
logo_override: false,
kind: PersistedEpgSourceKind::Xmltv,
input_name: None,
}]);
let mut playlist = FetchedPlaylist {
input: &input,
@@ -1254,6 +1256,7 @@ mod tests {
priority: 0,
logo_override: true,
kind: PersistedEpgSourceKind::Xmltv,
input_name: Some("epg-input".into()),
}]);
let mut playlist = FetchedPlaylist {
input: &input,
@@ -1266,8 +1269,12 @@ mod tests {
let updated = playlist.items_mut().next().unwrap();
assert_eq!(updated.header.epg_channel_id.as_deref(), Some("demo.channel"));
assert_eq!(updated.header.logo.as_ref(), "http://guide/icon.png");
assert_eq!(updated.header.logo_small.as_ref(), "http://guide/icon.png");
let logo = shared::model::ResourceLocator::decode(&updated.header.logo).expect("EPG logo locator");
let logo_small =
shared::model::ResourceLocator::decode(&updated.header.logo_small).expect("EPG small logo locator");
assert_eq!(logo.input_name.as_ref(), "epg-input");
assert_eq!(logo.url.as_ref(), "http://guide/icon.png");
assert_eq!(logo_small, logo);
assert_eq!(epg[0].children[0].id.as_ref(), "Demo.Channel");
});
}
@@ -1327,6 +1334,7 @@ mod tests {
priority: 0,
logo_override: false,
kind: PersistedEpgSourceKind::Xmltv,
input_name: None,
}]);
let mut playlist = FetchedPlaylist {
input: &input,
@@ -1434,6 +1442,7 @@ mod tests {
priority: 0,
logo_override: false,
kind: PersistedEpgSourceKind::Xmltv,
input_name: None,
}]);
let mut playlist = FetchedPlaylist {
input: &input,
@@ -1468,6 +1477,7 @@ mod tests {
priority: 0,
logo_override: false,
kind: PersistedEpgSourceKind::Xmltv,
input_name: None,
}]);
let mut playlist = FetchedPlaylist {
input: &input,