Browse Source

HALLELUJAH now runs both as client and server

main_chirho
LoveJesus 3 months ago
commit
95773fc770
12 changed files with 770 additions and 0 deletions
  1. +4
    -0
      .env_chirho
  2. +22
    -0
      README.md
  3. +3
    -0
      dot.env_chirho.sample_chirho
  4. +23
    -0
      rocket.toml
  5. +11
    -0
      sql_chirho/createdb_chirho.sh
  6. +39
    -0
      sql_chirho/sql_definitions_chirho.sql
  7. +244
    -0
      src/cli_chirho/cli_chirho.rs
  8. +4
    -0
      src/cli_chirho/mod.rs
  9. +150
    -0
      src/models_chirho/host_model_chirho.rs
  10. +14
    -0
      src/models_chirho/mod.rs
  11. +133
    -0
      src/models_chirho/user_model_chirho.rs
  12. +123
    -0
      src/models_chirho/user_ssh_authorized_key_chirho.rs

+ 4
- 0
.env_chirho View File

@ -0,0 +1,4 @@
# For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
# Rename to .env_chirho
export API_KEY_CHIRHO="HALLELUJAH30920-9482"
export DATABASE_URL="sqlite:./db_chirho.sqlite"

+ 22
- 0
README.md View File

@ -0,0 +1,22 @@
# For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
## rs_machine_input_chirho
This command line application is intended to keep a remote database of computer resources synchronized
with the information about those resources.
run the following command from the project base to create the server side DB:
```bash
sql_chirho/createdb_chirho.sh
```
we also need the environment variables in dot.env_chirho.sample_chirho properly set up in both the client and the
server.
`export ROCKET_PORT=...` to set the port where the server will listen to requests.

+ 3
- 0
dot.env_chirho.sample_chirho View File

@ -0,0 +1,3 @@
# For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
# Rename to .env_chirho
export API_KEY_CHIRHO="HALLELUJAH30920-9482"

+ 23
- 0
rocket.toml View File

@ -0,0 +1,23 @@
# For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
## defaults for _all_ profiles
[default]
address = "127.0.0.1"
limits = { form = "64 kB", json = "1 MiB" }
## set only when compiled in debug mode, i.e, `cargo build`
[debug]
port = 8870
## only the `json` key from `default` will be overridden; `form` will remain
limits = { json = "10MiB" }
## set only when the `nyc` profile is selected
[nyc]
port = 9001
## set only when compiled in release mode, i.e, `cargo build --release`
[release]
port = 9999
ip_header = false
[default.databases.sqlite_database_chirho]
url = "sqlite:db_chirho.sqlite"

+ 11
- 0
sql_chirho/createdb_chirho.sh View File

@ -0,0 +1,11 @@
#!/usr/bin/env zsh
# For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
if [ ! -d "sql_chirho" ]; then
echo "Hallelujah Please run this script from the root of the repository"
exit 1
fi
# Create the sqlite database in db_chirho.sqlite
rm db_chirho.sqlite
sqlite3 db_chirho.sqlite < sql_chirho/sql_definitions_chirho.sql

+ 39
- 0
sql_chirho/sql_definitions_chirho.sql View File

@ -0,0 +1,39 @@
-- For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
-- Sqlite descriptor of hosts, users, ssh public keys, etc...
PRAGMA foreign_keys = ON;
DROP TABLE IF EXISTS hosts_chirho;
DROP TABLE IF EXISTS users_chirho;
DROP TABLE IF EXISTS user_ssh_authorized_keys_chirho;
CREATE TABLE IF NOT EXISTS hosts_chirho (
id_chirho INTEGER PRIMARY KEY AUTOINCREMENT,
hostname_chirho TEXT NOT NULL,
operating_system_chirho TEXT NOT NULL,
ram_mb_chirho INTEGER NOT NULL,
cpu_cores_chirho INTEGER NOT NULL,
storage_gb_chirho INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS users_chirho (
id_chirho INTEGER PRIMARY KEY AUTOINCREMENT,
host_id_chirho INTEGER NOT NULL,
username_chirho VARCHAR(255) NOT NULL,
groups_chirho TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (host_id_chirho) REFERENCES hosts_chirho(id_chirho)
);
create table if not exists user_ssh_authorized_keys_chirho (
id_chirho INTEGER PRIMARY KEY AUTOINCREMENT,
user_id_chirho INTEGER NOT NULL,
ssh_key_chirho TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id_chirho) REFERENCES users_chirho(id_chirho)
);

+ 244
- 0
src/cli_chirho/cli_chirho.rs View File

@ -0,0 +1,244 @@
/*
* For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
*/
use clap::{Parser, Subcommand};
use serde::{Serialize, Deserialize};
use std::error::Error;
use std::{env, fs, panic};
use std::fs::{File, read_to_string};
use std::io::{BufRead, BufReader};
use std::path::Path;
use reqwest::Client;
use rocket::futures::TryFutureExt;
use serde_json::json;
use crate::models_chirho::host_model_chirho::HostChirho;
use crate::models_chirho::user_model_chirho::UserChirho;
use crate::models_chirho::user_ssh_authorized_key_chirho::UserSshAuthorizedKeyChirho;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct CliChirho {
#[arg(long)]
pub cli_url_chirho: Option<String>,}
#[derive(Debug, Serialize, Deserialize)]
struct SystemInfoChirho {
hostname_chirho: String,
operating_system_chirho: String,
ram_mb_chirho: u64,
cpu_cores_chirho: u64,
storage_gb_chirho: u64,
users_chirho: Vec<UserInfoChirho>,
}
#[derive(Debug, Serialize, Deserialize)]
struct UserInfoChirho {
username_chirho: String,
groups_chirho: Vec<String>,
ssh_keys_chirho: Vec<String>,
}
pub fn run_cli_chirho(url_chirho: &str) -> Result<(), Box<dyn Error>> {
let system_info_chirho = collect_system_info_chirho()?;
tokio::runtime::Runtime::new()?.block_on(async {
create_resources_chirho(&system_info_chirho, url_chirho).await.expect("TODO: panic message");
});
println!("System information sent successfully!");
Ok(())
}
fn collect_system_info_chirho() -> Result<SystemInfoChirho, Box<dyn Error>> {
let hostname_chirho = hostname::get()?.into_string().unwrap();
let os_chirho = std::env::consts::OS.to_string();
#[cfg(target_os = "linux")]
let (ram_mb_chirho, cpu_cores_chirho, storage_gb_chirho) = collect_linux_info_chirho()?;
#[cfg(target_os = "windows")]
let (ram_mb_chirho, cpu_cores_chirho, storage_gb_chirho) = collect_windows_info_chirho()?;
#[cfg(target_os = "macos")]
let (ram_mb_chirho, cpu_cores_chirho, storage_gb_chirho) = collect_macos_info_chirho()?;
let users_chirho = collect_user_info_chirho()?;
Ok(SystemInfoChirho {
hostname_chirho,
operating_system_chirho: os_chirho,
ram_mb_chirho,
cpu_cores_chirho,
storage_gb_chirho,
users_chirho,
})
}
#[cfg(target_os = "linux")]
fn collect_linux_info_chirho() -> Result<(u64, u64, u64), Box<dyn Error>> {
use sys_info::{mem_info, cpu_num, disk_info};
let mem_chirho = mem_info()?;
let ram_mb_chirho = mem_chirho.total / 1024;
let cpu_cores_chirho = cpu_num()? as u64;
let disk_chirho = disk_info()?;
let storage_gb_chirho = disk_chirho.total / (1024 * 1024);
Ok((ram_mb_chirho, cpu_cores_chirho, storage_gb_chirho))
}
#[cfg(target_os = "windows")]
fn collect_windows_info_chirho() -> Result<(u64, u64, u64), Box<dyn Error>> {
use sysinfo::{SystemExt, DiskExt};
let mut sys_chirho = sysinfo::System::new_all();
sys_chirho.refresh_all();
let ram_mb_chirho = sys_chirho.total_memory() / 1024;
let cpu_cores_chirho = sys_chirho.processors().len() as u64;
let storage_gb_chirho = sys_chirho.disks().iter().map(|disk_chirho| disk_chirho.total_space()).sum::<u64>() / (1024 * 1024 * 1024);
Ok((ram_mb_chirho, cpu_cores_chirho, storage_gb_chirho))
}
#[cfg(target_os = "macos")]
fn collect_macos_info_chirho() -> Result<(u64, u64, u64), Box<dyn Error>> {
use sysinfo::{SystemExt, DiskExt};
let mut sys_chirho = sysinfo::System::new_all();
sys_chirho.refresh_all();
let ram_mb_chirho = sys_chirho.total_memory() / 1024;
let cpu_cores_chirho = sys_chirho.processors().len() as u64;
let storage_gb_chirho = sys_chirho.disks().iter().map(|disk_chirho| disk_chirho.total_space()).sum::<u64>() / (1024 * 1024 * 1024);
Ok((ram_mb_chirho, cpu_cores_chirho, storage_gb_chirho))
}
fn collect_user_info_chirho() -> Result<Vec<UserInfoChirho>, Box<dyn Error>> {
let mut users_chirho = Vec::new();
#[cfg(target_family = "unix")]
{
let passwd_file = File::open("/etc/passwd")?;
let passwd_reader = BufReader::new(passwd_file);
let group_file = File::open("/etc/group")?;
let group_reader = BufReader::new(group_file);
// Read group information
let mut groups_map = std::collections::HashMap::new();
for line in group_reader.lines() {
let line = line?;
let parts: Vec<&str> = line.split(':').collect();
if parts.len() >= 4 {
let group_name = parts[0].to_string();
let group_id = parts[2].parse::<u32>().unwrap_or(0);
groups_map.insert(group_id, group_name);
}
}
// Read user information
for line in passwd_reader.lines() {
let line = line?;
let parts: Vec<&str> = line.split(':').collect();
if parts.len() >= 7 {
let username_chirho = parts[0].to_string();
let uid = parts[2].parse::<u32>().unwrap_or(0);
let gid = parts[3].parse::<u32>().unwrap_or(0);
let home_dir = parts[5].to_string();
// Only include users with a home directory
if Path::new(&home_dir).exists()
&& !home_dir.contains("/empty")
&& !home_dir.contains("/nologin")
&& !home_dir.contains("/false")
&& (home_dir.to_lowercase().contains("/home")
|| home_dir.to_lowercase().contains("users")
|| (home_dir.contains("root") && uid == 0)) {
let mut groups_chirho = Vec::new();
if let Some(group_name) = groups_map.get(&gid) {
groups_chirho.push(group_name.clone());
}
let ssh_keys_chirho = read_ssh_keys_chirho(&home_dir).unwrap_or_else(|e| {
eprintln!("Failed to read SSH keys for user {}: {}", username_chirho, e);
vec![]
});
users_chirho.push(UserInfoChirho {
username_chirho,
groups_chirho,
ssh_keys_chirho,
});
}
}
}
}
#[cfg(target_os = "windows")]
{
println!("Warning: User enumeration not implemented for Windows");
}
println!("{:?}", users_chirho);
Ok(users_chirho)
}
fn read_ssh_keys_chirho(home_dir: &str) -> Result<Vec<String>, Box<dyn Error>> {
let authorized_keys_path = Path::new(home_dir).join(".ssh").join("authorized_keys");
if authorized_keys_path.exists() {
let content = read_to_string(authorized_keys_path)?;
Ok(content.lines().map(String::from).collect())
} else {
Ok(vec![])
}
}
async fn create_resources_chirho(system_info: &SystemInfoChirho, base_url: &str) -> Result<(), Box<dyn Error>> {
let client_chirho = Client::new();
let api_key_chirho = env::var("API_KEY_CHIRHO").expect("API_KEY_CHIRHO must be set");
// Create host
let host_response_chirho: HostChirho = client_chirho
.post(&format!("{}/hosts_chirho", base_url))
.header("X-API-Key-Chirho", &api_key_chirho)
.json(&json!({
"hostname_chirho": system_info.hostname_chirho,
"operating_system_chirho": system_info.operating_system_chirho,
"ram_mb_chirho": system_info.ram_mb_chirho,
"cpu_cores_chirho": system_info.cpu_cores_chirho,
"storage_gb_chirho": system_info.storage_gb_chirho
}))
.send().await?
.json().await?;
// Create users and their SSH keys
for user_chirho in &system_info.users_chirho {
let user_response_chirho: UserChirho = client_chirho
.post(&format!("{}/users_chirho", base_url))
.header("X-API-Key-Chirho", &api_key_chirho)
.json(&json!({
"host_id_chirho": host_response_chirho.id_chirho,
"username_chirho": user_chirho.username_chirho,
"groups_chirho": user_chirho.groups_chirho.join(",")
}))
.send().await?
.json().await?;
for ssh_key_chirho in &user_chirho.ssh_keys_chirho {
let _: UserSshAuthorizedKeyChirho = client_chirho
.post(&format!("{}/ssh_keys_chirho", base_url))
.header("X-API-Key-Chirho", &api_key_chirho)
.json(&json!({
"user_id_chirho": user_response_chirho.id_chirho,
"ssh_key_chirho": ssh_key_chirho
}))
.send().await?
.json().await?;
}
}
Ok(())
}

+ 4
- 0
src/cli_chirho/mod.rs View File

@ -0,0 +1,4 @@
/*
* For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
*/
pub mod cli_chirho;

+ 150
- 0
src/models_chirho/host_model_chirho.rs View File

@ -0,0 +1,150 @@
/*
* For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
*/
use sqlx::FromRow;
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use rocket::{serde::json::Json};
use rocket_db_pools::{sqlx, Connection};
use sqlx::sqlite::{SqliteRow};
use sqlx::Row;
use crate::ApiKeyChirho;
use crate::models_chirho::DbChirho;
#[derive(FromRow, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HostChirho {
pub id_chirho: Option<i64>,
pub hostname_chirho: String,
pub operating_system_chirho: String,
pub ram_mb_chirho: i64,
pub cpu_cores_chirho: i64,
pub storage_gb_chirho: i64,
pub created_at: Option<NaiveDateTime>,
}
// Assuming the structs from the previous example are in scope
// use crate::models::HostChirho;
// HostChirho CRUD operations
#[get("/hosts_chirho")]
pub async fn list_hosts_chirho(_api_key: ApiKeyChirho, mut db_chirho: Connection<DbChirho>) -> Json<Vec<HostChirho>> {
let hosts_chirho = sqlx::query(
"SELECT * FROM hosts_chirho"
)
.map(|row: SqliteRow| HostChirho {
id_chirho: row.get("id_chirho"),
hostname_chirho: row.get("hostname_chirho"),
operating_system_chirho: row.get("operating_system_chirho"),
ram_mb_chirho: row.get("ram_mb_chirho"),
cpu_cores_chirho: row.get("cpu_cores_chirho"),
storage_gb_chirho: row.get("storage_gb_chirho"),
created_at: row.get("created_at"),
})
.fetch_all(&mut **db_chirho)
.await
.expect("Failed to fetch hosts_chirho");
Json(hosts_chirho)
}
#[post("/hosts_chirho", data = "<host_chirho>")]
pub async fn create_host_chirho(_api_key: ApiKeyChirho, mut db_chirho: Connection<DbChirho>, host_chirho: Json<HostChirho>) -> Json<HostChirho> {
let new_host_chirho = sqlx::query(
r#"
INSERT INTO hosts_chirho (hostname_chirho, operating_system_chirho, ram_mb_chirho, cpu_cores_chirho, storage_gb_chirho)
VALUES (?, ?, ?, ?, ?)
RETURNING *
"#
)
.bind(&host_chirho.hostname_chirho)
.bind(&host_chirho.operating_system_chirho)
.bind(host_chirho.ram_mb_chirho)
.bind(host_chirho.cpu_cores_chirho)
.bind(host_chirho.storage_gb_chirho)
.map(|row: SqliteRow| HostChirho {
id_chirho: row.get("id_chirho"),
hostname_chirho: row.get("hostname_chirho"),
operating_system_chirho: row.get("operating_system_chirho"),
ram_mb_chirho: row.get("ram_mb_chirho"),
cpu_cores_chirho: row.get("cpu_cores_chirho"),
storage_gb_chirho: row.get("storage_gb_chirho"),
created_at: row.get("created_at"),
})
.fetch_one(&mut **db_chirho)
.await
.expect("Failed to create host_chirho");
Json(new_host_chirho)
}
#[get("/hosts_chirho/<id_chirho>")]
pub async fn read_host_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64) -> Option<Json<HostChirho>> {
let host_chirho = sqlx::query(
"SELECT * FROM hosts_chirho WHERE id_chirho = ?"
)
.bind(id_chirho)
.map(|row: SqliteRow| HostChirho {
id_chirho: row.get("id_chirho"),
hostname_chirho: row.get("hostname_chirho"),
operating_system_chirho: row.get("operating_system_chirho"),
ram_mb_chirho: row.get("ram_mb_chirho"),
cpu_cores_chirho: row.get("cpu_cores_chirho"),
storage_gb_chirho: row.get("storage_gb_chirho"),
created_at: row.get("created_at"),
})
.fetch_optional(&mut **db_chirho)
.await
.expect("Failed to fetch host_chirho");
host_chirho.map(Json)
}
#[put("/hosts_chirho/<id_chirho>", data = "<host_chirho>")]
pub async fn update_host_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64, host_chirho: Json<HostChirho>) -> Option<Json<HostChirho>> {
let updated_host_chirho = sqlx::query(
r#"
UPDATE hosts_chirho
SET hostname_chirho = ?, operating_system_chirho = ?, ram_mb_chirho = ?, cpu_cores_chirho = ?, storage_gb_chirho = ?
WHERE id_chirho = ?
RETURNING *
"#
)
.bind(&host_chirho.hostname_chirho)
.bind(&host_chirho.operating_system_chirho)
.bind(host_chirho.ram_mb_chirho)
.bind(host_chirho.cpu_cores_chirho)
.bind(host_chirho.storage_gb_chirho)
.bind(id_chirho)
.map(|row: SqliteRow| HostChirho {
id_chirho: row.get("id_chirho"),
hostname_chirho: row.get("hostname_chirho"),
operating_system_chirho: row.get("operating_system_chirho"),
ram_mb_chirho: row.get("ram_mb_chirho"),
cpu_cores_chirho: row.get("cpu_cores_chirho"),
storage_gb_chirho: row.get("storage_gb_chirho"),
created_at: row.get("created_at"),
})
.fetch_optional(&mut **db_chirho)
.await
.expect("Failed to update host_chirho");
updated_host_chirho.map(Json)
}
#[delete("/hosts_chirho/<id_chirho>")]
pub async fn delete_host_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64) -> Option<()> {
let result_chirho = sqlx::query("DELETE FROM hosts_chirho WHERE id_chirho = ?")
.bind(id_chirho)
.execute(&mut **db_chirho)
.await
.expect("Failed to delete host_chirho");
if result_chirho.rows_affected() > 0 {
Some(())
} else {
None
}
}

+ 14
- 0
src/models_chirho/mod.rs View File

@ -0,0 +1,14 @@
/*
* For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
*/
use rocket_db_pools::Database;
use sqlx::SqlitePool;
pub mod host_model_chirho;
pub mod user_model_chirho;
pub mod user_ssh_authorized_key_chirho;
#[derive(Database)]
#[database("sqlite_database_chirho")]
pub struct DbChirho(SqlitePool);

+ 133
- 0
src/models_chirho/user_model_chirho.rs View File

@ -0,0 +1,133 @@
/*
* For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
*/
use sqlx::FromRow;
use chrono::NaiveDateTime;
use rocket::serde::{Deserialize, Serialize};
use rocket::{serde::json::Json};
use rocket_db_pools::{sqlx, Connection};
use sqlx::sqlite::{SqliteRow};
use sqlx::Row;
use crate::ApiKeyChirho;
use crate::models_chirho::DbChirho;
#[derive(FromRow, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UserChirho {
pub id_chirho: Option<i64>,
pub host_id_chirho: i64,
pub username_chirho: String,
pub groups_chirho: String,
pub created_at: Option<NaiveDateTime>,
}
#[get("/users_chirho")]
pub async fn list_users_chirho(_api_key: ApiKeyChirho, mut db_chirho: Connection<DbChirho>) -> Json<Vec<UserChirho>> {
let users_chirho = sqlx::query(
"SELECT * FROM users_chirho"
)
.map(|row: SqliteRow| UserChirho {
id_chirho: row.get("id_chirho"),
host_id_chirho: row.get("host_id_chirho"),
username_chirho: row.get("username_chirho"),
groups_chirho: row.get("groups_chirho"),
created_at: row.get("created_at"),
})
.fetch_all(&mut **db_chirho)
.await
.expect("Failed to fetch users_chirho");
Json(users_chirho)
}
#[post("/users_chirho", data = "<user_chirho>")]
pub async fn create_user_chirho(mut db_chirho: Connection<DbChirho>, user_chirho: Json<UserChirho>) -> Json<UserChirho> {
let new_user_chirho = sqlx::query(
r#"
INSERT INTO users_chirho (host_id_chirho, username_chirho, groups_chirho)
VALUES (?, ?, ?)
RETURNING *
"#
)
.bind(user_chirho.host_id_chirho)
.bind(&user_chirho.username_chirho)
.bind(&user_chirho.groups_chirho)
.map(|row: SqliteRow| UserChirho {
id_chirho: row.get("id_chirho"),
host_id_chirho: row.get("host_id_chirho"),
username_chirho: row.get("username_chirho"),
groups_chirho: row.get("groups_chirho"),
created_at: row.get("created_at"),
})
.fetch_one(&mut **db_chirho)
.await
.expect("Failed to create user_chirho");
Json(new_user_chirho)
}
#[get("/users_chirho/<id_chirho>")]
pub async fn read_user_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64) -> Option<Json<UserChirho>> {
let user_chirho = sqlx::query(
"SELECT * FROM users_chirho WHERE id_chirho = ?"
)
.bind(id_chirho)
.map(|row: SqliteRow| UserChirho {
id_chirho: row.get("id_chirho"),
host_id_chirho: row.get("host_id_chirho"),
username_chirho: row.get("username_chirho"),
groups_chirho: row.get("groups_chirho"),
created_at: row.get("created_at"),
})
.fetch_optional(&mut **db_chirho)
.await
.expect("Failed to fetch user_chirho");
user_chirho.map(Json)
}
#[put("/users_chirho/<id_chirho>", data = "<user_chirho>")]
pub async fn update_user_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64, user_chirho: Json<UserChirho>) -> Option<Json<UserChirho>> {
let updated_user_chirho = sqlx::query(
r#"
UPDATE users_chirho
SET host_id_chirho = ?, username_chirho = ?, groups_chirho = ?
WHERE id_chirho = ?
RETURNING *
"#
)
.bind(user_chirho.host_id_chirho)
.bind(&user_chirho.username_chirho)
.bind(&user_chirho.groups_chirho)
.bind(id_chirho)
.map(|row: SqliteRow| UserChirho {
id_chirho: row.get("id_chirho"),
host_id_chirho: row.get("host_id_chirho"),
username_chirho: row.get("username_chirho"),
groups_chirho: row.get("groups_chirho"),
created_at: row.get("created_at"),
})
.fetch_optional(&mut **db_chirho)
.await
.expect("Failed to update user_chirho");
updated_user_chirho.map(Json)
}
#[delete("/users_chirho/<id_chirho>")]
pub async fn delete_user_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64) -> Option<()> {
let result_chirho = sqlx::query("DELETE FROM users_chirho WHERE id_chirho = ?")
.bind(id_chirho)
.execute(&mut **db_chirho)
.await
.expect("Failed to delete user_chirho");
if result_chirho.rows_affected() > 0 {
Some(())
} else {
None
}
}

+ 123
- 0
src/models_chirho/user_ssh_authorized_key_chirho.rs View File

@ -0,0 +1,123 @@
/*
* For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
*/
use sqlx::FromRow;
use chrono::NaiveDateTime;
use rocket::serde::{Deserialize, Serialize};
use rocket::{serde::json::Json};
use rocket_db_pools::{sqlx, Connection};
use sqlx::sqlite::{SqliteRow};
use sqlx::Row;
use crate::ApiKeyChirho;
use crate::models_chirho::DbChirho;
#[derive(FromRow, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UserSshAuthorizedKeyChirho {
pub id_chirho: Option<i64>,
pub user_id_chirho: i64,
pub ssh_key_chirho: String,
pub created_at: Option<NaiveDateTime>
}
#[get("/ssh_keys_chirho")]
pub async fn list_ssh_keys_chirho(_api_key: ApiKeyChirho, mut db_chirho: Connection<DbChirho>) -> Json<Vec<UserSshAuthorizedKeyChirho>> {
let ssh_keys_chirho = sqlx::query(
"SELECT * FROM user_ssh_authorized_keys_chirho"
)
.map(|row: SqliteRow| UserSshAuthorizedKeyChirho {
id_chirho: row.get("id_chirho"),
user_id_chirho: row.get("user_id_chirho"),
ssh_key_chirho: row.get("ssh_key_chirho"),
created_at: row.get("created_at"),
})
.fetch_all(&mut **db_chirho)
.await
.expect("Failed to fetch ssh_keys_chirho");
Json(ssh_keys_chirho)
}
#[post("/ssh_keys_chirho", data = "<ssh_key_chirho>")]
pub async fn create_ssh_key_chirho(mut db_chirho: Connection<DbChirho>, ssh_key_chirho: Json<UserSshAuthorizedKeyChirho>) -> Json<UserSshAuthorizedKeyChirho> {
let new_ssh_key_chirho = sqlx::query(
r#"
INSERT INTO user_ssh_authorized_keys_chirho (user_id_chirho, ssh_key_chirho)
VALUES (?, ?)
RETURNING *
"#
)
.bind(ssh_key_chirho.user_id_chirho)
.bind(&ssh_key_chirho.ssh_key_chirho)
.map(|row: SqliteRow| UserSshAuthorizedKeyChirho {
id_chirho: row.get("id_chirho"),
user_id_chirho: row.get("user_id_chirho"),
ssh_key_chirho: row.get("ssh_key_chirho"),
created_at: row.get("created_at"),
})
.fetch_one(&mut **db_chirho)
.await
.expect("Failed to create ssh_key_chirho");
Json(new_ssh_key_chirho)
}
#[get("/ssh_keys_chirho/<id_chirho>")]
pub async fn read_ssh_key_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64) -> Option<Json<UserSshAuthorizedKeyChirho>> {
let ssh_key_chirho = sqlx::query(
"SELECT * FROM user_ssh_authorized_keys_chirho WHERE id_chirho = ?"
)
.bind(id_chirho)
.map(|row: SqliteRow| UserSshAuthorizedKeyChirho {
id_chirho: row.get("id_chirho"),
user_id_chirho: row.get("user_id_chirho"),
ssh_key_chirho: row.get("ssh_key_chirho"),
created_at: row.get("created_at"),
})
.fetch_optional(&mut **db_chirho)
.await
.expect("Failed to fetch ssh_key_chirho");
ssh_key_chirho.map(Json)
}
#[put("/ssh_keys_chirho/<id_chirho>", data = "<ssh_key_chirho>")]
pub async fn update_ssh_key_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64, ssh_key_chirho: Json<UserSshAuthorizedKeyChirho>) -> Option<Json<UserSshAuthorizedKeyChirho>> {
let updated_ssh_key_chirho = sqlx::query(
r#"
UPDATE user_ssh_authorized_keys_chirho
SET user_id_chirho = ?, ssh_key_chirho = ?
WHERE id_chirho = ?
RETURNING *
"#
)
.bind(ssh_key_chirho.user_id_chirho)
.bind(&ssh_key_chirho.ssh_key_chirho)
.bind(id_chirho)
.map(|row: SqliteRow| UserSshAuthorizedKeyChirho {
id_chirho: row.get("id_chirho"),
user_id_chirho: row.get("user_id_chirho"),
ssh_key_chirho: row.get("ssh_key_chirho"),
created_at: row.get("created_at"),
})
.fetch_optional(&mut **db_chirho)
.await
.expect("Failed to update ssh_key_chirho");
updated_ssh_key_chirho.map(Json)
}
#[delete("/ssh_keys_chirho/<id_chirho>")]
pub async fn delete_ssh_key_chirho(mut db_chirho: Connection<DbChirho>, id_chirho: i64) -> Option<()> {
let result_chirho = sqlx::query("DELETE FROM user_ssh_authorized_keys_chirho WHERE id_chirho = ?")
.bind(id_chirho)
.execute(&mut **db_chirho)
.await
.expect("Failed to delete ssh_key_chirho");
if result_chirho.rows_affected() > 0 {
Some(())
} else {
None
}
}

Loading…
Cancel
Save