ssowat-rs/yunohost-api/src/permissions/ssowat.rs

98 lines
3.1 KiB
Rust

use regex::Regex;
use serde::{Serialize, Deserialize};
use url::Url;
use std::collections::HashMap;
use crate::Username;
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct SSOWatConfig {
domains: Vec<String>,
permissions: HashMap<PermissionName, Permission>,
portal_domain: String,
portal_path: String,
redirected_urls: HashMap<String, String>,
theme: String,
}
impl SSOWatConfig {
pub fn permission_for_uri(&self, uri: &Url) -> Option<PermissionName> {
// First check if the domain is actually managed by SSOWat
if let Some(domain) = uri.domain() {
if ! self.domains.contains(&domain.to_string()) {
// Domain not managed
return None;
}
// Strip protocol but keep full URL
let stripped_uri = AsRef::<str>::as_ref(uri)
.trim_start_matches("http")
.trim_start_matches("s")
.trim_start_matches("://");
// Check which app matches this URI, to find corresponding permission
for (key, val) in &self.permissions {
for uri_format in &val.uris {
if uri_format.starts_with("re:") {
let uri_format = uri_format.trim_start_matches("re:");
// TODO: generate regex in advance
// TODO: error
let re = Regex::new(uri_format).unwrap();
if re.is_match(stripped_uri) {
return Some(key.clone());
}
} else {
if stripped_uri.starts_with(uri_format) {
return Some(key.clone());
}
}
}
}
// No app URI matched
return None;
} else {
// No domain (eg. http://8.8.8.8/)
return None;
}
}
pub fn user_has_permission_for_uri(&self, username: Option<&Username>, uri: &Url) -> bool {
if let Some(permission_name) = self.permission_for_uri(uri) {
let permission = self.permissions.get(&permission_name).unwrap();
if permission.public {
return true;
}
if let Some(username) = username {
permission.users.contains(username)
} else {
// User is not logged-in. Non-public URIs are not authorized
false
}
} else {
// No permission matching this URI
false
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Permission {
auth_header: bool,
label: String,
public: bool,
show_tile: bool,
uris: Vec<String>,
#[serde(default)]
use_remote_user_in_nginx_conf: bool,
users: Vec<Username>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct PermissionName {
name: String,
}