Set of administration tools for 42l's infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

322 lines
9.3 KiB

use crate::db_structs::*;
use crate::globals::*;
use crate::helper_structs::*;
use crate::term::*;
use crate::texts::*;
use crate::tools::*;
use chrono::offset::TimeZone;
use chrono::Utc;
use crossterm::style::{Colorize, Styler};
use std::{thread, time};
pub fn users_main(fast_config: FastConfig) -> usize {
display_template();
display_menu(&USERS_MAIN_TXT, fast_config)
}
pub fn users_panel(fast_config: FastConfig) -> usize {
display_template();
print_title(&USERS_MAIN_TXT, 0);
let username = input_line("Please enter a member name:")
.as_str()
.trim()
.to_lowercase();
if let Some(user) = User::get(&username) {
return display_userpanel(FastConfig {
user: Some(&user),
domain: fast_config.domain,
mail_cache: fast_config.mail_cache,
});
}
println!("User not found.");
thread::sleep(time::Duration::from_millis(1000));
users_main(fast_config)
}
pub fn users_list(fast_config: FastConfig) -> usize {
display_template();
print_title(&USERS_MAIN_TXT, 1);
let all_users = User::get_all();
println!(
"{:<5}{:<25}{:<12}{:>6}{:>6}{:>6}{:>6} {:>15}",
"ID", "Username", "Status", "NL", "AG", "Gitea", "NC", "Adhesion status"
);
let (mut nl_count, mut ag_count, mut gitea_count, mut nc_count) = (0, 0, 0, 0);
let (mut adh_count, mut adh_total) = (0, 0);
for user in all_users.iter() {
let display = DisplayUser::from_user(user);
println!(
"{:<5}{:<25}{:<12}{:>6}{:>6}{:>6}{:>6} {:>15}",
display.id,
display.username_plain,
display.status,
display.has_sub_newsletter,
display.has_sub_ag,
display.has_gitea_account,
display.has_nextcloud_account,
display.adh_status
);
if user.sub_newsletter {
nl_count += 1;
}
if user.sub_ag {
ag_count += 1;
}
if user.gitea_id.is_some() {
gitea_count += 1;
}
if user.nextcloud_username.is_some() {
nc_count += 1;
}
if display.adh_days.is_some() {
adh_total += 1;
}
if display.adh_days.is_some() && display.adh_days.unwrap() < 0 {
adh_count += 1;
}
}
// stats: printing total
println!(
"\n{:<42}{:>6}{:>6}{:>6}{:>6}",
"Total".bold().blue(),
nl_count,
ag_count,
gitea_count,
nc_count
);
// stats: printing total (%)
println!(
"{:<42}{:>4} %{:>4} %{:>4} %{:>4} %",
"Total (%)".bold().blue(),
100 * nl_count / all_users.len(),
100 * ag_count / all_users.len(),
100 * gitea_count / all_users.len(),
100 * nc_count / all_users.len()
);
println!(
"\nUp-to-date subscribers: {} ({} % all subscribers, {} % total)",
adh_count,
adh_count * 100 / adh_total,
adh_count * 100 / all_users.len()
);
println!(
"Total subscribers: {} ({} % total)",
adh_total,
adh_total * 100 / all_users.len()
);
input_line("Press Enter to continue...");
users_main(fast_config)
}
pub fn display_userpanel(fast_config: FastConfig) -> usize {
// display user + domains they're owning, mail count, alias count
let fast_config = fast_config;
let du = DisplayUser::from_user(&fast_config.user.unwrap());
let adhlist = Adhesions::adhesions_by_user(du.id);
let first_adhesion = adh_date_format_opt(du.adhesions.first());
let last_adhesion = adh_date_format_opt(du.adhesions.last());
let owned_domains = EmailDomains::owned_by_user(du.id);
let owned_domains = if !owned_domains.is_empty() {
let mut domainlist = String::new();
for domain in owned_domains {
domainlist.push_str(&format!("\n - {}", domain.fqdn));
}
domainlist
} else {
"None".to_owned()
};
let allowed_domains = EmailDomains::get_allowed_domains(du.id);
let allowed_domains = if !allowed_domains.is_empty() {
let mut domainlist = String::new();
for domain in allowed_domains {
domainlist.push_str(&format!("\n - {}", domain.fqdn));
}
domainlist
} else {
"None".to_owned()
};
println!(
r#"
id: {}
Username: {}
Password set: {}
AG subscription: {}
Newsletter subscription: {}
Status: {}
Email quota: {} / {}
Alias quota: {} / {}
Gitea account: {}
Nextcloud account: {}
First subscription: {}
Last subscription: {}
Subscription count: {}
Subscription state: {}
Owned domains: {}
Allowed domains: {}
"#,
du.id,
du.username_plain,
du.password_set,
du.has_sub_ag,
du.has_sub_newsletter,
du.status,
Email::count_by_user(du.id),
du.max_emails,
Alias::count_by_user(du.id),
du.max_alias,
du.has_gitea_account,
du.has_nextcloud_account,
first_adhesion,
last_adhesion,
adhlist.len(),
du.adh_status,
owned_domains,
allowed_domains
);
println!("Available actions:");
display_menu(&USERS_PANEL_TXT, fast_config)
}
pub fn user_addsub(fast_config: FastConfig) -> usize {
let sub_date_default = Utc::now().naive_utc();
let sub_date;
loop {
let sub_date_input = input_line(&format!(
"Enter the subscription date, YYYY-MM-DD format [{}]:",
sub_date_default.format("%Y-%m-%d")
));
let sub_date_input = sub_date_input.trim();
if sub_date_input.is_empty() {
sub_date = sub_date_default;
break;
} else if let Ok(sub_date_parsed) =
Utc.datetime_from_str(&format!("{} 00:00:00", sub_date_input), "%Y-%m-%d %X")
{
sub_date = sub_date_parsed.naive_utc();
break;
} else {
println!("Invalid input, please retry.");
}
}
Adhesions::add_subscription(fast_config.user.unwrap().id, sub_date.date());
println!("{}", "Entry updated.".green().bold());
thread::sleep(time::Duration::from_millis(1000));
users_main(fast_config)
}
pub fn user_remsub(fast_config: FastConfig) -> usize {
let adh_list = Adhesions::adhesions_by_user(fast_config.user.unwrap().id);
println!("Please select a subscription to remove:");
for adh in &adh_list {
println!("{}\t\t{}", adh.id, adh.adh_date);
}
let adh_input_num;
loop {
let adh_input = input_line("Your choice:");
let adh_input = adh_input.trim();
if let Ok(num) = adh_input.parse::<i32>() {
if adh_list.iter().filter(|adh_i| adh_i.id == num).count() == 1 {
adh_input_num = num;
break;
}
}
println!("Subscription id not found.");
}
Adhesions::del_by_id(adh_input_num);
println!("{}", "Entry updated.".green().bold());
thread::sleep(time::Duration::from_millis(1000));
users_main(fast_config)
}
pub fn user_edit_emails(fast_config: FastConfig) -> usize {
let u = fast_config.user.unwrap();
let question = "How many emails should the user be allowed to use? (Default: 5)";
let email_input_num = loop {
match input_line(question).trim().parse::<i16>() {
Ok(num) => break num,
Err(_) => continue,
/*Err(_) => continue,*/
}
};
u.edit_max_emails(email_input_num);
println!("{}", "Entry updated.".green().bold());
thread::sleep(time::Duration::from_millis(1000));
users_main(fast_config)
}
pub fn user_edit_aliases(fast_config: FastConfig) -> usize {
let u = fast_config.user.unwrap();
let question = "How many aliases should the user be allowed to use? (Default: 60)";
let alias_input_num = loop {
match input_line(question).trim().parse::<i16>() {
Ok(num) => break num,
// if e.kind() == IntParseError::Empty --> unstable :(
Err(_) => continue,
}
};
u.edit_max_alias(alias_input_num);
println!("{}", "Entry updated.".green().bold());
thread::sleep(time::Duration::from_millis(1000));
users_main(fast_config)
}
pub fn user_export_email(fast_config: FastConfig) -> usize {
let user = fast_config.user.unwrap();
println!("Here's the user's encrypted email:");
println!("\n{}|{}\n", user.id, base64::encode(&user.notify_email));
input_line("Press Enter to continue...");
users_main(fast_config)
}
pub fn user_delete(fast_config: FastConfig) -> usize {
let user = fast_config.user.unwrap();
println!(
r#"User deletion can't be cancelled. It will remove:
- All their mailboxes and aliases
- Access to domains they have access to
- All the domains they own, and all granted access to those domains to the other users"#
);
println!("The mailboxes and aliases must be removed manually in the mailserver container");
if input_line("Are you SURE? [y/N]").trim().to_lowercase() == "y"
&& input_line("REALLY SURE? I'm not joking. [y/N]")
.trim()
.to_lowercase()
== "y"
{
println!("Now deleting {}.", user.username_plain);
user.delete();
} else {
println!("Operation cancelled.");
}
input_line("Press Enter to continue...");
users_main(fast_config)
}