Merge branch '#7_secure_password' into 'main'
Ensure users have a secure password to be added to groups Closes #7 See merge request compsoc1/skynet/ldap/backend!4
This commit is contained in:
commit
91ee2a246e
1 changed files with 69 additions and 15 deletions
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue