mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-12-26 05:28:50 +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,
|
||||
`time_insert` INT NULL,
|
||||
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,
|
||||
`time_insert` INT NULL,
|
||||
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_KEYS_TABLE: &str = "comunic_admin_key";
|
||||
pub const ADMIN_ROLES_TABLE: &str = "comunic_admin_roles";
|
||||
pub const ADMIN_LOGS_TABLE: &str = "comunic_admin_log";
|
||||
}
|
||||
|
||||
/// 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_res_create_account::AdminResCreateAccount;
|
||||
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_action_log::AdminAction;
|
||||
use crate::data::base_request_handler::BaseRequestHandler;
|
||||
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_log_helper::log_admin_action;
|
||||
use crate::routes::RequestResult;
|
||||
use crate::utils::date_utils::time;
|
||||
use crate::constants::admin::AdminRole;
|
||||
|
||||
/// Create a new administrator account
|
||||
pub fn create(r: &mut HttpRequestHandler) -> RequestResult {
|
||||
let email = r.post_email("mail")?;
|
||||
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))
|
||||
}
|
||||
@ -52,6 +58,9 @@ pub fn auth_with_reset_token(r: &mut HttpRequestHandler) -> RequestResult {
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
@ -102,10 +111,13 @@ pub fn update_general_settings(r: &mut HttpRequestHandler) -> RequestResult {
|
||||
|
||||
admin_account_helper::set_general_settings(NewAdminGeneralSettings {
|
||||
id: admin_id,
|
||||
name: new_name,
|
||||
email: new_email,
|
||||
name: new_name.to_string(),
|
||||
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()
|
||||
}
|
||||
|
||||
@ -119,5 +131,8 @@ pub fn generate_reset_token(r: &mut HttpRequestHandler) -> RequestResult {
|
||||
|
||||
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))
|
||||
}
|
@ -4,15 +4,17 @@
|
||||
|
||||
|
||||
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_action_log::AdminAction;
|
||||
use crate::data::base_request_handler::BaseRequestHandler;
|
||||
use crate::data::error::Res;
|
||||
use crate::data::http_request_handler::HttpRequestHandler;
|
||||
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_log_helper::log_admin_action;
|
||||
use crate::routes::RequestResult;
|
||||
use crate::api_data::admin::admin_keys_api::AdminKeyAPI;
|
||||
use crate::constants::admin::AdminRole;
|
||||
|
||||
impl HttpRequestHandler {
|
||||
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)?;
|
||||
|
||||
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
||||
AdminAction::RegisteredAdminKey { name, target: r.admin_id()? })?;
|
||||
|
||||
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)? {
|
||||
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)?;
|
||||
|
||||
return r.ok();
|
||||
@ -125,5 +133,8 @@ pub fn auth_with_key(r: &mut HttpRequestHandler) -> RequestResult {
|
||||
// Generate access token
|
||||
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))
|
||||
}
|
@ -4,8 +4,10 @@
|
||||
|
||||
use crate::api_data::admin::admin_role_api::AdminRoleDetailsAPI;
|
||||
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::http_request_handler::HttpRequestHandler;
|
||||
use crate::helpers::admin_log_helper::log_admin_action;
|
||||
use crate::helpers::admin_roles_helper;
|
||||
use crate::routes::RequestResult;
|
||||
|
||||
@ -30,8 +32,13 @@ pub fn toggle(r: &mut HttpRequestHandler) -> RequestResult {
|
||||
|
||||
if !enable {
|
||||
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)? {
|
||||
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()
|
||||
|
@ -2,9 +2,12 @@
|
||||
//!
|
||||
//! @author Pierre Hubert
|
||||
|
||||
use mysql::serde::{Deserializer, Serializer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use webauthn_rs::proto::Credential;
|
||||
|
||||
use crate::constants::admin::{ADMIN_ROLES_LIST, AdminRole};
|
||||
use crate::data::u64_visitor::U64Visitor;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
|
||||
pub struct AdminID(u64);
|
||||
@ -82,4 +85,18 @@ impl AdminRole {
|
||||
.next()
|
||||
.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,
|
||||
}
|
@ -42,4 +42,6 @@ pub mod new_notifications_settings;
|
||||
pub mod push_notification;
|
||||
pub mod presence;
|
||||
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()
|
||||
}
|
@ -27,4 +27,5 @@ pub mod admin_account_key_helper;
|
||||
pub mod admin_access_token_helper;
|
||||
pub mod admin_key_registration_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