mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
- Add lightweight SMTP server support using `lettre` and `tokio`. - Implement `DATA_SMTP_INGEST` permission check for inbound mail. - Support real-time email archiving via SMTP protocol. - Integrate with existing EML index manager for automated indexing.
248 lines
8.8 KiB
Rust
248 lines
8.8 KiB
Rust
//
|
|
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
|
//
|
|
// This file is part of the Bichon Email Archiving Project
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use std::{
|
|
collections::{BTreeSet, HashSet},
|
|
sync::LazyLock,
|
|
};
|
|
|
|
use crate::{
|
|
modules::{
|
|
error::{code::ErrorCode, BichonResult},
|
|
users::role::RoleType,
|
|
},
|
|
raise_error,
|
|
};
|
|
|
|
pub static VALID_PERMISSION_SET: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
|
|
Permission::all_permissions()
|
|
.into_iter()
|
|
.map(|(key, _)| key)
|
|
.collect()
|
|
});
|
|
|
|
pub struct Permission;
|
|
|
|
impl Permission {
|
|
// ----------------------------------------------------------------------
|
|
// 1. Global Management Permissions (System, Users, Tokens)
|
|
// ----------------------------------------------------------------------
|
|
|
|
/// Basic platform access. Required for any user to log in and access the dashboard.
|
|
/// This provides no administrative powers.
|
|
pub const SYSTEM_ACCESS: &str = "system:access";
|
|
|
|
/// Manage core system configurations (OAuth Client ID/Secret, Proxy settings).
|
|
pub const ROOT: &str = "system:root";
|
|
|
|
/// Create, modify, and delete all users and their roles (Admin only).
|
|
pub const USER_MANAGE: &str = "user:manage";
|
|
|
|
/// View the minimal user list, basic user profiles,
|
|
/// including visibility into account-level roles (Managers and Admins).
|
|
pub const USER_VIEW: &str = "user:view";
|
|
|
|
/// View and revoke all access tokens in the system.
|
|
pub const TOKEN_MANAGE: &str = "token:manage";
|
|
|
|
/// Create new email account connections.
|
|
pub const ACCOUNT_CREATE: &str = "account:create";
|
|
|
|
// ----------------------------------------------------------------------
|
|
// 2. Global "ALL" Scoped Permissions (Reserved for Admin)
|
|
// ----------------------------------------------------------------------
|
|
|
|
/// Manage configuration for all accounts (Global control).
|
|
pub const ACCOUNT_MANAGE_ALL: &str = "account:manage:all";
|
|
|
|
/// Read mail data from all accounts (Search, view messages).
|
|
pub const DATA_READ_ALL: &str = "data:read:all";
|
|
|
|
/// Download raw EML/MIME files from all accounts.
|
|
pub const DATA_RAW_DOWNLOAD_ALL: &str = "data:raw:download:all";
|
|
|
|
/// Delete messages from all accounts.
|
|
pub const DATA_DELETE_ALL: &str = "data:delete:all";
|
|
|
|
/// Manage metadata (e.g., tags, categories, notes) for messages in ALL email accounts.
|
|
pub const DATA_MANAGE_ALL: &str = "data:manage:all";
|
|
|
|
/// Export messages in batches from all accounts.
|
|
pub const DATA_EXPORT_BATCH_ALL: &str = "data:export:batch:all";
|
|
|
|
// ----------------------------------------------------------------------
|
|
// 3. Scoped/Limited Permissions (Manager & Viewer)
|
|
// Authorization requires checking the user's Account Access List (ACL)
|
|
// ----------------------------------------------------------------------
|
|
|
|
/// Manage (modify/delete/sync) configuration for a specific set of accounts.
|
|
pub const ACCOUNT_MANAGE: &str = "account:manage";
|
|
|
|
/// Read details and sync status for a specific set of accounts.
|
|
pub const ACCOUNT_READ_DETAILS: &str = "account:read_details";
|
|
|
|
/// Manage mail data metadata (e.g., updating tags, adding notes)
|
|
/// for specific accounts.
|
|
pub const DATA_MANAGE: &str = "data:manage";
|
|
|
|
/// Read mail data (Search, view) from a specific set of accounts.
|
|
pub const DATA_READ: &str = "data:read";
|
|
|
|
/// Download raw EML/MIME files from a specific set of accounts.
|
|
pub const DATA_RAW_DOWNLOAD: &str = "data:raw:download";
|
|
|
|
/// Delete messages from a specific set of accounts.
|
|
pub const DATA_DELETE: &str = "data:delete";
|
|
|
|
/// Export messages in batches from a specific set of accounts.
|
|
pub const DATA_EXPORT_BATCH: &str = "data:export:batch";
|
|
|
|
/// Import EML/PST data into a SPECIFIC account.
|
|
/// Authorization requires checking access to the target account_id.
|
|
pub const DATA_IMPORT_BATCH: &str = "data:import:batch";
|
|
|
|
/// Allow SMTP ingestion into SPECIFIC accounts.
|
|
pub const DATA_SMTP_INGEST: &str = "data:smtp:ingest";
|
|
|
|
pub fn global_permissions() -> Vec<(&'static str, &'static str)> {
|
|
vec![
|
|
(
|
|
Self::SYSTEM_ACCESS,
|
|
"Basic platform access for dashboard and personal settings.",
|
|
),
|
|
(Self::ROOT, "Full system access and configuration."),
|
|
(Self::USER_MANAGE, "Create, update, and delete users."),
|
|
(
|
|
Self::USER_VIEW,
|
|
"Read-only access to user list and profiles.",
|
|
),
|
|
(Self::TOKEN_MANAGE, "View and revoke all active API tokens."),
|
|
(
|
|
Self::ACCOUNT_CREATE,
|
|
"Connect new email accounts to the system.",
|
|
),
|
|
(
|
|
Self::ACCOUNT_MANAGE_ALL,
|
|
"Manage configurations for all email accounts.",
|
|
),
|
|
(
|
|
Self::DATA_READ_ALL,
|
|
"Search and read messages across all accounts.",
|
|
),
|
|
(
|
|
Self::DATA_MANAGE_ALL,
|
|
"Manage metadata and tags for all accounts.",
|
|
),
|
|
(
|
|
Self::DATA_RAW_DOWNLOAD_ALL,
|
|
"Download raw EML data from any account.",
|
|
),
|
|
(
|
|
Self::DATA_DELETE_ALL,
|
|
"Permanently delete messages from any account.",
|
|
),
|
|
(
|
|
Self::DATA_EXPORT_BATCH_ALL,
|
|
"Export bulk message data from all accounts.",
|
|
),
|
|
]
|
|
}
|
|
|
|
pub fn account_permissions() -> Vec<(&'static str, &'static str)> {
|
|
vec![
|
|
(
|
|
Self::ACCOUNT_MANAGE,
|
|
"Update or sync settings for authorized accounts.",
|
|
),
|
|
(
|
|
Self::ACCOUNT_READ_DETAILS,
|
|
"View status and details of authorized accounts.",
|
|
),
|
|
(
|
|
Self::DATA_READ,
|
|
"Read messages from authorized email accounts.",
|
|
),
|
|
(
|
|
Self::DATA_MANAGE,
|
|
"Manage tags and metadata for authorized accounts.",
|
|
),
|
|
(
|
|
Self::DATA_RAW_DOWNLOAD,
|
|
"Download raw EML files from authorized accounts.",
|
|
),
|
|
(
|
|
Self::DATA_DELETE,
|
|
"Delete messages from authorized email accounts.",
|
|
),
|
|
(
|
|
Self::DATA_EXPORT_BATCH,
|
|
"Export messages from authorized accounts.",
|
|
),
|
|
(
|
|
Self::DATA_IMPORT_BATCH,
|
|
"Import external EML/PST data into authorized accounts.",
|
|
),
|
|
(
|
|
Self::DATA_SMTP_INGEST,
|
|
"Receive and archive emails via SMTP for authorized accounts.",
|
|
),
|
|
]
|
|
}
|
|
|
|
pub fn all_permissions() -> Vec<(&'static str, &'static str)> {
|
|
let mut all = Self::global_permissions();
|
|
all.extend(Self::account_permissions());
|
|
all
|
|
}
|
|
|
|
fn is_account_permission(perm: &str) -> bool {
|
|
Self::account_permissions().iter().any(|(p, _)| *p == perm)
|
|
}
|
|
|
|
fn is_global_permission(perm: &str) -> bool {
|
|
Self::global_permissions().iter().any(|(p, _)| *p == perm)
|
|
}
|
|
|
|
pub fn validate_role_permissions(
|
|
role_type: &RoleType,
|
|
permissions: &BTreeSet<String>,
|
|
) -> BichonResult<()> {
|
|
for p in permissions {
|
|
match role_type {
|
|
RoleType::Global => {
|
|
if !Self::is_global_permission(p) {
|
|
return Err(raise_error!(
|
|
format!("Permission '{}' is not a valid Global permission", p),
|
|
ErrorCode::InvalidParameter
|
|
));
|
|
}
|
|
}
|
|
RoleType::Account => {
|
|
if !Self::is_account_permission(p) {
|
|
return Err(raise_error!(
|
|
format!("Permission '{}' is not a valid Account permission", p),
|
|
ErrorCode::InvalidParameter
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|