use crate::error::VtxError;
use crate::{Capabilities, HttpAllowRule};
pub const PERM_BUFFER_CREATE: &str = "buffer:create";
pub const PERM_FILE_READ: &str = "file:read";
pub const PERM_FILE_WRITE: &str = "file:write";
pub const PERM_FFMPEG_EXECUTE: &str = "ffmpeg:execute";
pub const PERM_SQL_WRITE: &str = "sql:write";
pub trait CapabilitiesExt {
fn has_permission(&self, perm: &str) -> bool;
}
impl CapabilitiesExt for Capabilities {
fn has_permission(&self, perm: &str) -> bool {
self.permissions.iter().any(|p| p == perm)
}
}
pub trait VtxErrorExt {
fn is_permission_denied(&self) -> bool;
}
impl VtxErrorExt for VtxError {
fn is_permission_denied(&self) -> bool {
matches!(self, VtxError::PermissionDenied(_))
}
}
pub struct CapabilitiesBuilder {
subscriptions: Vec<String>,
permissions: Vec<String>,
http: Vec<HttpAllowRule>,
}
impl CapabilitiesBuilder {
pub fn new() -> Self {
Self {
subscriptions: Vec::new(),
permissions: Vec::new(),
http: Vec::new(),
}
}
pub fn subscription(mut self, topic: impl Into<String>) -> Self {
self.subscriptions.push(topic.into());
self
}
pub fn subscriptions<I, S>(mut self, topics: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.subscriptions
.extend(topics.into_iter().map(Into::into));
self
}
pub fn permission(mut self, perm: impl Into<String>) -> Self {
self.permissions.push(perm.into());
self
}
pub fn permissions<I, S>(mut self, perms: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.permissions.extend(perms.into_iter().map(Into::into));
self
}
pub fn http_rule(mut self, rule: HttpAllowRule) -> Self {
self.http.push(rule);
self
}
pub fn http_rules<I>(mut self, rules: I) -> Self
where
I: IntoIterator<Item = HttpAllowRule>,
{
self.http.extend(rules);
self
}
pub fn build(self) -> Capabilities {
let http = if self.http.is_empty() {
None
} else {
Some(self.http)
};
Capabilities {
subscriptions: self.subscriptions,
permissions: self.permissions,
http,
}
}
}
impl Default for CapabilitiesBuilder {
fn default() -> Self {
Self::new()
}
}
pub struct HttpAllowRuleBuilder {
scheme: String,
host: String,
port: Option<u16>,
path: Option<String>,
methods: Option<Vec<String>>,
allow_headers: Option<Vec<String>>,
max_request_bytes: Option<u64>,
max_response_bytes: Option<u64>,
follow_redirects: Option<bool>,
redirect_policy: Option<String>,
}
impl HttpAllowRuleBuilder {
pub fn new(scheme: impl Into<String>, host: impl Into<String>) -> Self {
Self {
scheme: scheme.into(),
host: host.into(),
port: None,
path: None,
methods: None,
allow_headers: None,
max_request_bytes: None,
max_response_bytes: None,
follow_redirects: None,
redirect_policy: None,
}
}
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
pub fn path(mut self, path: impl Into<String>) -> Self {
self.path = Some(path.into());
self
}
pub fn methods<I, S>(mut self, methods: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.methods = Some(methods.into_iter().map(Into::into).collect());
self
}
pub fn allow_headers<I, S>(mut self, headers: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.allow_headers = Some(headers.into_iter().map(Into::into).collect());
self
}
pub fn max_request_bytes(mut self, bytes: u64) -> Self {
self.max_request_bytes = Some(bytes);
self
}
pub fn max_response_bytes(mut self, bytes: u64) -> Self {
self.max_response_bytes = Some(bytes);
self
}
pub fn follow_redirects(mut self, enabled: bool) -> Self {
self.follow_redirects = Some(enabled);
self
}
pub fn redirect_policy(mut self, policy: impl Into<String>) -> Self {
self.redirect_policy = Some(policy.into());
self
}
pub fn build(self) -> HttpAllowRule {
HttpAllowRule {
scheme: self.scheme,
host: self.host,
port: self.port,
path: self.path,
methods: self.methods,
allow_headers: self.allow_headers,
max_request_bytes: self.max_request_bytes,
max_response_bytes: self.max_response_bytes,
follow_redirects: self.follow_redirects,
redirect_policy: self.redirect_policy,
}
}
}