mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-22 13:29:21 +00:00
Can create new admin accounts from command line
This commit is contained in:
parent
d84b7051fb
commit
c0489613fb
@ -60,6 +60,10 @@ pub mod database_tables_names {
|
||||
|
||||
/// Forez presence table
|
||||
pub const FOREZ_PRESENCE_TABLE: &str = "forez_presence";
|
||||
|
||||
/// Administrators tables
|
||||
pub const ADMIN_LIST_TABLE: &str = "comunic_admin";
|
||||
pub const ADMIN_KEYS_TABLE: &str = "comunic_admin_key";
|
||||
}
|
||||
|
||||
/// Push Notifications Database prefix
|
||||
@ -153,6 +157,12 @@ pub const PASSWORD_RESET_TOKEN_LENGTH: usize = 255;
|
||||
/// Duration of the validity of a password reset token (6 hours)
|
||||
pub const PASSWORD_RESET_TOKEN_LIFETIME: u64 = 60 * 60 * 6;
|
||||
|
||||
/// Length of admin reset tokens
|
||||
pub const ADMIN_RESET_TOKEN_LENGTH: usize = 255;
|
||||
|
||||
/// Duration of the validity of a password reset token (1 hour)
|
||||
pub const ADMIN_RESET_TOKEN_LIFETIME: u64 = 60 * 60;
|
||||
|
||||
/// Minimum password length
|
||||
pub const PASSWORD_MIN_LENGTH: usize = 3;
|
||||
|
||||
|
41
src/data/admin.rs
Normal file
41
src/data/admin.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//! # Comunic administrator
|
||||
//!
|
||||
//! @author Pierre Hubert
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub struct AdminID(u64);
|
||||
|
||||
impl AdminID {
|
||||
pub fn new(id: u64) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NewAdmin {
|
||||
pub name: String,
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
pub struct AdminResetToken {
|
||||
pub token: String,
|
||||
pub expire: u64,
|
||||
}
|
||||
|
||||
pub struct Admin {
|
||||
pub id: AdminID,
|
||||
pub time_create: u64,
|
||||
pub name: String,
|
||||
pub email: String,
|
||||
pub reset_token: Option<AdminResetToken>,
|
||||
}
|
||||
|
||||
pub struct AdminKey {
|
||||
pub id: u64,
|
||||
pub admin_id: AdminID,
|
||||
pub name: String,
|
||||
pub key: String,
|
||||
}
|
@ -41,3 +41,4 @@ pub mod call_signal;
|
||||
pub mod new_notifications_settings;
|
||||
pub mod push_notification;
|
||||
pub mod presence;
|
||||
pub mod admin;
|
73
src/helpers/admin_account_helper.rs
Normal file
73
src/helpers/admin_account_helper.rs
Normal file
@ -0,0 +1,73 @@
|
||||
//! # Administration accounts helper
|
||||
//!
|
||||
//! @author Pierre Hubert
|
||||
|
||||
use crate::constants::{ADMIN_RESET_TOKEN_LENGTH, ADMIN_RESET_TOKEN_LIFETIME};
|
||||
use crate::constants::database_tables_names::ADMIN_LIST_TABLE;
|
||||
use crate::data::admin::{Admin, AdminID, AdminResetToken, NewAdmin};
|
||||
use crate::data::error::{ExecError, Res};
|
||||
use crate::helpers::database;
|
||||
use crate::utils::crypt_utils::rand_str;
|
||||
use crate::utils::date_utils::time;
|
||||
|
||||
/// Create a new admin account
|
||||
pub fn create(new_admin: &NewAdmin) -> Res<AdminID> {
|
||||
if find_admin_by_email(&new_admin.email).is_ok() {
|
||||
return Err(ExecError::boxed_new("An other admin account already holds the same email address!"));
|
||||
}
|
||||
|
||||
database::InsertQuery::new(ADMIN_LIST_TABLE)
|
||||
.add_u64("time_create", time())
|
||||
.add_str("name", &new_admin.name)
|
||||
.add_str("email", &new_admin.email)
|
||||
.insert_expect_result()
|
||||
.map(|i| AdminID::new(i))
|
||||
}
|
||||
|
||||
|
||||
/// Get admin information by admin email address
|
||||
pub fn find_admin_by_email(email: &str) -> Res<Admin> {
|
||||
database::QueryInfo::new(ADMIN_LIST_TABLE)
|
||||
.cond("email", email)
|
||||
.query_row(db_to_admin)
|
||||
}
|
||||
|
||||
/// Create a new reset token for an admin
|
||||
pub fn create_new_reset_token(id: AdminID) -> Res<AdminResetToken> {
|
||||
let token = AdminResetToken {
|
||||
token: rand_str(ADMIN_RESET_TOKEN_LENGTH),
|
||||
expire: time() + ADMIN_RESET_TOKEN_LIFETIME,
|
||||
};
|
||||
|
||||
database::UpdateInfo::new(ADMIN_LIST_TABLE)
|
||||
.cond_admin_id("id", id)
|
||||
.set_str("reset_token", &token.token)
|
||||
.set_u64("reset_token_expire", token.expire)
|
||||
.exec()?;
|
||||
|
||||
Ok(token)
|
||||
}
|
||||
|
||||
/// Turn a database entry into an admin structure
|
||||
fn db_to_admin(row: &database::RowResult) -> Res<Admin> {
|
||||
let reset_token_expire = row.get_optional_u64("reset_token_expire")?
|
||||
.unwrap_or(0);
|
||||
|
||||
let reset_token = if reset_token_expire < time() {
|
||||
None
|
||||
} else {
|
||||
Some(AdminResetToken {
|
||||
token: row.get_str("reset_token")?,
|
||||
expire: row.get_u64("reset_token_expire")?,
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
Ok(Admin {
|
||||
id: row.get_admin_id("id")?,
|
||||
time_create: row.get_u64("time_create")?,
|
||||
name: row.get_str("name")?,
|
||||
email: row.get_str("email")?,
|
||||
reset_token,
|
||||
})
|
||||
}
|
@ -8,6 +8,7 @@ use chrono::{TimeZone, Utc};
|
||||
use mysql::{Binary, Pool, ResultSet, Value};
|
||||
use mysql::prelude::Queryable;
|
||||
|
||||
use crate::data::admin::AdminID;
|
||||
use crate::data::config::{conf, DatabaseConfig};
|
||||
use crate::data::conversation::ConvID;
|
||||
use crate::data::error::{ExecError, ResultBoxError};
|
||||
@ -376,6 +377,11 @@ impl<'a> RowResult<'a> {
|
||||
Ok(UserID::new(self.get_u64(name)?))
|
||||
}
|
||||
|
||||
/// Get the ID of an admin included in the request
|
||||
pub fn get_admin_id(&self, name: &str) -> ResultBoxError<AdminID> {
|
||||
Ok(AdminID::new(self.get_u64(name)?))
|
||||
}
|
||||
|
||||
/// Get the ID of a group included in the response
|
||||
pub fn get_group_id(&self, name: &str) -> ResultBoxError<GroupID> {
|
||||
Ok(GroupID::new(self.get_u64(name)?))
|
||||
@ -903,6 +909,12 @@ impl UpdateInfo {
|
||||
self
|
||||
}
|
||||
|
||||
/// Filter with an admin id
|
||||
pub fn cond_admin_id(mut self, name: &str, val: AdminID) -> Self {
|
||||
self.cond.insert(name.to_string(), Value::UInt(val.id()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Filter with a group id
|
||||
pub fn cond_group_id(mut self, name: &str, val: &GroupID) -> UpdateInfo {
|
||||
self.cond.insert(name.to_string(), Value::UInt(val.id()));
|
||||
|
@ -22,3 +22,4 @@ pub mod push_notifications_helper;
|
||||
pub mod independent_push_notifications_service_helper;
|
||||
pub mod firebase_notifications_helper;
|
||||
pub mod forez_presence_helper;
|
||||
pub mod admin_account_helper;
|
32
src/main.rs
32
src/main.rs
@ -1,8 +1,9 @@
|
||||
use comunic_server::{cleanup_thread, server};
|
||||
use comunic_server::data::admin::NewAdmin;
|
||||
use comunic_server::data::config::{conf, Config};
|
||||
use comunic_server::data::error::Res;
|
||||
use comunic_server::data::user::UserID;
|
||||
use comunic_server::helpers::{account_helper, database};
|
||||
use comunic_server::helpers::{account_helper, admin_account_helper, database};
|
||||
use comunic_server::utils::date_utils::current_year;
|
||||
|
||||
type MainActionFunction = Res;
|
||||
@ -38,7 +39,15 @@ fn get_actions() -> Vec<Action> {
|
||||
description: "Create a password reset URL for a user".to_string(),
|
||||
arguments: vec!["user_id".to_string()],
|
||||
function: Box::new(reset_password),
|
||||
}
|
||||
},
|
||||
|
||||
// Create a new administrator
|
||||
Action {
|
||||
name: "create_admin".to_string(),
|
||||
description: "Create a new administrator account".to_string(),
|
||||
arguments: vec!["name".to_string(), "email".to_string()],
|
||||
function: Box::new(create_admin),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@ -144,3 +153,22 @@ fn reset_password(args: Vec<String>) -> Res {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_admin(args: Vec<String>) -> Res {
|
||||
let new_admin = NewAdmin {
|
||||
name: args[0].to_string(),
|
||||
email: args[1].to_string(),
|
||||
};
|
||||
|
||||
if !mailchecker::is_valid(&new_admin.email) {
|
||||
eprintln!("Specified email address is not valid!");
|
||||
std::process::exit(-1);
|
||||
}
|
||||
|
||||
let id = admin_account_helper::create(&new_admin)
|
||||
.expect("Failed to create account!");
|
||||
|
||||
println!("* New admin ID: {}", id.id());
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user