Refactored loxide libs for easier readability
Build Library / Build Library (push) Successful in 5m52s

This commit is contained in:
brotoskyj
2025-12-03 11:45:22 -05:00
parent e5b4b9d959
commit 6ab9de413f
9 changed files with 152 additions and 142 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ dependencies = [
[[package]]
name = "airlock_libs"
version = "5.0.0"
version = "5.0.1"
dependencies = [
"chrono",
"indicatif",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "airlock_libs"
version = "5.0.0"
version = "5.0.1"
edition = "2024"
[lib]
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "maturin"
[project]
name = "airlock_libs"
version = "5.0.0"
version = "5.0.1"
description = "Airlock Digital API Wrapper"
readme = "README.md"
license = { text = "AGPL-3.0-only" }
+3 -1
View File
@@ -1,5 +1,7 @@
use pyo3::prelude::*;
mod services;
pub mod modules;
pub mod services;
pub mod prelude;
#[pymodule]
fn airlock_libs(py: Python<'_>, m: &Bound<PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(services::pull_policy_exec_histories, py)?)?;
+112
View File
@@ -0,0 +1,112 @@
use crate::prelude::*;
use crate::services::get_base_directory;
#[allow(non_snake_case)]
#[derive(Deserialize, Debug)]
pub struct TelemetryConfig {
pub TELEMETRY: bool,
pub TELEM_URL: Option<String>,
}
impl TelemetryConfig {
pub fn load() -> Self {
let cfg_path = get_base_directory().join("config\\user_config.json");
if !cfg_path.exists() {
return Self {
TELEMETRY: false,
TELEM_URL: None,
};
}
match fs::read_to_string(&cfg_path) {
Ok(contents) => serde_json::from_str::<Self>(&contents).unwrap_or(Self {
TELEMETRY: false,
TELEM_URL: None,
}),
Err(_) => Self {
TELEMETRY: false,
TELEM_URL: None,
},
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ApiResponse {
pub(crate) error: String,
pub(crate) response: ExecHistories,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ExecHistories {
pub(crate) exechistories: Vec<Group>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Group {
pub(crate) checkpoint: String,
#[serde(rename = "type")]
pub(crate) exectype: u8,
pub(crate) username: String,
pub(crate) hostname: String,
pub(crate) netdomain: String,
pub(crate) filename: String,
pub(crate) ppolicy: String,
pub(crate) policyname: String,
pub(crate) policyver: String,
pub(crate) commandline: String,
pub(crate) publisher: String,
pub(crate) pprocess: String,
pub(crate) gprocess: String,
pub(crate) sha256: String,
pub(crate) datetime: String,
pub(crate) md5: String,
pub(crate) sha128: String,
pub(crate) sha384: String,
pub(crate) sha512: String,
pub(crate) ip: String,
pub(crate) localip: String,
}
pub enum ExtractedValues {
Headers(reqwest::header::HeaderMap),
BaseUrl(String),
}
pub trait Converter {
fn convert(py: Python<'_>, py_self: &Py<PyAny>, extract_headers: bool) -> ExtractedValues;
}
pub struct PyData;
impl Converter for PyData {
fn convert(py: Python<'_>, py_self: &Py<PyAny>, extract_headers: bool) -> ExtractedValues {
if extract_headers {
let headers = py_self.getattr(py, "headers").unwrap().to_string();
let headers_replace = headers.replace('\'', "\"");
let parsed: Value = serde_json::from_str(headers_replace.as_str()).unwrap();
let mut header_map = HeaderMap::new();
if let Some(obj) = parsed.as_object() {
for (_key, value) in obj {
if let Some(v) = value.as_str() {
let val = HeaderValue::from_str(v).unwrap();
header_map.insert(HeaderName::from_str("X-APIKey").unwrap(), val);
}
}
}
ExtractedValues::Headers(header_map)
} else {
let base_url = py_self.getattr(py, "base_url").unwrap().to_string();
ExtractedValues::BaseUrl(base_url)
}
}
}
pub struct SkipBack;
impl SkipBack {
pub fn find_checkpoint(days: i64) -> ObjectId {
let date_days_ago = Local::now() - Duration::days(days);
let timestamp = date_days_ago.timestamp() as u32;
let mut hex_timestamp = String::new();
write!(&mut hex_timestamp, "{:08x}", timestamp).unwrap();
let objectid_hex = format!("{}0000000000000000", hex_timestamp);
ObjectId::parse_str(&objectid_hex).expect("Invalid ObjectId hex")
}
}
+1
View File
@@ -0,0 +1 @@
pub mod datatypes;
+27
View File
@@ -0,0 +1,27 @@
pub use chrono::{Duration, Local, NaiveDate};
pub use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle};
pub use mongodb::bson::oid::ObjectId;
pub use opentelemetry::global::shutdown_tracer_provider;
pub use opentelemetry::sdk::Resource;
pub use opentelemetry::trace::noop::NoopTracerProvider;
pub use opentelemetry::trace::{Status, TraceContextExt, TraceError};
pub use opentelemetry::{Context, KeyValue, sdk::trace as sdktrace, trace::Tracer};
pub use opentelemetry::{Key, global};
pub use opentelemetry_otlp::WithExportConfig;
pub use pyo3::{prelude::*, types::PyString};
pub use pyo3_async_runtimes::async_std;
pub use reqwest::{
Client,
header::{HeaderMap, HeaderName, HeaderValue},
};
pub use serde::{Deserialize, Serialize};
pub use serde_json::Value;
pub use std::{
collections::HashMap,
env,
fmt::Write,
fs::{self, File},
io::{Read, Seek, SeekFrom},
path::PathBuf,
str::FromStr,
};
+5 -137
View File
@@ -1,128 +1,5 @@
use chrono::{Duration, Local, NaiveDate};
use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle};
use mongodb::bson::oid::ObjectId;
use opentelemetry::global::shutdown_tracer_provider;
use opentelemetry::sdk::Resource;
use opentelemetry::trace::noop::NoopTracerProvider;
use opentelemetry::trace::{Status, TraceContextExt, TraceError};
use opentelemetry::{Context, KeyValue, sdk::trace as sdktrace, trace::Tracer};
use opentelemetry::{Key, global};
use opentelemetry_otlp::WithExportConfig;
use pyo3::{prelude::*, types::PyString};
use pyo3_async_runtimes::async_std;
use reqwest::{
Client,
header::{HeaderMap, HeaderName, HeaderValue},
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{
collections::HashMap,
env,
fmt::Write,
fs::{self, File},
io::{Read, Seek, SeekFrom},
path::PathBuf,
str::FromStr,
};
#[allow(non_snake_case)]
#[derive(Deserialize, Debug)]
struct TelemetryConfig {
TELEMETRY: bool,
TELEM_URL: Option<String>,
}
impl TelemetryConfig {
pub fn load() -> Self {
let cfg_path = get_base_directory().join("config\\user_config.json");
if !cfg_path.exists() {
return Self {
TELEMETRY: false,
TELEM_URL: None,
};
}
match fs::read_to_string(&cfg_path) {
Ok(contents) => serde_json::from_str::<Self>(&contents).unwrap_or(Self {
TELEMETRY: false,
TELEM_URL: None,
}),
Err(_) => Self {
TELEMETRY: false,
TELEM_URL: None,
},
}
}
}
#[derive(Debug, Deserialize, Serialize)]
struct ApiResponse {
error: String,
response: ExecHistories,
}
#[derive(Debug, Deserialize, Serialize)]
struct ExecHistories {
exechistories: Vec<Group>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
struct Group {
checkpoint: String,
#[serde(rename = "type")]
exectype: u8,
username: String,
hostname: String,
netdomain: String,
filename: String,
ppolicy: String,
policyname: String,
policyver: String,
commandline: String,
publisher: String,
pprocess: String,
gprocess: String,
sha256: String,
datetime: String,
md5: String,
sha128: String,
sha384: String,
sha512: String,
ip: String,
localip: String,
}
enum ExtractedValues {
Headers(reqwest::header::HeaderMap),
BaseUrl(String),
}
trait Converter {
fn convert(py: Python<'_>, py_self: &Py<PyAny>, extract_headers: bool) -> ExtractedValues;
}
struct PyData;
impl Converter for PyData {
fn convert(py: Python<'_>, py_self: &Py<PyAny>, extract_headers: bool) -> ExtractedValues {
if extract_headers {
let headers = py_self.getattr(py, "headers").unwrap().to_string();
let headers_replace = headers.replace('\'', "\"");
let parsed: Value = serde_json::from_str(headers_replace.as_str()).unwrap();
let mut header_map = HeaderMap::new();
if let Some(obj) = parsed.as_object() {
for (_key, value) in obj {
if let Some(v) = value.as_str() {
let val = HeaderValue::from_str(v).unwrap();
header_map.insert(HeaderName::from_str("X-APIKey").unwrap(), val);
}
}
}
ExtractedValues::Headers(header_map)
} else {
let base_url = py_self.getattr(py, "base_url").unwrap().to_string();
ExtractedValues::BaseUrl(base_url)
}
}
}
use crate::prelude::*;
use crate::modules::datatypes::*;
#[pyfunction]
pub fn pull_policy_exec_histories(
py: Python<'_>,
@@ -192,7 +69,7 @@ pub fn pull_policy_exec_histories(
std::process::abort();
}
}
let mut checkpoint_number: String = skipback(days).to_string();
let mut checkpoint_number: String = SkipBack::find_checkpoint(days).to_string();
let multi_progress = MultiProgress::new();
multi_progress.set_draw_target(ProgressDrawTarget::stdout());
let progress_bar = multi_progress.add(ProgressBar::new(100));
@@ -410,7 +287,7 @@ async fn history_logging(
}
}
fn get_base_directory() -> PathBuf {
pub fn get_base_directory() -> PathBuf {
let home = env::var_os("HOME")
.map(PathBuf::from)
.or_else(|| env::var_os("USERPROFILE").map(PathBuf::from))
@@ -427,15 +304,6 @@ fn get_base_directory() -> PathBuf {
}
}
fn skipback(days: i64) -> ObjectId {
let date_days_ago = Local::now() - Duration::days(days);
let timestamp = date_days_ago.timestamp() as u32;
let mut hex_timestamp = String::new();
write!(&mut hex_timestamp, "{:08x}", timestamp).unwrap();
let objectid_hex = format!("{}0000000000000000", hex_timestamp);
ObjectId::parse_str(&objectid_hex).expect("Invalid ObjectId hex")
}
fn init_tracer() -> Result<Option<sdktrace::Tracer>, TraceError> {
let cfg = TelemetryConfig::load();
if !cfg.TELEMETRY {
@@ -457,4 +325,4 @@ fn init_tracer() -> Result<Option<sdktrace::Tracer>, TraceError> {
.install_simple()
.unwrap();
Ok(Some(tracer))
}
}
+1 -1
View File
@@ -11,4 +11,4 @@ urllib3==2.5.0
pyperclip==1.11.0
--extra-index-url https://git.racooncity.org/api/packages/brotoskyj/pypi/simple/
airlock_libs==5.0.0
airlock_libs==5.0.1