Access token permissions
This commit is contained in:
@@ -21,7 +21,7 @@ use store::{
|
||||
BitmapKey, ValueKey,
|
||||
};
|
||||
|
||||
use crate::directory::DirectoryTest;
|
||||
use crate::directory::{DirectoryTest, IntoTestPrincipal, TestPrincipal};
|
||||
|
||||
#[tokio::test]
|
||||
async fn internal_directory() {
|
||||
@@ -33,20 +33,20 @@ async fn internal_directory() {
|
||||
|
||||
// A principal without name should fail
|
||||
assert_eq!(
|
||||
store.create_account(Principal::default(), vec![]).await,
|
||||
store.create_account(Principal::default()).await,
|
||||
Err(manage::err_missing(PrincipalField::Name))
|
||||
);
|
||||
|
||||
// Basic account creation
|
||||
let john_id = store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "john".to_string(),
|
||||
description: Some("John Doe".to_string()),
|
||||
secrets: vec!["secret".to_string(), "secret2".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
vec![],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -55,11 +55,11 @@ async fn internal_directory() {
|
||||
assert_eq!(
|
||||
store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "john".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
vec![]
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await,
|
||||
Err(manage::err_exists(PrincipalField::Name, "john".to_string()))
|
||||
@@ -69,12 +69,12 @@ async fn internal_directory() {
|
||||
assert_eq!(
|
||||
store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "jane".to_string(),
|
||||
emails: vec!["jane@example.org".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
vec![]
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await,
|
||||
Err(manage::not_found("example.org".to_string()))
|
||||
@@ -121,15 +121,15 @@ async fn internal_directory() {
|
||||
// Create an account with an email address
|
||||
let jane_id = store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "jane".to_string(),
|
||||
description: Some("Jane Doe".to_string()),
|
||||
secrets: vec!["my_secret".to_string(), "my_secret2".to_string()],
|
||||
emails: vec!["jane@example.org".to_string()],
|
||||
quota: 123,
|
||||
..Default::default()
|
||||
},
|
||||
vec![],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -151,8 +151,9 @@ async fn internal_directory() {
|
||||
true
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(Principal {
|
||||
.unwrap()
|
||||
.map(|p| p.into_test()),
|
||||
Some(TestPrincipal {
|
||||
id: jane_id,
|
||||
name: "jane".to_string(),
|
||||
description: Some("Jane Doe".to_string()),
|
||||
@@ -180,13 +181,13 @@ async fn internal_directory() {
|
||||
assert_eq!(
|
||||
store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "janeth".to_string(),
|
||||
description: Some("Janeth Doe".to_string()),
|
||||
emails: vec!["jane@example.org".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
vec![]
|
||||
}
|
||||
.into()
|
||||
)
|
||||
.await,
|
||||
Err(manage::err_exists(
|
||||
@@ -198,13 +199,13 @@ async fn internal_directory() {
|
||||
// Create a mailing list
|
||||
let list_id = store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "list".to_string(),
|
||||
typ: Type::List,
|
||||
emails: vec!["list@example.org".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
vec![],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -235,8 +236,9 @@ async fn internal_directory() {
|
||||
.query(QueryBy::Name("list"), true)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Principal {
|
||||
.unwrap()
|
||||
.into_test(),
|
||||
TestPrincipal {
|
||||
name: "list".to_string(),
|
||||
id: list_id,
|
||||
typ: Type::List,
|
||||
@@ -260,25 +262,25 @@ async fn internal_directory() {
|
||||
// Create groups
|
||||
store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "sales".to_string(),
|
||||
description: Some("Sales Team".to_string()),
|
||||
typ: Type::Group,
|
||||
..Default::default()
|
||||
},
|
||||
vec![],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
store
|
||||
.create_account(
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
name: "support".to_string(),
|
||||
description: Some("Support Team".to_string()),
|
||||
typ: Type::Group,
|
||||
..Default::default()
|
||||
},
|
||||
vec![],
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -313,8 +315,9 @@ async fn internal_directory() {
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_test()
|
||||
.into_sorted(),
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
id: john_id,
|
||||
name: "john".to_string(),
|
||||
description: Some("John Doe".to_string()),
|
||||
@@ -367,8 +370,9 @@ async fn internal_directory() {
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_test()
|
||||
.into_sorted(),
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
id: john_id,
|
||||
name: "john".to_string(),
|
||||
description: Some("John Doe".to_string()),
|
||||
@@ -398,10 +402,6 @@ async fn internal_directory() {
|
||||
PrincipalValue::StringList(vec!["12345".to_string()])
|
||||
),
|
||||
PrincipalUpdate::set(PrincipalField::Quota, PrincipalValue::Integer(1024)),
|
||||
PrincipalUpdate::set(
|
||||
PrincipalField::Type,
|
||||
PrincipalValue::String("superuser".to_string())
|
||||
),
|
||||
PrincipalUpdate::remove_item(
|
||||
PrincipalField::Emails,
|
||||
PrincipalValue::String("john@example.org".to_string()),
|
||||
@@ -426,15 +426,16 @@ async fn internal_directory() {
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_test()
|
||||
.into_sorted(),
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
id: john_id,
|
||||
name: "john.doe".to_string(),
|
||||
description: Some("Johnny Doe".to_string()),
|
||||
secrets: vec!["12345".to_string()],
|
||||
emails: vec!["john.doe@example.org".to_string()],
|
||||
quota: 1024,
|
||||
typ: Type::Superuser,
|
||||
typ: Type::Individual,
|
||||
member_of: vec!["list".to_string(), "sales".to_string()],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use directory::{backend::internal::manage::ManageDirectory, Principal, QueryBy, Type};
|
||||
use directory::{backend::internal::manage::ManageDirectory, QueryBy, Type};
|
||||
use mail_send::Credentials;
|
||||
|
||||
use crate::directory::{map_account_ids, DirectoryTest};
|
||||
use crate::directory::{map_account_ids, DirectoryTest, IntoTestPrincipal, TestPrincipal};
|
||||
|
||||
#[tokio::test]
|
||||
async fn ldap_directory() {
|
||||
@@ -40,14 +40,19 @@ async fn ldap_directory() {
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_test()
|
||||
.into_sorted(),
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("john").await.unwrap().unwrap(),
|
||||
name: "john".to_string(),
|
||||
description: "John Doe".to_string().into(),
|
||||
secrets: vec!["12345".to_string()],
|
||||
typ: Type::Individual,
|
||||
member_of: map_account_ids(base_store, vec!["sales"]).await,
|
||||
member_of: map_account_ids(base_store, vec!["sales"])
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect(),
|
||||
emails: vec![
|
||||
"john@example.org".to_string(),
|
||||
"john.doe@example.org".to_string()
|
||||
@@ -68,8 +73,9 @@ async fn ldap_directory() {
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_test()
|
||||
.into_sorted(),
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("bill").await.unwrap().unwrap(),
|
||||
name: "bill".to_string(),
|
||||
description: "Bill Foobar".to_string().into(),
|
||||
@@ -102,14 +108,19 @@ async fn ldap_directory() {
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_test()
|
||||
.into_sorted(),
|
||||
Principal {
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("jane").await.unwrap().unwrap(),
|
||||
name: "jane".to_string(),
|
||||
description: "Jane Doe".to_string().into(),
|
||||
typ: Type::Individual,
|
||||
secrets: vec!["abcde".to_string()],
|
||||
member_of: map_account_ids(base_store, vec!["sales", "support"]).await,
|
||||
member_of: map_account_ids(base_store, vec!["sales", "support"])
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect(),
|
||||
emails: vec!["jane@example.org".to_string(),],
|
||||
..Default::default()
|
||||
}
|
||||
@@ -122,8 +133,9 @@ async fn ldap_directory() {
|
||||
.query(QueryBy::Name("sales"), true)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Principal {
|
||||
.unwrap()
|
||||
.into_test(),
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("sales").await.unwrap().unwrap(),
|
||||
name: "sales".to_string(),
|
||||
description: "sales".to_string().into(),
|
||||
|
||||
@@ -11,7 +11,10 @@ pub mod smtp;
|
||||
pub mod sql;
|
||||
|
||||
use common::{config::smtp::session::AddressMapping, Core};
|
||||
use directory::{backend::internal::manage::ManageDirectory, Directories};
|
||||
use directory::{
|
||||
backend::internal::{manage::ManageDirectory, PrincipalField},
|
||||
Directories, Principal, Type,
|
||||
};
|
||||
use mail_send::Credentials;
|
||||
use rustls::ServerConfig;
|
||||
use rustls_pemfile::{certs, pkcs8_private_keys};
|
||||
@@ -254,6 +257,18 @@ pub struct DirectoryTest {
|
||||
pub core: Core,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub struct TestPrincipal {
|
||||
pub id: u32,
|
||||
pub typ: Type,
|
||||
pub quota: u64,
|
||||
pub name: String,
|
||||
pub secrets: Vec<String>,
|
||||
pub emails: Vec<String>,
|
||||
pub member_of: Vec<String>,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
impl DirectoryTest {
|
||||
pub async fn new(id_store: Option<&str>) -> DirectoryTest {
|
||||
let temp_dir = TempDir::new("directory_tests", true);
|
||||
@@ -408,6 +423,61 @@ pub fn dummy_tls_acceptor() -> Arc<TlsAcceptor> {
|
||||
)))
|
||||
}
|
||||
|
||||
trait IntoTestPrincipal {
|
||||
fn into_test(self) -> TestPrincipal;
|
||||
}
|
||||
|
||||
impl IntoTestPrincipal for Principal {
|
||||
fn into_test(self) -> TestPrincipal {
|
||||
TestPrincipal::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl TestPrincipal {
|
||||
pub fn into_sorted(mut self) -> Self {
|
||||
self.member_of.sort_unstable();
|
||||
self.emails.sort_unstable();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Principal> for TestPrincipal {
|
||||
fn from(mut value: Principal) -> Self {
|
||||
Self {
|
||||
id: value.id(),
|
||||
typ: value.typ(),
|
||||
quota: value.quota(),
|
||||
name: value.take_str(PrincipalField::Name).unwrap_or_default(),
|
||||
secrets: value
|
||||
.take_str_array(PrincipalField::Secrets)
|
||||
.unwrap_or_default(),
|
||||
emails: value
|
||||
.take_str_array(PrincipalField::Emails)
|
||||
.unwrap_or_default(),
|
||||
member_of: value
|
||||
.take_str_array(PrincipalField::MemberOf)
|
||||
.unwrap_or_default(),
|
||||
/*member_of: value
|
||||
.iter_int(PrincipalField::MemberOf)
|
||||
.map(|v| v as u32)
|
||||
.collect(),*/
|
||||
description: value.take_str(PrincipalField::Description),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TestPrincipal> for Principal {
|
||||
fn from(value: TestPrincipal) -> Self {
|
||||
Principal::new(value.id, value.typ)
|
||||
.with_field(PrincipalField::Name, value.name)
|
||||
.with_field(PrincipalField::Quota, value.quota)
|
||||
.with_field(PrincipalField::Secrets, value.secrets)
|
||||
.with_field(PrincipalField::Emails, value.emails)
|
||||
.with_field(PrincipalField::MemberOf, value.member_of)
|
||||
.with_opt_field(PrincipalField::Description, value.description)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Item {
|
||||
IsAccount(String),
|
||||
@@ -500,92 +570,6 @@ impl core::fmt::Debug for Item {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// DEPRECATED - TODO: Remove
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore]
|
||||
async fn lookup_local() {
|
||||
const LOOKUP_CONFIG: &str = r#"
|
||||
[store."local/regex"]
|
||||
type = "memory"
|
||||
format = "regex"
|
||||
values = ["^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
||||
"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"]
|
||||
|
||||
[store."local/glob"]
|
||||
type = "memory"
|
||||
format = "glob"
|
||||
values = ["*@example.org", "test@*", "localhost", "*+*@*.domain.net"]
|
||||
|
||||
[store."local/list"]
|
||||
type = "memory"
|
||||
format = "list"
|
||||
values = ["abc", "xyz", "123"]
|
||||
|
||||
[store."local/suffix"]
|
||||
type = "memory"
|
||||
format = "glob"
|
||||
comment = "//"
|
||||
values = ["https://publicsuffix.org/list/public_suffix_list.dat", "fallback+file://%PATH%/public_suffix_list.dat.gz"]
|
||||
"#;
|
||||
|
||||
/*tracing::subscriber::set_global_default(
|
||||
tracing_subscriber::FmtSubscriber::builder()
|
||||
.with_max_level(tracing::Level::TRACE)
|
||||
.finish(),
|
||||
)
|
||||
.unwrap();*/
|
||||
|
||||
let mut config = utils::config::Config::new(
|
||||
&LOOKUP_CONFIG.replace(
|
||||
"%PATH%",
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.parent()
|
||||
.unwrap()
|
||||
.to_path_buf()
|
||||
.join("resources")
|
||||
.join("config")
|
||||
.join("lists")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let lookups = Stores::parse_all(&mut config).await.lookup_stores;
|
||||
|
||||
for (lookup, item, expect) in [
|
||||
("glob", "user@example.org", true),
|
||||
("glob", "test@otherdomain.org", true),
|
||||
("glob", "localhost", true),
|
||||
("glob", "john+doe@doefamily.domain.net", true),
|
||||
("glob", "john@domain.net", false),
|
||||
("glob", "example.org", false),
|
||||
("list", "abc", true),
|
||||
("list", "xyz", true),
|
||||
("list", "zzz", false),
|
||||
("regex", "user@domain.com", true),
|
||||
("regex", "127.0.0.1", true),
|
||||
("regex", "hello", false),
|
||||
("suffix", "co.uk", true),
|
||||
("suffix", "coco", false),
|
||||
] {
|
||||
assert_eq!(
|
||||
lookups
|
||||
.get(&format!("local/{lookup}"))
|
||||
.unwrap()
|
||||
.key_get::<String>(item.as_bytes().to_vec())
|
||||
.await
|
||||
.unwrap()
|
||||
.is_some(),
|
||||
expect,
|
||||
"failed for {lookup}, item {item}"
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[tokio::test]
|
||||
async fn address_mappings() {
|
||||
const MAPPINGS: &str = r#"
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use directory::{backend::internal::manage::ManageDirectory, Principal, QueryBy, Type};
|
||||
use directory::{backend::internal::manage::ManageDirectory, QueryBy, Type};
|
||||
use mail_send::Credentials;
|
||||
use store::{LookupStore, Store};
|
||||
|
||||
use crate::directory::{map_account_ids, DirectoryTest};
|
||||
use crate::directory::{map_account_ids, DirectoryTest, IntoTestPrincipal, TestPrincipal};
|
||||
|
||||
use super::DirectoryStore;
|
||||
|
||||
@@ -110,14 +110,19 @@ async fn sql_directory() {
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Principal {
|
||||
.unwrap()
|
||||
.into_test(),
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("john").await.unwrap().unwrap(),
|
||||
name: "john".to_string(),
|
||||
description: "John Doe".to_string().into(),
|
||||
secrets: vec!["12345".to_string()],
|
||||
typ: Type::Individual,
|
||||
member_of: map_account_ids(base_store, vec!["sales"]).await,
|
||||
member_of: map_account_ids(base_store, vec!["sales"])
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect(),
|
||||
emails: vec![
|
||||
"john@example.org".to_string(),
|
||||
"jdoe@example.org".to_string(),
|
||||
@@ -137,8 +142,9 @@ async fn sql_directory() {
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Principal {
|
||||
.unwrap()
|
||||
.into_test(),
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("bill").await.unwrap().unwrap(),
|
||||
name: "bill".to_string(),
|
||||
description: "Bill Foobar".to_string().into(),
|
||||
@@ -169,14 +175,19 @@ async fn sql_directory() {
|
||||
.query(QueryBy::Name("jane"), true)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Principal {
|
||||
.unwrap()
|
||||
.into_test(),
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("jane").await.unwrap().unwrap(),
|
||||
name: "jane".to_string(),
|
||||
description: "Jane Doe".to_string().into(),
|
||||
typ: Type::Individual,
|
||||
secrets: vec!["abcde".to_string()],
|
||||
member_of: map_account_ids(base_store, vec!["sales", "support"]).await,
|
||||
member_of: map_account_ids(base_store, vec!["sales", "support"])
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect(),
|
||||
emails: vec!["jane@example.org".to_string(),],
|
||||
..Default::default()
|
||||
}
|
||||
@@ -188,8 +199,9 @@ async fn sql_directory() {
|
||||
.query(QueryBy::Name("sales"), true)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Principal {
|
||||
.unwrap()
|
||||
.into_test(),
|
||||
TestPrincipal {
|
||||
id: base_store.get_account_id("sales").await.unwrap().unwrap(),
|
||||
name: "sales".to_string(),
|
||||
description: "Sales Team".to_string().into(),
|
||||
|
||||
Reference in New Issue
Block a user