mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-22 21:39:21 +00:00
Start to log administrator actions
This commit is contained in:
parent
81d6996f01
commit
5a13d7beb3
@ -296,3 +296,11 @@ CREATE TABLE `comunic_admin_roles` (
|
|||||||
`role_id` VARCHAR(25) NULL,
|
`role_id` VARCHAR(25) NULL,
|
||||||
`time_insert` INT NULL,
|
`time_insert` INT NULL,
|
||||||
PRIMARY KEY (`id`));
|
PRIMARY KEY (`id`));
|
||||||
|
|
||||||
|
CREATE TABLE `comunic_admin_log` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`admin_id` INT NULL,
|
||||||
|
`ip` VARCHAR(40) NULL,
|
||||||
|
`time` INT NULL,
|
||||||
|
`action` VARCHAR(100) NULL,
|
||||||
|
PRIMARY KEY (`id`));
|
||||||
|
@ -22,3 +22,11 @@ CREATE TABLE `comunic_admin_roles` (
|
|||||||
`role_id` VARCHAR(25) NULL,
|
`role_id` VARCHAR(25) NULL,
|
||||||
`time_insert` INT NULL,
|
`time_insert` INT NULL,
|
||||||
PRIMARY KEY (`id`));
|
PRIMARY KEY (`id`));
|
||||||
|
|
||||||
|
CREATE TABLE `comunic_admin_log` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`admin_id` INT NULL,
|
||||||
|
`ip` VARCHAR(40) NULL,
|
||||||
|
`time` INT NULL,
|
||||||
|
`action` VARCHAR(100) NULL,
|
||||||
|
PRIMARY KEY (`id`));
|
||||||
|
@ -65,6 +65,7 @@ pub mod database_tables_names {
|
|||||||
pub const ADMIN_LIST_TABLE: &str = "comunic_admin";
|
pub const ADMIN_LIST_TABLE: &str = "comunic_admin";
|
||||||
pub const ADMIN_KEYS_TABLE: &str = "comunic_admin_key";
|
pub const ADMIN_KEYS_TABLE: &str = "comunic_admin_key";
|
||||||
pub const ADMIN_ROLES_TABLE: &str = "comunic_admin_roles";
|
pub const ADMIN_ROLES_TABLE: &str = "comunic_admin_roles";
|
||||||
|
pub const ADMIN_LOGS_TABLE: &str = "comunic_admin_log";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push Notifications Database prefix
|
/// Push Notifications Database prefix
|
||||||
|
@ -9,20 +9,26 @@ use crate::api_data::admin::admin_id_api::AdminIDAPI;
|
|||||||
use crate::api_data::admin::admin_info_api::AdminInfoAPI;
|
use crate::api_data::admin::admin_info_api::AdminInfoAPI;
|
||||||
use crate::api_data::admin::admin_res_create_account::AdminResCreateAccount;
|
use crate::api_data::admin::admin_res_create_account::AdminResCreateAccount;
|
||||||
use crate::api_data::admin::admin_res_create_reset_token::AdminResCreateResetToken;
|
use crate::api_data::admin::admin_res_create_reset_token::AdminResCreateResetToken;
|
||||||
|
use crate::constants::admin::AdminRole;
|
||||||
use crate::data::admin::{NewAdmin, NewAdminGeneralSettings};
|
use crate::data::admin::{NewAdmin, NewAdminGeneralSettings};
|
||||||
|
use crate::data::admin_action_log::AdminAction;
|
||||||
use crate::data::base_request_handler::BaseRequestHandler;
|
use crate::data::base_request_handler::BaseRequestHandler;
|
||||||
use crate::data::http_request_handler::HttpRequestHandler;
|
use crate::data::http_request_handler::HttpRequestHandler;
|
||||||
use crate::helpers::{admin_access_token_helper, admin_account_helper, admin_account_key_helper};
|
use crate::helpers::{admin_access_token_helper, admin_account_helper, admin_account_key_helper};
|
||||||
|
use crate::helpers::admin_log_helper::log_admin_action;
|
||||||
use crate::routes::RequestResult;
|
use crate::routes::RequestResult;
|
||||||
use crate::utils::date_utils::time;
|
use crate::utils::date_utils::time;
|
||||||
use crate::constants::admin::AdminRole;
|
|
||||||
|
|
||||||
/// Create a new administrator account
|
/// Create a new administrator account
|
||||||
pub fn create(r: &mut HttpRequestHandler) -> RequestResult {
|
pub fn create(r: &mut HttpRequestHandler) -> RequestResult {
|
||||||
let email = r.post_email("mail")?;
|
let email = r.post_email("mail")?;
|
||||||
let name = r.post_string_opt("name", 3, true)?;
|
let name = r.post_string_opt("name", 3, true)?;
|
||||||
|
|
||||||
let admin_id = admin_account_helper::create(&NewAdmin { name, email })?;
|
let new_admin = NewAdmin { name, email };
|
||||||
|
let admin_id = admin_account_helper::create(&new_admin)?;
|
||||||
|
|
||||||
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||||
|
AdminAction::CreatedAdmin { id: admin_id, name: new_admin.name, email: new_admin.email })?;
|
||||||
|
|
||||||
r.set_response(AdminResCreateAccount::new(admin_id))
|
r.set_response(AdminResCreateAccount::new(admin_id))
|
||||||
}
|
}
|
||||||
@ -52,6 +58,9 @@ pub fn auth_with_reset_token(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
let token = admin_access_token_helper::create(admin.id)?;
|
let token = admin_access_token_helper::create(admin.id)?;
|
||||||
|
|
||||||
|
log_admin_action(admin.id, &r.remote_ip(),
|
||||||
|
AdminAction::AuthWithResetToken)?;
|
||||||
|
|
||||||
r.set_response(AdminAuthSuccess::new(token))
|
r.set_response(AdminAuthSuccess::new(token))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,10 +111,13 @@ pub fn update_general_settings(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
admin_account_helper::set_general_settings(NewAdminGeneralSettings {
|
admin_account_helper::set_general_settings(NewAdminGeneralSettings {
|
||||||
id: admin_id,
|
id: admin_id,
|
||||||
name: new_name,
|
name: new_name.to_string(),
|
||||||
email: new_email,
|
email: new_email.to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||||
|
AdminAction::UpdatedAdminGeneralSettings { target: admin_id, new_name, new_email })?;
|
||||||
|
|
||||||
r.ok()
|
r.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,5 +131,8 @@ pub fn generate_reset_token(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
let token = admin_account_helper::create_new_reset_token(admin_id)?;
|
let token = admin_account_helper::create_new_reset_token(admin_id)?;
|
||||||
|
|
||||||
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||||
|
AdminAction::GeneratedAdminResetToken { target: admin_id })?;
|
||||||
|
|
||||||
r.set_response(AdminResCreateResetToken::new(token))
|
r.set_response(AdminResCreateResetToken::new(token))
|
||||||
}
|
}
|
@ -4,15 +4,17 @@
|
|||||||
|
|
||||||
|
|
||||||
use crate::api_data::admin::admin_auth_success::AdminAuthSuccess;
|
use crate::api_data::admin::admin_auth_success::AdminAuthSuccess;
|
||||||
|
use crate::api_data::admin::admin_keys_api::AdminKeyAPI;
|
||||||
|
use crate::constants::admin::AdminRole;
|
||||||
use crate::data::admin::AdminKey;
|
use crate::data::admin::AdminKey;
|
||||||
|
use crate::data::admin_action_log::AdminAction;
|
||||||
use crate::data::base_request_handler::BaseRequestHandler;
|
use crate::data::base_request_handler::BaseRequestHandler;
|
||||||
use crate::data::error::Res;
|
use crate::data::error::Res;
|
||||||
use crate::data::http_request_handler::HttpRequestHandler;
|
use crate::data::http_request_handler::HttpRequestHandler;
|
||||||
use crate::data::webauthn_config::get_wan;
|
use crate::data::webauthn_config::get_wan;
|
||||||
use crate::helpers::{admin_access_token_helper, admin_account_helper, admin_account_key_helper, admin_key_authentication_challenges_helper, admin_key_registration_challenges_helper};
|
use crate::helpers::{admin_access_token_helper, admin_account_helper, admin_account_key_helper, admin_key_authentication_challenges_helper, admin_key_registration_challenges_helper};
|
||||||
|
use crate::helpers::admin_log_helper::log_admin_action;
|
||||||
use crate::routes::RequestResult;
|
use crate::routes::RequestResult;
|
||||||
use crate::api_data::admin::admin_keys_api::AdminKeyAPI;
|
|
||||||
use crate::constants::admin::AdminRole;
|
|
||||||
|
|
||||||
impl HttpRequestHandler {
|
impl HttpRequestHandler {
|
||||||
pub fn post_admin_auth_key(&mut self, name_mail: &str, name_key_id: &str) -> Res<AdminKey> {
|
pub fn post_admin_auth_key(&mut self, name_mail: &str, name_key_id: &str) -> Res<AdminKey> {
|
||||||
@ -73,6 +75,9 @@ pub fn register_key(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
admin_account_key_helper::add_key(r.admin_id()?, &name, key)?;
|
admin_account_key_helper::add_key(r.admin_id()?, &name, key)?;
|
||||||
|
|
||||||
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||||
|
AdminAction::RegisteredAdminKey { name, target: r.admin_id()? })?;
|
||||||
|
|
||||||
r.ok()
|
r.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +92,9 @@ pub fn delete_auth_key(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
for key in admin_account_key_helper::get_admin_keys(admin_id)? {
|
for key in admin_account_key_helper::get_admin_keys(admin_id)? {
|
||||||
if key.id == key_id {
|
if key.id == key_id {
|
||||||
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||||
|
AdminAction::DeletedAdminKey { name: key.name.to_string(), target: admin_id })?;
|
||||||
|
|
||||||
admin_account_key_helper::delete_key(key)?;
|
admin_account_key_helper::delete_key(key)?;
|
||||||
|
|
||||||
return r.ok();
|
return r.ok();
|
||||||
@ -125,5 +133,8 @@ pub fn auth_with_key(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
// Generate access token
|
// Generate access token
|
||||||
let token = admin_access_token_helper::create(key.admin_id)?;
|
let token = admin_access_token_helper::create(key.admin_id)?;
|
||||||
|
|
||||||
|
log_admin_action(key.admin_id, &r.remote_ip(),
|
||||||
|
AdminAction::AuthWithAccessKey { key: key.name, key_id: key.id })?;
|
||||||
|
|
||||||
r.set_response(AdminAuthSuccess::new(token))
|
r.set_response(AdminAuthSuccess::new(token))
|
||||||
}
|
}
|
@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
use crate::api_data::admin::admin_role_api::AdminRoleDetailsAPI;
|
use crate::api_data::admin::admin_role_api::AdminRoleDetailsAPI;
|
||||||
use crate::constants::admin::{ADMIN_ROLES_LIST, AdminRole};
|
use crate::constants::admin::{ADMIN_ROLES_LIST, AdminRole};
|
||||||
|
use crate::data::admin_action_log::AdminAction;
|
||||||
use crate::data::base_request_handler::BaseRequestHandler;
|
use crate::data::base_request_handler::BaseRequestHandler;
|
||||||
use crate::data::http_request_handler::HttpRequestHandler;
|
use crate::data::http_request_handler::HttpRequestHandler;
|
||||||
|
use crate::helpers::admin_log_helper::log_admin_action;
|
||||||
use crate::helpers::admin_roles_helper;
|
use crate::helpers::admin_roles_helper;
|
||||||
use crate::routes::RequestResult;
|
use crate::routes::RequestResult;
|
||||||
|
|
||||||
@ -30,8 +32,13 @@ pub fn toggle(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
if !enable {
|
if !enable {
|
||||||
admin_roles_helper::remove_role(admin_id, role)?;
|
admin_roles_helper::remove_role(admin_id, role)?;
|
||||||
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||||
|
AdminAction::RemoveAdminRole { target: admin_id, role: role_str })?;
|
||||||
} else if !admin_roles_helper::has_role(admin_id, role)? {
|
} else if !admin_roles_helper::has_role(admin_id, role)? {
|
||||||
admin_roles_helper::add_role(admin_id, role)?;
|
admin_roles_helper::add_role(admin_id, role)?;
|
||||||
|
|
||||||
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||||
|
AdminAction::AddAdminRole { target: admin_id, role: role_str })?;
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ok()
|
r.ok()
|
||||||
|
@ -2,9 +2,12 @@
|
|||||||
//!
|
//!
|
||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
use mysql::serde::{Deserializer, Serializer};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use webauthn_rs::proto::Credential;
|
use webauthn_rs::proto::Credential;
|
||||||
|
|
||||||
use crate::constants::admin::{ADMIN_ROLES_LIST, AdminRole};
|
use crate::constants::admin::{ADMIN_ROLES_LIST, AdminRole};
|
||||||
|
use crate::data::u64_visitor::U64Visitor;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
|
||||||
pub struct AdminID(u64);
|
pub struct AdminID(u64);
|
||||||
@ -83,3 +86,17 @@ impl AdminRole {
|
|||||||
.expect("Should have found a role!!!")
|
.expect("Should have found a role!!!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for AdminID {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> where
|
||||||
|
S: Serializer {
|
||||||
|
serializer.serialize_u64(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for AdminID {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error> where
|
||||||
|
D: Deserializer<'de> {
|
||||||
|
deserializer.deserialize_u64(U64Visitor {}).map(|id| AdminID::new(id))
|
||||||
|
}
|
||||||
|
}
|
26
src/data/admin_action_log.rs
Normal file
26
src/data/admin_action_log.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//! # Admin action log
|
||||||
|
|
||||||
|
use crate::data::admin::AdminID;
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
pub enum AdminAction {
|
||||||
|
AuthWithResetToken,
|
||||||
|
AuthWithAccessKey { key: String, key_id: u64 },
|
||||||
|
RegisteredAdminKey { name: String, target: AdminID },
|
||||||
|
DeletedAdminKey { name: String, target: AdminID },
|
||||||
|
GeneratedAdminResetToken { target: AdminID },
|
||||||
|
CreatedAdmin { id: AdminID, name: String, email: String },
|
||||||
|
UpdatedAdminGeneralSettings { target: AdminID, new_email: String, new_name: String },
|
||||||
|
AddAdminRole { target: AdminID, role: String },
|
||||||
|
RemoveAdminRole { target: AdminID, role: String },
|
||||||
|
UnsupportedAction,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct AdminActionLog {
|
||||||
|
pub id: u64,
|
||||||
|
pub admin_id: AdminID,
|
||||||
|
pub ip: String,
|
||||||
|
pub time: u64,
|
||||||
|
pub action: AdminAction,
|
||||||
|
}
|
@ -43,3 +43,5 @@ pub mod push_notification;
|
|||||||
pub mod presence;
|
pub mod presence;
|
||||||
pub mod admin;
|
pub mod admin;
|
||||||
pub mod webauthn_config;
|
pub mod webauthn_config;
|
||||||
|
pub mod admin_action_log;
|
||||||
|
pub mod u64_visitor;
|
20
src/data/u64_visitor.rs
Normal file
20
src/data/u64_visitor.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Formatter;
|
||||||
|
|
||||||
|
use mysql::serde::de::Error;
|
||||||
|
use serde::de::Visitor;
|
||||||
|
|
||||||
|
pub struct U64Visitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for U64Visitor {
|
||||||
|
type Value = u64;
|
||||||
|
|
||||||
|
fn expecting<'a>(&self, formatter: &mut Formatter<'a>) -> fmt::Result {
|
||||||
|
formatter.write_str("An unsigned integer value")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> where
|
||||||
|
E: Error, {
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
}
|
20
src/helpers/admin_log_helper.rs
Normal file
20
src/helpers/admin_log_helper.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//! # Admin logs management
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
use crate::constants::database_tables_names::ADMIN_LOGS_TABLE;
|
||||||
|
use crate::data::admin::AdminID;
|
||||||
|
use crate::data::admin_action_log::AdminAction;
|
||||||
|
use crate::data::error::Res;
|
||||||
|
use crate::helpers::database;
|
||||||
|
use crate::utils::date_utils::time;
|
||||||
|
|
||||||
|
/// Record an administrator action
|
||||||
|
pub fn log_admin_action(admin: AdminID, ip: &str, action: AdminAction) -> Res {
|
||||||
|
database::InsertQuery::new(ADMIN_LOGS_TABLE)
|
||||||
|
.add_admin_id("admin_id", admin)
|
||||||
|
.add_str("ip", ip)
|
||||||
|
.add_u64("time", time())
|
||||||
|
.add_str("action", &serde_json::to_string(&action)?)
|
||||||
|
.insert_drop_result()
|
||||||
|
}
|
@ -28,3 +28,4 @@ pub mod admin_access_token_helper;
|
|||||||
pub mod admin_key_registration_challenges_helper;
|
pub mod admin_key_registration_challenges_helper;
|
||||||
pub mod admin_key_authentication_challenges_helper;
|
pub mod admin_key_authentication_challenges_helper;
|
||||||
pub mod admin_roles_helper;
|
pub mod admin_roles_helper;
|
||||||
|
pub mod admin_log_helper;
|
Loading…
Reference in New Issue
Block a user