use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub id: String,
pub username: String,
pub email: String,
pub display_name: String,
pub roles: HashSet<String>,
pub permissions: HashSet<Permission>,
pub groups: HashSet<String>,
pub attributes: HashMap<String, String>,
pub created_at: u64,
pub last_login: Option<u64>,
pub is_active: bool,
}
impl User {
pub fn new(id: String, username: String, email: String, display_name: String) -> Self {
Self {
id,
username,
email,
display_name,
roles: HashSet::new(),
permissions: HashSet::new(),
groups: HashSet::new(),
attributes: HashMap::new(),
created_at: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
last_login: None,
is_active: true,
}
}
pub fn add_role(&mut self, role: String) {
self.roles.insert(role);
}
pub fn remove_role(&mut self, role: &str) {
self.roles.remove(role);
}
pub fn has_role(&self, role: &str) -> bool {
self.roles.contains(role)
}
pub fn add_permission(&mut self, permission: Permission) {
self.permissions.insert(permission);
}
pub fn remove_permission(&mut self, permission: &Permission) {
self.permissions.remove(permission);
}
pub fn has_permission(&self, permission: &Permission) -> bool {
self.permissions.contains(permission)
}
pub fn add_group(&mut self, group: String) {
self.groups.insert(group);
}
pub fn remove_group(&mut self, group: &str) {
self.groups.remove(group);
}
pub fn in_group(&self, group: &str) -> bool {
self.groups.contains(group)
}
pub fn set_attribute(&mut self, key: String, value: String) {
self.attributes.insert(key, value);
}
pub fn get_attribute(&self, key: &str) -> Option<&String> {
self.attributes.get(key)
}
pub fn update_last_login(&mut self) {
self.last_login = Some(
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
);
}
pub fn activate(&mut self) {
self.is_active = true;
}
pub fn deactivate(&mut self) {
self.is_active = false;
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Permission {
ViewCharts,
CreateCharts,
EditCharts,
DeleteCharts,
ViewData,
EditData,
DeleteData,
ExportData,
ImportData,
ManageUsers,
ManageRoles,
ManageSystem,
ViewAuditLogs,
ExportPNG,
ExportSVG,
ExportPDF,
ExportHTML,
Custom(String),
}
impl Permission {
pub fn as_str(&self) -> &str {
match self {
Permission::ViewCharts => "view_charts",
Permission::CreateCharts => "create_charts",
Permission::EditCharts => "edit_charts",
Permission::DeleteCharts => "delete_charts",
Permission::ViewData => "view_data",
Permission::EditData => "edit_data",
Permission::DeleteData => "delete_data",
Permission::ExportData => "export_data",
Permission::ImportData => "import_data",
Permission::ManageUsers => "manage_users",
Permission::ManageRoles => "manage_roles",
Permission::ManageSystem => "manage_system",
Permission::ViewAuditLogs => "view_audit_logs",
Permission::ExportPNG => "export_png",
Permission::ExportSVG => "export_svg",
Permission::ExportPDF => "export_pdf",
Permission::ExportHTML => "export_html",
Permission::Custom(name) => name,
}
}
pub fn custom(name: impl Into<String>) -> Self {
Self::Custom(name.into())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Credentials {
pub credential_type: CredentialType,
pub username: Option<String>,
pub password: Option<String>,
pub token: Option<String>,
pub additional_data: HashMap<String, String>,
}
impl Credentials {
pub fn username_password(username: String, password: String) -> Self {
Self {
credential_type: CredentialType::UsernamePassword,
username: Some(username),
password: Some(password),
token: None,
additional_data: HashMap::new(),
}
}
pub fn bearer_token(token: String) -> Self {
Self {
credential_type: CredentialType::BearerToken,
username: None,
password: None,
token: Some(token),
additional_data: HashMap::new(),
}
}
pub fn api_key(api_key: String) -> Self {
Self {
credential_type: CredentialType::ApiKey,
username: None,
password: None,
token: Some(api_key),
additional_data: HashMap::new(),
}
}
pub fn add_data(&mut self, key: String, value: String) {
self.additional_data.insert(key, value);
}
pub fn get_data(&self, key: &str) -> Option<&String> {
self.additional_data.get(key)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CredentialType {
UsernamePassword,
BearerToken,
ApiKey,
OAuth2,
SAML,
Certificate,
Biometric,
}
impl CredentialType {
pub fn as_str(&self) -> &str {
match self {
CredentialType::UsernamePassword => "username_password", CredentialType::BearerToken => "bearer_token", CredentialType::ApiKey => "api_key", CredentialType::OAuth2 => "oauth2",
CredentialType::SAML => "saml",
CredentialType::Certificate => "certificate",
CredentialType::Biometric => "biometric",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthenticationResult {
pub success: bool,
pub user: Option<User>,
pub token: Option<String>,
pub expires_at: Option<u64>,
pub error_message: Option<String>,
}
impl AuthenticationResult {
pub fn success(user: User, token: String, expires_at: u64) -> Self {
Self {
success: true,
user: Some(user),
token: Some(token),
expires_at: Some(expires_at),
error_message: None,
}
}
pub fn failure(error_message: String) -> Self {
Self {
success: false,
user: None,
token: None,
expires_at: None,
error_message: Some(error_message),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorizationContext {
pub user: User,
pub resource: Resource,
pub action: Action,
pub environment: HashMap<String, String>,
}
impl AuthorizationContext {
pub fn new(user: User, resource: Resource, action: Action) -> Self {
Self {
user,
resource,
action,
environment: HashMap::new(),
}
}
pub fn add_environment(&mut self, key: String, value: String) {
self.environment.insert(key, value);
}
pub fn get_environment(&self, key: &str) -> Option<&String> {
self.environment.get(key)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Resource {
Chart(String),
Data(String),
User(String),
Role(String),
System,
AuditLog,
Export(String),
Import(String),
Custom(String),
}
impl Resource {
pub fn as_string(&self) -> String {
match self {
Resource::Chart(id) => format!("chart:{}", id),
Resource::Data(id) => format!("data:{}", id),
Resource::User(id) => format!("user:{}", id),
Resource::Role(id) => format!("role:{}", id),
Resource::System => "system".to_string(),
Resource::AuditLog => "audit_log".to_string(),
Resource::Export(id) => format!("export:{}", id),
Resource::Import(id) => format!("import:{}", id),
Resource::Custom(name) => name.clone(),
}
}
pub fn custom(name: impl Into<String>) -> Self {
Self::Custom(name.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Action {
Read,
Write,
Create,
Delete,
Execute,
Export,
Import,
Manage,
Custom(String),
}
impl Action {
pub fn as_str(&self) -> &str {
match self {
Action::Read => "read",
Action::Write => "write",
Action::Create => "create",
Action::Delete => "delete",
Action::Execute => "execute",
Action::Export => "export",
Action::Import => "import",
Action::Manage => "manage",
Action::Custom(name) => name,
}
}
pub fn custom(name: impl Into<String>) -> Self {
Self::Custom(name.into())
}
}