mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-26 07:19:22 +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
|
/// Forez presence table
|
||||||
pub const FOREZ_PRESENCE_TABLE: &str = "forez_presence";
|
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
|
/// 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)
|
/// Duration of the validity of a password reset token (6 hours)
|
||||||
pub const PASSWORD_RESET_TOKEN_LIFETIME: u64 = 60 * 60 * 6;
|
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
|
/// Minimum password length
|
||||||
pub const PASSWORD_MIN_LENGTH: usize = 3;
|
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 new_notifications_settings;
|
||||||
pub mod push_notification;
|
pub mod push_notification;
|
||||||
pub mod presence;
|
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::{Binary, Pool, ResultSet, Value};
|
||||||
use mysql::prelude::Queryable;
|
use mysql::prelude::Queryable;
|
||||||
|
|
||||||
|
use crate::data::admin::AdminID;
|
||||||
use crate::data::config::{conf, DatabaseConfig};
|
use crate::data::config::{conf, DatabaseConfig};
|
||||||
use crate::data::conversation::ConvID;
|
use crate::data::conversation::ConvID;
|
||||||
use crate::data::error::{ExecError, ResultBoxError};
|
use crate::data::error::{ExecError, ResultBoxError};
|
||||||
@ -376,6 +377,11 @@ impl<'a> RowResult<'a> {
|
|||||||
Ok(UserID::new(self.get_u64(name)?))
|
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
|
/// Get the ID of a group included in the response
|
||||||
pub fn get_group_id(&self, name: &str) -> ResultBoxError<GroupID> {
|
pub fn get_group_id(&self, name: &str) -> ResultBoxError<GroupID> {
|
||||||
Ok(GroupID::new(self.get_u64(name)?))
|
Ok(GroupID::new(self.get_u64(name)?))
|
||||||
@ -903,6 +909,12 @@ impl UpdateInfo {
|
|||||||
self
|
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
|
/// Filter with a group id
|
||||||
pub fn cond_group_id(mut self, name: &str, val: &GroupID) -> UpdateInfo {
|
pub fn cond_group_id(mut self, name: &str, val: &GroupID) -> UpdateInfo {
|
||||||
self.cond.insert(name.to_string(), Value::UInt(val.id()));
|
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 independent_push_notifications_service_helper;
|
||||||
pub mod firebase_notifications_helper;
|
pub mod firebase_notifications_helper;
|
||||||
pub mod forez_presence_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::{cleanup_thread, server};
|
||||||
|
use comunic_server::data::admin::NewAdmin;
|
||||||
use comunic_server::data::config::{conf, Config};
|
use comunic_server::data::config::{conf, Config};
|
||||||
use comunic_server::data::error::Res;
|
use comunic_server::data::error::Res;
|
||||||
use comunic_server::data::user::UserID;
|
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;
|
use comunic_server::utils::date_utils::current_year;
|
||||||
|
|
||||||
type MainActionFunction = Res;
|
type MainActionFunction = Res;
|
||||||
@ -38,7 +39,15 @@ fn get_actions() -> Vec<Action> {
|
|||||||
description: "Create a password reset URL for a user".to_string(),
|
description: "Create a password reset URL for a user".to_string(),
|
||||||
arguments: vec!["user_id".to_string()],
|
arguments: vec!["user_id".to_string()],
|
||||||
function: Box::new(reset_password),
|
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(())
|
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