fix: all users will need to havea secure/updated password to log in

Closes #7
This commit is contained in:
silver 2023-08-02 14:52:58 +01:00
parent b892326545
commit bd18ad759e

View file

@ -1,4 +1,3 @@
use dotenvy::dotenv;
use ldap3::{LdapConn, Mod};
use skynet_ldap_backend::{db_init, get_config, get_now_iso, read_csv, Accounts, Config};
use sqlx::{Pool, Sqlite};
@ -14,11 +13,12 @@ async fn main() -> tide::Result<()> {
}
async fn update(config: &Config) -> tide::Result<()> {
dotenv().ok();
let db = db_init(config).await.unwrap();
let mut users_tmp = HashSet::new();
// default user to ensure group is never empty
users_tmp.insert(String::from("compsoc"));
let mut users_tmp = HashSet::from([String::from("compsoc")]);
let mut admins_tmp = HashSet::from([String::from("compsoc")]);
let mut committee_tmp = HashSet::from([String::from("compsoc")]);
if let Ok(x) = env::var("USERS_LIFETIME") {
for user in x.split(',').collect::<Vec<&str>>() {
@ -32,22 +32,18 @@ async fn update(config: &Config) -> tide::Result<()> {
}
if let Ok(x) = env::var("USERS_ADMIN") {
let users = x.split(',').collect::<Vec<&str>>();
update_group(config, "skynet-admins", &users, true).await?;
// admins automatically get added as users
for user in users {
for user in x.split(',').collect::<Vec<&str>>() {
admins_tmp.insert(user.to_string());
users_tmp.insert(user.to_string());
}
}
// read from teh env
if let Ok(x) = env::var("USERS_COMMITTEE") {
let users = x.split(',').collect::<Vec<&str>>();
update_group(config, "skynet-committee", &users, true).await?;
// committee automatically get added as users
for user in users {
for user in x.split(',').collect::<Vec<&str>>() {
committee_tmp.insert(user.to_string());
users_tmp.insert(user.to_string());
}
}
@ -59,10 +55,15 @@ async fn update(config: &Config) -> tide::Result<()> {
}
}
// easier to work with Strings above but easier to work with &str below
let users: Vec<&str> = users_tmp.iter().map(|s| &**s).collect();
let AccountsSecure {
users,
admins,
committee,
} = get_secure(&db, &users_tmp, &admins_tmp, &committee_tmp).await;
update_group(config, "skynet-users", &users, true).await?;
update_group(config, "skynet-admins", &admins, true).await?;
update_group(config, "skynet-committee", &committee, true).await?;
Ok(())
}
@ -71,7 +72,7 @@ fn uid_to_dn(uid: &str) -> String {
format!("uid={},ou=users,dc=skynet,dc=ie", uid)
}
async fn update_group(config: &Config, group: &str, users: &[&str], replace: bool) -> tide::Result<()> {
async fn update_group(config: &Config, group: &str, users: &Vec<String>, replace: bool) -> tide::Result<()> {
if users.is_empty() {
return Ok(());
}
@ -178,3 +179,56 @@ async fn account_id_get_uid(db: &Pool<Sqlite>, id: &str) -> Option<String> {
Err(_) => None,
}
}
struct AccountsSecure {
users: Vec<String>,
admins: Vec<String>,
committee: Vec<String>,
}
async fn get_secure(db: &Pool<Sqlite>, users: &HashSet<String>, admins: &HashSet<String>, committee: &HashSet<String>) -> AccountsSecure {
// to avoid searching for teh same thing again.
let mut cache = HashSet::new();
AccountsSecure {
users: get_secure_sub(db, users, &mut cache).await,
admins: get_secure_sub(db, admins, &mut cache).await,
committee: get_secure_sub(db, committee, &mut cache).await,
}
}
async fn get_secure_sub(db: &Pool<Sqlite>, group: &HashSet<String>, cache: &mut HashSet<String>) -> Vec<String> {
let mut tmp = vec![];
for user in group {
// check the cache first
let mut add = false;
if cache.get(user).is_some() {
add = true;
} else if is_secure(db, user).await {
cache.insert(user.to_string());
add = true;
}
if add {
tmp.push(user.clone());
}
}
tmp
}
async fn is_secure(db: &Pool<Sqlite>, user: &str) -> bool {
match sqlx::query_as::<_, Accounts>(
r#"
SELECT *
FROM accounts
WHERE user == ? AND secure == 1
"#,
)
.bind(user)
.fetch_all(db)
.await
{
Ok(res) => !res.is_empty(),
Err(_) => false,
}
}