advotracker: restructure project using crate tree

* advotracker: the framework crate
* crate/advotrackerdb: crate implementing the database backend
* crate/advotrackerd: the backend daemon
* crate/adovtracker: the application (CLI and GUI)

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
This commit is contained in:
2021-03-07 18:38:50 +01:00
parent 1ce1d029e5
commit 4c88167bef
185 changed files with 2542983 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
fn main() {
use advotracker_db::functions::db_connection::establish_connection;
use advotracker_db::models::harms::Harm;
let connection = establish_connection();
// function call
let vec_rows = Harm::get_all(&connection);
let rows = vec_rows.iter();
println!("Matching harms (count: {})", rows.len());
for row in rows {
println!("{:?}: {:?} {:?} {:?} {:?}",
row.id, row.id_harm, row.id_policyholder, row.id_callback, row.date_recording);
}
}

View File

@@ -0,0 +1,88 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
fn main() {
use diesel::RunQueryDsl;
use advotracker_db::functions::db_connection::establish_connection;
use advotracker_db::models::roles::Role;
use advotracker_db::schema::roles::dsl::*;
let connection = establish_connection();
// direct diesel method call
match roles
//.filter(name.eq("Administrator"))
.load::<Role>(&connection)
{
Err(err) => println!("{}", err),
Ok(rows) => {
println!("Matching roles (found: {})", rows.len());
//for row in rows {
// println!("{:?}: {:?}", row.id, row.name);
//}
//for field in role_row {
// println!("{}", field.id);
// println!("{}", field.name);
//}
}
}
// function call
let vec_rows = Role::get_all(&connection);
let rows = vec_rows.iter();
println!("Matching roles (count: {})", rows.len());
for row in rows {
println!("{:?}: {:?}", row.id, row.name);
}
// get a specific role, selected by attribute "name"
//let role_name = "Hacker";
let role_name = "Sekretariat";
println!("\nRole details for: {}", role_name);
let row = Role::get(&role_name, &connection).unwrap();
/*let row = match row {
Err(err) => println!("{}", err),
// will return a vector of matching rows
Ok(row) => {
//println!("\nNumber of matching rows: {}", row.len());
println!("Role id: {:?}", row[0].id);
println!("----------");
//println!("row: {:?}", row);
println!("Role name: {:?}", row[0].name);
println!("Role date_created: {:?}", row[0].date_created);
println!("Role updated by: {:?}", row[0].id_user_changed);
println!("Role date_changed: {:?}", row[0].date_changed);
}
};
*/
if row.len() > 0 {
println!("Role name: {:?}", row[0].name);
println!("Role date_created: {:?}", row[0].date_created);
println!("Role updated by: {:?}", row[0].id_user_changed);
println!("Role date_changed: {:?}", row[0].date_changed);
}
/*
// join tables "roles" and "users"
let join = roles::table.left_join(users::table);
// By default, all columns from both tables are selected
let role_struct = join
.select((roles::name, users::full_name.nullable()))
.load::<(String, Option<String>)>(&connection)?;
println!(
"\nRole id: {} (len: {})",
role_struct.name,
role_struct.len()
);
println!("----------\n");
println!("Role name: {}", role_struct.name);
*/
println!("Finish!");
}

View File

@@ -0,0 +1,59 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
fn main() {
use advotracker_db::functions::db_connection::establish_connection;
use advotracker_db::models::users::User;
let connection = establish_connection();
// function call
let vec_rows = User::get_all(&connection);
let rows = vec_rows.iter();
println!("Matching roles (count: {})", rows.len());
for row in rows {
println!("{:?}: {:?} {:?} {:?} {:?}",
row.id, row.last_name, row.first_name, row.email, row.password_hash);
}
/*
use advotracker_database::models::User;
use advotracker_database::schema::users::dsl::*;
let results = users
.load::<User>(&connection)
.expect("Error loading users");
//.filter(email_confirmed.eq(1))
//.limit(5)
//.filter(email_confirmed.eq(Confirmed))
//.limit(5)
println!("Displaying {} users", results.len());
for user in results {
println!("{}", user.id);
println!("----------\n");
println!("{:?}", user.first_name);
println!("{:?}", user.last_name);
println!("{:?}", user.alias);
println!("{:?}", user.email);
}
*/
/*
use advotracker_database::models::Role;
let results = roles
.load::<Role>(&connection)
.expect("Error loading Roles");
println!("Displaying {} roles", results.len());
for role in results {
println!("{}", role.id);
println!("----------\n");
println!("{:?}", role.name);
}
*/
}

View File

@@ -0,0 +1,71 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
fn main() {
use chrono::Local;
use std::io::{stdin, Read};
use advotracker_db::functions::db_connection::*;
use advotracker_db::models::harms::Harm;
let connection = establish_connection();
let number_harm = "123456789";
let number_policyholder = "110-123456789";
let number_callback = "0221 93123456789";
let date_fallback = Local::now().naive_local();
let date_recording = Local::now().naive_local();
// WIP: there is emptyness in the beginning
// how do we make sure, that there is a 'root' user?
// real world: this needs to be the id of the logged in user
let user_id = 1;
//let user_id_changed = 1;
println!("\nOk! I got the following:\nNumber Harm: {}", number_harm);
println!(
"Policyholder: {}, Number callback: {}",
number_policyholder, number_callback
);
println!(
"If correct, let's create this harm '{}'. (Press {} when finished)",
number_harm, EOF
);
let mut body = String::new();
stdin().read_to_string(&mut body).unwrap();
// insert as multicolon
let ret = Harm::new(
&number_harm,
Some(&number_policyholder),
Some(&number_callback),
Some(date_fallback),
date_recording,
user_id,
&connection,
);
println!("\nCreated new harm {}, returns {:?}", number_harm, ret);
// get a given harm
let harm_vec = Harm::get(number_harm, &connection);
println!("\nHarm: {:?}", harm_vec);
//let json = r#"{ "number_harm": "123456789", "number_policyholder": "110-123456789", "number_callback": "0221 92123456789", "user_id": 102, "user_id_changed": 101}"#;
//let json =
// r#"{ "number_harm": "123456789", "number_policyholder": null, "number_callback": null }"#;
//let harm_struct = serde_json::from_str::<NewHarm>(json);
//insert_into(harms).values(&harm_struct).execute(connection);
}
#[cfg(not(windows))]
const EOF: &str = "CTRL+D";
#[cfg(windows)]
const EOF: &str = "CTRL+Z";

View File

@@ -0,0 +1,78 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
fn main() {
use std::io::{stdin, Read};
use advotracker_db::functions::db_connection::*;
use advotracker_db::models::roles::Role;
let connection = establish_connection();
println!("Role name?");
let mut role_name = String::new();
stdin().read_line(&mut role_name).unwrap();
// Drop the newline character form our String slice
let role_name = &role_name[..(role_name.len() - 1)];
// WIP: there is emptyness in the beginning
// how do we make sure, that there is a 'root' user?
// real world: this needs to be the id of the logged in user
let user_id_changed = 1;
println!("\nOk! I got the following:\nRole Name: {}", role_name);
println!(
"If correct, let's create this role {}. (Press {} when finished)",
role_name, EOF
);
let mut body = String::new();
stdin().read_to_string(&mut body).unwrap();
// insert as multicolon
let ret = Role::new(role_name, user_id_changed, &connection);
println!("\nCreated new role {}, returns {:?}", role_name, ret);
// get a given role_name
let role_vec = Role::get(role_name, &connection);
println!("\nRole: {:?}", role_vec);
//println!(
// "\nRole parameter:\nRole name: {}\nUpdated via: {}",
// role_vec.name, role_vec.id_updated
//);
// update a given role_name
//role_id = 2;
//role_name = "New Freelancer";
//role_vec = Role::update(role_id, role_name, &connection);
//println!("\nRole: {:?}", role_vec);
let role_names = ["Administrator", "Rechtsanwalt", "Sekretariat"];
//let roles = role_names.iter();
for role_name in &role_names {
let _ = Role::new(role_name, user_id_changed, &connection);
}
//role_name = "Sekretariat";
//let _ = Role::new(role_name, user_id_changed, &connection);
/*
let inserted_count = insert_into(user_roles)
.values(&vec![
(id.eq(1), name.eq("Rechtsanwalt")),
(id.eq(2), name.eq("Administrator")),
])
.execute(&connection)?;
*/
println!("Saved Role {}", role_name);
}
#[cfg(not(windows))]
const EOF: &str = "CTRL+D";
#[cfg(windows)]
const EOF: &str = "CTRL+Z";

View File

@@ -0,0 +1,180 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
fn main() {
use std::io::{stdin, Read};
use advotracker_db::functions::db_connection::*;
use advotracker_db::models::users::User;
let connection = establish_connection();
/*
println!("Users first name?");
let mut last_name = String::new();
stdin().read_line(&mut last_name).unwrap();
let last_name = &last_name[..(last_name.len() - 1)]; // Drop the newline character
println!("Users last name?");
let mut first_name = String::new();
stdin().read_line(&mut first_name).unwrap();
let first_name = &first_name[..(first_name.len() - 1)];
println!("Users alias?");
let mut alias = String::new();
stdin().read_line(&mut alias).unwrap();
let alias = &alias[..(alias.len() - 1)];
println!("Users email?");
let mut email = String::new();
stdin().read_line(&mut email).unwrap();
let email = &email[..(email.len() - 1)];
let email_confirmed = 0;
println!("Users password?");
let mut password_hash = String::new();
stdin().read_line(&mut password_hash).unwrap();
let password_hash = &password_hash[..(password_hash.len() - 1)];
println!("Users initials?");
let mut initials = String::new();
stdin().read_line(&mut initials).unwrap();
let initials = &initials[..(initials.len() - 1)];
*/
let first_name = "Ralf";
let last_name = "Zerres";
let alias = "ralf.zerres";
let email = "ralf.zerres@networkx.de";
let initials = "rze";
let email_confirmed = 0;
let password_hash = "testrze";
let id_changed = 1;
println!(
"\nOk! I got the following:\nName: {} {}, Alias: {}",
first_name, last_name, alias
);
println!(
"Email-address: {}, Status: {}\nInitials: {}, Password: {}",
email, email_confirmed, initials, password_hash
);
println!(
"If correct, let's create this user {}. (Press {} when finished)",
last_name, EOF
);
let mut body = String::new();
stdin().read_to_string(&mut body).unwrap();
// insert as multicolon
let ret = User::new(
last_name,
Some(first_name),
Some(alias),
Some(email),
Some(email_confirmed),
password_hash,
Some(initials),
//date_create: null,
//date_updated: null,
id_changed,
&connection,
);
println!("\nCreated new user {}, returns {:?}", last_name, ret);
use serde_json::json;
// prepare full record
let _json_record = json!({
"first_name": "Daniela",
"last_name": "Knocke",
"alias": "Sekretariat",
"email": "knocke@kanzlei.hiedemann.de",
"email_confirmed": 1,
"password_hash": "",
"initials": "dkn",
"date_create": null,
"date_updated": null,
"id_changed": 1,
});
// println!(
// "\nCreate user {} via json record:\n{}",
// json_record["last_name"], json_record
// );
// ret = User::set_user_struct_json_option(&connection);
// println!(
// "Created new user {} via json-struct returns {:?}",
// json_record["last_name"], ret
//);
// insert as vector
/*
//connection.test_transaction::<_, Error, _>(|| {
//use diesel::select;
use schema::users::dsl::*;
//let now = select(diesel::dsl::now).get_result::<NaiveDateTime>(&connection);
//let now = select(diesel::dsl::now).get_result::<NaiveDateTime>(&connection);
let inserted_count = insert_into(users)
.values(&vec![
(last_name.eq("Networkx"), first_name.eq("Admin"), alias.eq("Networkx"),
email.eq("support@networkx.de")),
(last_name.eq("Schlömer"), first_name.eq("Lothar"), alias.eq("lothar.schlömer"),
email.eq("schlömer@kanzlei-hiedemann.de")),
])
.execute(&connection);
//});
*/
// Some data structure.
//use advotracker_db::models::users::User;
println!(
"\nCreate new json stuct representing user: {} {}",
first_name, last_name
);
let user = json!({
"first_name": first_name,
"last_name": last_name,
"alias": alias,
"email": email,
//"email_confirmed": 1,
//"password_hash": "",
"initials": initials,
//"date_create": null,
//"date_updated": null,
"id_changed": 1,
});
// Convert to a string of JSON and print it out
println!(
"json stuct representing user: {} {}",
user["last_name"],
user.to_string()
);
// Serialize it to a JSON string.
let json = serde_json::to_string(&user);
// Print, write to a file, or send to an HTTP server.
println!("Serialized output: {:?}", json);
/*
let user_id = 1;
let role_id = 1;
use advotracker_db::functions::roles::*;
let _ = set_user_role(&connection, &user_id, &role_id);
*/
}
#[cfg(not(windows))]
const EOF: &str = "CTRL+D";
#[cfg(windows)]
const EOF: &str = "CTRL+Z";

View File

@@ -0,0 +1,33 @@
// source: https://github.com/inejge/ldap3
//use std::error::Error;
//use ldap3::{LdapConn, Scope, SearchEntry};
fn main() {
println!("search ldap ...");
/*
match do_search() {
Ok(_) => (),
Err(e) => println!("{}", e),
}
}
fn do_search() -> Result<(), Box<dyn Error>> {
println!("do_search ...");
/*
let ldap = LdapConn::new("ldap://localhost:2389")?;
let (rs, _res) = ldap
.search(
"ou=Places,dc=example,dc=org",
Scope::Subtree,
"(&(objectClass=locality)(l=ma*))",
vec!["l"],
)?
.success()?;
for entry in rs {
println!("{:?}", SearchEntry::construct(entry));
}
*/
Ok(())
*/
}

View File

@@ -0,0 +1,42 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
//use diesel::debug_query;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;
use diesel::sqlite::Sqlite;
use dotenv::dotenv;
use std::env;
/// establish a sqlite connection
pub fn establish_connection() -> SqliteConnection {
// load our .env file
dotenv().ok();
// set database_url to the given DATABASE_URL env variable
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
// establish a new SQLite connection (taking the reference from database_url)
SqliteConnection::establish(&database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &database_url))
/*
* WIP: integrate tracing!
trace!(
target: "diesel",
type: "Sqlite3",
status: "connected"
);
*/
}
/// show the sql query
pub fn show_query<T>(query: &T)
where
T: diesel::query_builder::QueryFragment<Sqlite>,
{
dbg!(diesel::debug_query::<Sqlite, _>(&query));
}

View File

@@ -0,0 +1,196 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
//#[cfg(test)]
use chrono::{Local, NaiveDateTime};
use diesel;
use diesel::debug_query;
use diesel::dsl::*;
use diesel::prelude::*;
use diesel::sqlite::{Sqlite, SqliteConnection};
use diesel::{QueryDsl, RunQueryDsl};
use std::error::Error;
use crate::models::harms::{Harm, NewHarm};
use crate::schema::harms;
use crate::schema::harms::dsl::*;
use crate::schema::harms::*;
impl Harm {
// implement CRUD-Functions
// new- -> Create
// get- -> Read
// set- -> Update
// remove- -> Delete
/// create a new harm record
pub fn new(
param_id_harm: &str,
param_id_policyholder: Option<&str>,
param_id_callback: Option<&str>,
param_date_fallback: Option<NaiveDateTime>,
param_date_recording: NaiveDateTime,
param_id_user: i32,
connection: &SqliteConnection,
) -> Result<(), Box<dyn Error>> {
let struct_harm = NewHarm {
id_harm: param_id_harm,
id_policyholder: param_id_policyholder,
id_callback: param_id_callback,
date_fallback: param_date_fallback,
date_recording: param_date_recording,
id_user: param_id_user,
date_created: Some(Local::now().naive_local()),
id_user_changed: param_id_user,
date_changed: Some(Local::now().naive_local()),
};
diesel::insert_into(harms::table)
.values(struct_harm)
.execute(connection)?;
Ok(())
}
/*
pub fn delete(param_hame_id: i32, connection: &SqliteConnection) -> Result<(), Box<dyn Error>> {
diesel::delete(dsl::harms.filter(dsl::id.eq(param_role_id)).find(id)).execute(connection)?;
Ok(())
// alternative:
// let old_count = get_count();
// assert_eq!(old_count.map(|count| count - 1), get_count());
}
*/
/// get list of all harm record
pub fn get_all(connection: &SqliteConnection) -> Box<Vec<Harm>> {
Box::new(
harms
.order(harms::id.asc())
.load::<Harm>(connection)
.expect("Error loading harms"),
)
}
/// get harm record
pub fn get(
param_id_harm: &str,
connection: &SqliteConnection,
) -> Result<Vec<Harm>, Box<dyn Error>> {
let query = harms
.filter(id_harm.eq(param_id_harm))
.load::<Harm>(connection)
.expect("Error loading harm");
debug_query::<Sqlite, _>(&query);
Ok(query)
}
/// update harm record
pub fn update(
param_id: i32,
param_id_harm: &str,
connection: &SqliteConnection,
) -> Result<(), Box<dyn Error>> {
let query = diesel::update(harms.filter(id.eq(param_id)))
.set(id_harm.eq(param_id_harm))
.execute(connection);
debug_query::<Sqlite, _>(&query);
Ok(())
}
}
/// set a test harm record
pub fn set_harms_single_column(connection: &SqliteConnection) -> QueryResult<usize> {
insert_into(harms)
.values(id_harm.eq("123456789"))
.execute(connection)
}
#[test]
/// examine the test harm record
fn examine_set_harms_single_column() {
let query = insert_into(harms).values(id_harm.eq("123456789"));
let sql = "INSERT INTO `harms` (`id_harm`) VALUES (?) \
-- binds: [\"123456789\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/// set multiple collumns for the test harm record
pub fn set_harms_multi_column(connection: &SqliteConnection) -> QueryResult<usize> {
insert_into(harms)
.values((
id_harm.eq("123456789"),
id_policyholder.eq("110-123456789"),
id_callback.eq("0221 93123456789"),
))
.execute(connection)
}
// #[test]
// fn examine_set_harms_multi_column() {
// let query = insert_into(harms).values((
// id_harm.eq("123456789"),
// id_policyholder.eq("110-123456789"),
// id_callback.eq("0221 93123456789"),
// ));
// let sql = "INSERT INTO `harms` (`id_harm`, `id_policyholder`, `id_callback`) \
// VALUES (?, ?, ?) \
// -- binds: [\"123456789\", \"110-123456789\", \"0221 93123456789\"]";
// assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
// }
// pub fn set_harms_struct_json(connection: &SqliteConnection) -> Result<(), Box<dyn Error>> {
// let json = r#"{ "id_harm": "123456789", "id_policyholder": "110-123456789", "id_callback": "0221 92123456789", "date_recording": "2019-11-16 20:00:15.114957766"}"#;
// //let harm_struct = serde_json::from_str::<NewHarm>(json)?;
// let harm_struct = serde_json::from_str::<'_>(json)?;
// insert_into(harms)
// .values(&harm_struct)
// .execute(connection)?;
// Ok(())
// }
// #[test]
// fn examine_set_harms_struct_json() {
// let json = r#"{ "id_harm": "123456789", "id_policyholder": "110-123456789", "id_callback": "0221 93123456789", "date_recording": "2019-11-19T00:08:00", "id_user": 102, "id_user_changed": 101 }"#;
// let harm_struct = serde_json::from_str::<NewHarm>(json).unwrap();
// let query = insert_into(harms).values(&harm_struct);
// let sql =
// "INSERT INTO `harms` (`id_harm`, `id_policyholder`, `id_callback`, `date_recording`, `id_user`, `id_user_changed`) \
// VALUES (?, ?, ?, ?, ?, ?) \
// -- binds: [\"123456789\", \"110-123456789\", \"0221 93123456789\", 2019-11-19T00:08:00, 102, 101]";
// assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
// }
// pub fn set_harms_struct_json_option(connection: &SqliteConnection) -> Result<(), Box<dyn Error>> {
// let json = r#"{ "id_harm": "123456789", "id_policyholder": null, "id_callback": null, "date_recording": "2019-11-19T00:08:00", 102, 101 }"#;
// let harm_struct = serde_json::from_str::<'_>(json)?;
// insert_into(harms)
// .values(&harm_struct)
// .execute(connection)?;
// Ok(())
// }
// #[test]
// fn examine_set_harms_struct_json_option() {
// let json = r#"{ "id_harm": "123456789", "id_policyholder": null, "id_callback": null, "date_recording": "2019-11-19T00:08:00", "id_user": 102, "id_user_changed": 101 }"#;
// let harm_struct = serde_json::from_str::<NewHarm>(json).unwrap();
// let query = insert_into(harms).values(&harm_struct);
// let sql = "INSERT INTO `harms` (`id_harm`, `date_recording`, `id_user`, `id_user_changed`) \
// VALUES (?, ?, ?, ?) \
// -- binds: [\"123456789\", 2019-11-19T00:08:00, 102, 101]";
// assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
// }

View File

@@ -0,0 +1,25 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
// table specific functions
/// module handling database connections
pub mod db_connection;
/// module handling harms
pub mod harms;
/// module handling roles
pub mod roles;
/// module handling user roles
pub mod user_roles;
/// module handling users
pub mod users;
/// module handling functionalty tests
pub mod tests;

View File

@@ -0,0 +1,105 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
//#[cfg(test)]
use chrono::Local;
use diesel::debug_query;
use diesel::prelude::*;
use diesel::sqlite::{Sqlite, SqliteConnection};
use diesel::{QueryDsl, RunQueryDsl};
use std::error::Error;
//use crate::functions::establish_connection;
//use crate::models::roles::{NewRole, Role, RoleList};
use crate::models::roles::{NewRole, Role};
use crate::schema::roles;
use crate::schema::roles::dsl::*;
use crate::schema::roles::*;
impl Role {
// implement CRUD-Functions for our trait
// new- -> Create
// show- -> Read
// update- -> Update
// delete- -> Delete
/// create a new role record
pub fn new(
param_role_name: &str,
param_id_user_changed: i32,
connection: &SqliteConnection,
) -> Result<(), Box<dyn Error>> {
//let row = Self::get(param_role_name, param_user_id_changed, &connection);
//if row.len() == 0 {
// create a new role row
let struct_role = NewRole {
name: param_role_name,
date_created: Some(Local::now().naive_local()),
id_user_changed: param_id_user_changed,
date_changed: Some(Local::now().naive_local()),
};
diesel::insert_into(roles::table)
.values(struct_role)
.execute(connection)?;
Ok(())
//else {
// Err(("row already exists!"))
//}
}
/*
pub fn delete(param_role_id: i32, connection: &SqliteConnection) -> Result<(), Box<dyn Error>> {
diesel::delete(dsl::roles.filter(dsl::id.eq(param_role_id)).find(id)).execute(connection)?;
Ok(())
// alternative:
// let old_count = get_count();
// assert_eq!(old_count.map(|count| count - 1), get_count());
}
*/
/// get all role records
pub fn get_all(connection: &SqliteConnection) -> Box<Vec<Role>> {
Box::new(
roles
.order(roles::id.asc())
.load::<Role>(connection)
.expect("Error loading roles"),
)
}
/// get a role record
pub fn get(
param_role_name: &str,
connection: &SqliteConnection, //) -> Vec<Role> {
) -> Result<Vec<Role>, Box<dyn Error>> {
let query = roles
.filter(name.eq(param_role_name))
.load::<Role>(connection)
.expect("Error loading roles");
debug_query::<Sqlite, _>(&query);
Ok(query)
}
/// update a role record
pub fn update(
param_id: i32,
param_role_name: &str,
connection: &SqliteConnection,
) -> Result<(), Box<dyn Error>> {
let query = diesel::update(roles.filter(id.eq(param_id)))
.set(name.eq(param_role_name))
.execute(connection);
debug_query::<Sqlite, _>(&query);
Ok(())
}
}

View File

@@ -0,0 +1,192 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
#[cfg(test)]
use diesel::debug_query;
use diesel::dsl::*;
use diesel::prelude::*;
#[cfg(test)]
use diesel::sqlite::Sqlite;
#[cfg(test)]
use diesel::sqlite::SqliteConnection;
use crate::schema;
/// set user defaults
pub fn set_users_default_values(connection: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
insert_into(users).default_values().execute(connection)
}
#[test]
/// examine results when setting user defaults
fn examine_set_users_default_values() {
use schema::users::dsl::*;
let query = insert_into(users).default_values();
let sql = "INSERT INTO `users` DEFAULT VALUES -- binds: []";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/// set user defaults
pub fn set_roles_default_values(connection: &SqliteConnection) -> QueryResult<usize> {
use schema::roles::dsl::*;
insert_into(roles).default_values().execute(connection)
}
#[test]
/// examine results when setting user defaults
fn examine_set_roles_default_values() {
use schema::roles::dsl::*;
let query = insert_into(roles).default_values();
let sql = "INSERT INTO `roles` DEFAULT VALUES -- binds: []";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/// set user roles defaults
pub fn set_user_roles_default_values(connection: &SqliteConnection) -> QueryResult<usize> {
use schema::user_roles::dsl::*;
insert_into(user_roles).default_values().execute(connection)
}
#[test]
/// examine results when setting user roles defaults
fn examine_set_user_roles_default_values() {
use schema::user_roles::dsl::*;
let query = insert_into(user_roles).default_values();
let sql = "INSERT INTO `user_roles` DEFAULT VALUES -- binds: []";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/// set harm defaults
pub fn set_harms_default_values(connection: &SqliteConnection) -> QueryResult<usize> {
use schema::harms::dsl::*;
insert_into(harms).default_values().execute(connection)
}
#[test]
/// examine results when setting harm defaults
fn examine_set_harms_default_values() {
use schema::harms::dsl::*;
let query = insert_into(harms).default_values();
let sql = "INSERT INTO `harms` DEFAULT VALUES -- binds: []";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/// set a users email-confirmed column
pub fn set_users_email_confirmed(connection: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
diesel::update(users)
.set(email_confirmed.eq(1))
.execute(connection)
}
/// set a user column
pub fn set_users_single_column(connection: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
insert_into(users)
.values(alias_name.eq("Hiedemann"))
.execute(connection)
}
#[test]
/// examine results when setting a single user column
fn examine_set_users_single_column() {
use schema::users::dsl::*;
let query = insert_into(users).values(alias_name.eq("Hiedemann"));
let sql = "INSERT INTO `users` (`alias_name`) VALUES (?) \
-- binds: [\"Hiedemann\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/// set multiple user columns
pub fn set_users_multiple_columns(connection: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
insert_into(users)
.values((
first_name.eq("Lothar"),
last_name.eq("Schlömer"),
alias_name.eq("102"),
))
.execute(connection)
}
#[test]
/// examine results when setting multiple user columns
fn examine_set_user_multiple_columns() {
use schema::users::dsl::*;
let query = diesel::insert_into(users).values((
first_name.eq("Lothar"),
last_name.eq("Schlömer"),
alias_name.eq("102"),
));
let sql = "INSERT INTO `users` (`first_name`, `last_name`, `alias_name`) \
VALUES (?, ?, ?) \
-- binds: [\"Lothar\", \"Schlömer\", \"102\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/*
#[test]
/// examine results when setting user columns via json
fn examine_set_user_struct_json() {
use crate::models::users::NewUser;
use schema::users::dsl::*;
//use serde_json::json;
/*_let json_struct = json!({
"last_name": "Knocke",
"first_name": "Daniela",
"alias_name": "Sekretariat",
"email": "knocke@kanzlei.hiedemann.de",
"email_confirmed": 1,
"password_hash": "",
"initials": "dkn",
"date_create": "2019-11-16 20:00:14.114957766",
"id_changed": 1,
"date_changed": "2019-11-16 20:00:15.114957766",
});*/
let json = r#"{ "last_name": "Knocke", "first_name": "Daniela", "alias_name": "Sekretariat", "email": "knocke@kanzlei.hiedemann.de", "email_confirmed": 1, "initials": "dkn", "password_hash": "testpassword", "date_created": "2019-11-16 20:00:14.114957766", "id_changed": 1", "date_changed": "2019-11-16 20:00:15.114957766" }"#;
let user_struct = serde_json::from_str::<NewUser>(json).unwrap();
let query = diesel::insert_into(users).values(&user_struct);
//let query = serde_json::from_str::<User>(&json_struct);
let sql = "diesel::INSERT INTO `users` (`last_name`, `first_name`, `alias_name`, `email`, `email_confirmed`, `initials`, `password_hash`, `date_create`, `id_changed`, `data_updated`) \
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) \
-- binds: [\"Knocke\", \"Daniela\", \"Sekretariat\", \"knocke@kanzlei.hiedemann.de\", 1, \"dkn\", \"testpassword\", \"2019-11-16 20:00:14.114957766\", 1, \"2019-11-16 20:00:15.114957766\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
*/
#[test]
/// examine results when setting user columns via json options
fn examine_set_user_struct_json_option() {
//use crate::models::users::NewUser;
use schema::users::dsl::*;
use serde_json;
let json = r#"{ "last_name": "Knocke", "first_name": null, "alias_name": null, "email": "knocke@kanzlei.hiedemann.de", "email_confirmed": 1, "initials": "dkn", "password_hash": "test", "date_created": null, "id_changed": 1, "date_changed": null }"#;
let user_struct = serde_json::from_str::<'_>(json).unwrap();
let query = diesel::insert_into(users).values(&user_struct);
let sql = "INSERT INTO `users` (`last_name`, `email`, `email_confirmed`, `initials`, `password_hash`, `id_changed`) \
VALUES (?, ?, ?, ?, ?, ?) \
-- binds: [\"Knocke\", \"knocke@kanzlei.hiedemann.de\", 1, \"dkn\", \"test\", 1]";
//assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}

View File

@@ -0,0 +1,79 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
//#[cfg(test)]
use diesel::debug_query;
use diesel::prelude::*;
use diesel::sqlite::{Sqlite, SqliteConnection};
use diesel::{QueryDsl, RunQueryDsl};
use std::error::Error;
use crate::models::user_roles::{NewUserRole, UserRole};
use crate::schema::user_roles;
use crate::schema::user_roles::dsl::*;
use crate::schema::user_roles::*;
impl UserRole {
/// create a new user role record
pub fn new(
param_id_user: i32,
param_id_role: i32,
connection: &SqliteConnection,
) -> Result<(), Box<dyn Error>> {
let struct_user_role = NewUserRole {
id_user: param_id_user,
id_role: param_id_role,
//date_created: Some(Local::now().naive_local()),
//id_user_changed: param_id_user_changed,
//date_changed: Some(Local::now().naive_local()),
};
diesel::insert_into(user_roles::table)
.values(struct_user_role)
.execute(connection)?;
Ok(())
}
/// get a list of all user role records
pub fn get_all(connection: &SqliteConnection) -> Box<Vec<UserRole>> {
Box::new(
user_roles
.order(user_roles::id_user.asc())
.load::<UserRole>(connection)
.expect("Error loading user_roles"),
)
}
/// get a user role record
pub fn get(
param_id_role: i32,
connection: &SqliteConnection,
) -> Result<Vec<UserRole>, Box<dyn Error>> {
let query = user_roles
.filter(id_role.eq(param_id_role))
.load::<UserRole>(connection)
.expect("Error loading user_roles");
debug_query::<Sqlite, _>(&query);
Ok(query)
}
/// update a user role record
pub fn update(
param_id_user: i32,
param_id_role: i32,
connection: &SqliteConnection,
) -> Result<(), Box<dyn Error>> {
let query = diesel::update(user_roles.filter(id_user.eq(param_id_user)))
.set(id_role.eq(param_id_role))
.execute(connection);
debug_query::<Sqlite, _>(&query);
Ok(())
}
}

View File

@@ -0,0 +1,189 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use bcrypt::{hash, DEFAULT_COST};
use chrono::Local;
use diesel::debug_query;
use diesel::prelude::*;
use diesel::sqlite::Sqlite;
#[cfg(test)]
use diesel::sqlite::SqliteConnection;
use diesel::{QueryDsl, RunQueryDsl};
// WIP: json functionality need work!
// use serde_json;
use std::error::Error;
//use crate::models::users::{NewUser, RegisterUser, User, UserList};
use crate::models::users::{NewUser, RegisterUser, User};
use crate::schema::users;
use crate::schema::users::dsl::*;
impl User {
// implement CRUD-Functions
// new- -> Create
// get- -> Read
// set- -> Update
// remove- -> Delete
/// create a new user record
pub fn new(
param_last_name: &str,
param_first_name: Option<&str>,
param_alias_name: Option<&str>,
param_email: Option<&str>,
param_email_confirmed: Option<i32>,
param_password_hash: &str,
param_initials: Option<&str>,
param_id_user: i32,
connection: &SqliteConnection,
) -> Result<(), Box<dyn Error>> {
let struct_user = NewUser {
last_name: param_last_name,
first_name: param_first_name,
alias_name: param_alias_name,
email: param_email,
email_confirmed: param_email_confirmed,
password_hash: param_password_hash,
//password_hash: Self::hash_password(param_password_hash.to_string()).unwrap(),
initials: param_initials,
date_created: Some(Local::now().naive_local()),
id_changed: param_id_user,
date_changed: Some(Local::now().naive_local()),
};
diesel::insert_into(users::table)
.values(struct_user)
.execute(connection)?;
Ok(())
}
/// get a list of all user records
pub fn get_all(connection: &SqliteConnection) -> Box<Vec<User>> {
Box::new(
users
.order(users::id.asc())
.load::<User>(connection)
.expect("Error loading users"),
)
}
/*
pub fn get(
param_last_name: &str,
connection: &SqliteConnection,
) -> Result<Vec<User>, Box<dyn Error>> {
let query = users
.filter(last_name.eq(param_last_name))
.load::<User>(connection)
.expect("Error loading users");
debug_query::<Sqlite, _>(&query);
Ok(query)
}
*/
/// update a user record
pub fn update(param_id: i32, connection: &SqliteConnection) -> Result<(), Box<dyn Error>> {
let query = users.filter(id.eq(param_id)).execute(connection)?;
debug_query::<Sqlite, _>(&query);
Ok(())
}
/// create a hash value for the user password
pub fn hash_password(plain: &str) -> Result<String, Box<dyn Error>> {
Ok(hash(plain, DEFAULT_COST)?)
}
/// update the confirmation status of a user emak address
pub fn set_users_email_confirmed(connection: &SqliteConnection) -> QueryResult<usize> {
diesel::update(users)
.set(email_confirmed.eq(1))
.execute(connection)
}
/// update a singel column of a given user record
pub fn set_users_single_column(connection: &SqliteConnection) -> QueryResult<usize> {
diesel::insert_into(users)
.values(alias_name.eq("Hiedemann"))
.execute(connection)
}
/// update multiple columns of a given user record
pub fn set_users_multiple_columns(connection: &SqliteConnection) -> QueryResult<usize> {
diesel::insert_into(users)
.values((
first_name.eq("Lothar"),
last_name.eq("Schlömer"),
alias_name.eq("102"),
))
.execute(connection)
}
// /// update multiple columns of a given user record with a json string
// pub fn set_user_struct_json(connection: &SqliteConnection) -> Result<(), Box<dyn Error>> {
// let json = r#"{ "first_name": "Daniela", "last_name": "Knocke", "alias_name": "Sekretariat", "email": "knocke@kanzlei.hiedemann.de", "email_confirmed": 1, "password_hash": "", "initials": "dkn" }"#;
// //let user_struct = serde_json::from_str::<NewUser>(json)?;
// let user_struct = serde_json::from_str::<'_>(json)?;
// diesel::insert_into(users)
// .values(&user_struct)
// .execute(connection)?;
// Ok(())
// }
// pub fn set_user_struct_json_option(
// connection: &SqliteConnection,
// ) -> Result<(), Box<dyn Error>> {
// let json = r#"{ "first_name": null, "last_name": "Knocke", "alias_name": null, "email": "knocke@kanzlei.hiedemann.de", "email_confirmed": 1, "password_hash": "", "initials": "dkn", "id_changed": 1 }"#;
// let user_form = serde_json::from_str::<'_>(json)?;
// diesel::insert_into(users)
// .values(&user_form)
// .execute(connection)?;
// Ok(())
//}
}
impl<'a> RegisterUser<'a> {
//pub fn validates(self) -> Result<(), Error> {
/// validate the password hash
pub fn validates(self) -> Result<RegisterUser<'a>, &'static str> {
let password_are_equal = self.password_hash == self.password_confirmation;
let password_not_empty = self.password_hash.len() > 0;
if password_are_equal && password_not_empty {
Ok(self)
//else if !password_are_equal {
// Err("Password and Password Confirmation does not match")
} else {
Err("Wrong Password, check it is not empty")
}
}
/*
pub fn get_all(
connection: &SqliteConnection,
//) -> Product {
//) -> Box<Vec<User>> {
) -> Result<Vec<User>, Box<dyn Error>> {
let data = users
.filter(last_name.like("H%"))
//.order(users::id.desc())
.load(connection)?;
debug_query::<Sqlite, _>(&data);
Ok(data)
// We return a value by leaving it without a comma
//UserList(all_users)
}
*/
}

View File

@@ -0,0 +1,139 @@
// WIP
use diesel::dsl::*;
use diesel::prelude::*;
//#[cfg(test)]
//use diesel::sqlite::Sqlite;
//#[cfg(test)]
//use diesel::sqlite::SqliteConnection;
//use serde_derive;
//use std::error::Error;
use crate::schema;
pub fn set_users_single_column_batch(conn: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
insert_into(users)
.values(&vec![last_name.eq("Zerres"), last_name.eq("Plank")])
.execute(conn)
}
/*
#[test]
fn examine_sql_users_insert_get_results() {
use diesel::result::Error;
let connection = establish_connection();
connection.test_transaction::<_, Error, _>(|| {
use diesel::select;
use diesel::dsl;
use chrono::NaiveDateTime;
use schema::users::dsl::*;
use models::insert::NewUser;
//use models::User;
//let now = select(dsl::now).get_result::<NaiveDateTime>(&connection)?;
let inserted_users = connection.transaction::<_, Error, _>(|| {
let inserted_count = insert_into(users)
.values(&vec![
(id.eq(1), last_name.eq("Hiedemann"), first_name.eq("Eric"),
alias.eq("Eric.Hiedemann"), email_confirmed.eq(0),initials.eq("EH")),
(id.eq(2), last_name.eq("Schlömer"), first_name.eq("Lothar"),
alias.eq("Lothar.Schlömer"), email_confirmed.eq(0), initials.eq("LS")),
])
.execute(&connection)?;
Ok(users
.order(id.desc())
.limit(inserted_count as i64)
.load(&connection)?
.into_iter()
.rev()
.collect::<Vec<_>>())
})?;
let expected_users = vec![
NewUser {
//id: 1,
last_name: "Hiedemann".into(),
first_name: "Eric".into(),
alias: "Eric.Hiedemann".into(),
email: "".into(),
email_confirmed: 0,
password_hash: "".into(),
initials: "EH".into(),
//date_created: now,
//date_updated: now,
},
NewUser {
//id: 2,
last_name: "Schlömer".into(),
first_name: "Lothar".into(),
alias: "Lothar.Schlömer".into(),
email: "".into(),
email_confirmed: 0,
password_hash: "".into(),
initials: ("LS").into(),
//date_created: now,
//date_updated: now,
},
];
//assert_eq!(expected_users, inserted_users);
Ok(())
});
}
*/
/*
pub fn create_numberharm<'a>(connection: &SqliteConnection, NumberHarm: &'a str) {
let numberHarm = models::NewNumberHarm { NumberHarm };
diesel::insert_into(schema::NumberHarm::table)
.values(&numberHarm)
.execute(connection)
.expect("Error inserting new task");
}
*/
/*
pub fn create_userid<'a>(connection: &SqliteConnection, User: &'a str) {
let user = models::NewUser { User };
diesel::insert_into(schema::User::table)
.values(&user)
.execute(connection)
.expect("Error inserting new task");
}
*/
/*
pub fn create_userclaimid<'a>(connection: &SqliteConnection, UserClaim: &'a str) {
let userClaim = models::NewUserClaim { UserClaim };
diesel::insert_into(schema::UserClaim::table)
.values(&userClaim)
.execute(connection)
.expect("Error inserting new task");
}
pub fn create_userrole<'a>(connection: &SqliteConnection, UserRole: &'a str) {
let userRole = models::NewUserRole { UserRole };
diesel::insert_into(schema::UserRole::table)
.values(&userRole)
.execute(connection)
.expect("Error inserting new task");
}
pub fn create_useruserrole<'a>(connection: &SqliteConnection, UserUserRole: &'a str) {
let userUserRole = models::NewUserUserRole { UserUserRole };
diesel::insert_into(schema::UserUserRole::table)
.values(&userUserRole)
.execute(connection)
.expect("Error inserting new task");
}
*/

View File

@@ -0,0 +1,31 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
#![warn(missing_docs, rust_2018_idioms, rust_2018_compatibility)]
#![recursion_limit="256"]
#![warn(clippy::pedantic)]
//#![warn(clippy::nursery)]
//! advotracker database
//! Supports lawyers to capture relevant data encountered during an
//! online legal advice.
//! This SQL database backend will consuming Diesel to make use of
//! sql features.
// ?? is this needed in edition 2018 anymore ??
#[macro_use]
extern crate diesel;
/// SQL functions and methods
pub mod functions;
/// SQL models definitions
pub mod models;
/// SQL schema definitions
pub mod schema;

View File

@@ -0,0 +1,8 @@
--- src/schema.rs.orig 2020-06-30 13:35:01.826955973 +0200
+++ src/schema.rs 2020-06-30 13:35:26.640286611 +0200
@@ -1,3 +1,5 @@
+#![allow(missing_docs)]
+
table! {
claims (id) {
id -> Integer,

View File

@@ -0,0 +1,32 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use crate::schema::claim;
/// Stucture of a claim record
#[derive(Debug, Queryable)]
pub struct Claim {
/// the auto incremented primary index
pub id: i32,
/// the user id
pub user_id: i32,
/// the type of the user
pub type_: Option<String>,
/// the name string of the claim type
pub value: Option<String>,
}
/// Structure of a new claim record
#[derive(Debug, Deserialize, Insertable)]
#[table_name = "claims"]
pub struct NewClaim<'a> {
//pub user_id: &'a i32,
/// Lifetime to the claim type
pub type_: Option<&'a str>,
/// Lifetime to the name of the claim type
pub value: Option<&'a str>,
}

View File

@@ -0,0 +1,60 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use crate::schema::harms;
/// Manage harm records (SELECT, UPDATE, DELETE)
#[derive(AsChangeset, Debug, Deserialize, Identifiable, PartialEq, Queryable)]
pub struct Harm {
/// the auto incremented primary index
pub id: i32,
/// the harm name
pub id_harm: String,
/// the policy holder name
pub id_policyholder: Option<String>,
/// the callback number
pub id_callback: Option<String>,
/// the fallback date
pub date_fallback: Option<NaiveDateTime>,
/// the date the record was recorded
pub date_recording: NaiveDateTime,
/// the user id
pub id_user: i32,
/// the date the record was created
pub date_created: NaiveDateTime,
/// the user id that has chanced the record
pub id_user_changed: i32,
/// the date the record was changed
pub date_changed: NaiveDateTime,
}
/// Structure of a new harm
#[derive(Debug, Deserialize, Insertable, Serialize)]
#[table_name = "harms"]
pub struct NewHarm<'a> {
/// Lifetime to the harm name
pub id_harm: &'a str,
/// Lifetime to the policyholder
pub id_policyholder: Option<&'a str>,
/// Lifetime to the callback number
pub id_callback: Option<&'a str>,
/// the fallback date
pub date_fallback: Option<NaiveDateTime>,
/// the date the record was recorded
pub date_recording: NaiveDateTime,
/// the user id that has chanced the record
pub id_user: i32,
/// the date the record was created
pub date_created: Option<NaiveDateTime>,
/// the user id that has chanced the record
pub id_user_changed: i32,
/// Lifetime to the date the record was changed
pub date_changed: Option<NaiveDateTime>,
}

View File

@@ -0,0 +1,15 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use crate::schema::*;
//use chrono::NaiveDateTime;
use serde_derive::*;
//use types::*;
//use crate::models::types::*;
//use serde::*;
pub mod types;

View File

@@ -0,0 +1,22 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
/// defining roles
pub mod roles;
/// defining harms
pub mod harms;
/// defining users
pub mod users;
/// defining user roles
pub mod user_roles;
// methods used for: INSERT
//pub mod insert;
//use insert::types::*;

View File

@@ -0,0 +1,47 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use crate::schema::roles;
/// Structure of a role record
#[derive(AsChangeset, Debug, Deserialize, Identifiable, PartialEq, Queryable)]
#[table_name = "roles"]
pub struct Role {
/// The auto incremented primary index
pub id: i32,
/// The role name
pub name: String,
/// Creation date of the role
pub date_created: NaiveDateTime,
/// The user id, that has changed the record
pub id_user_changed: i32,
/// The timestamp, when the record was changed
pub date_changed: NaiveDateTime,
}
/// Structure of a new claim record
#[derive(Debug, Deserialize, Insertable, Serialize)]
#[table_name = "roles"]
pub struct NewRole<'a> {
/// Lifetime of the role name
pub name: &'a str,
/// Creation date of the role
pub date_created: Option<NaiveDateTime>,
/// The user id, that has changed the record
pub id_user_changed: i32,
/// The timestamp, when the record was changed
pub date_changed: Option<NaiveDateTime>,
}
// we couldn't do a RoleList implementation for a Vector
// because we don't own it, RoleList is using the newtype pattern
//#[derive(Debug, Deserialize, Serialize)]
//pub struct RoleList(pub Vec<Role>);

View File

@@ -0,0 +1,10 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
// WIP
// /// traits for the user model
// pub mod traits;

View File

@@ -0,0 +1,192 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
// bring models into scope
use diesel::backend::Backend;
use diesel::deserialize;
use diesel::deserialize::FromSql;
use diesel::serialize;
use diesel::serialize::{Output, ToSql};
use diesel::sql_types::Integer;
//use serde::Serializer;
use serde;
//use super::models::ConfirmState;
//use crate::db::models::ConfirmState;
// trait: meaningful enum/types for email confirmation states
// in analogy: https://noyez.gitlab.io/post/2018-08-05-a-small-custom-bool-type-in-diesel/
//#[repr(i32)]
#[derive(AsExpression, Copy, Clone, Debug, PartialEq, FromSqlRow)]
#[sql_type = "Integer"]
pub enum ConfirmState {
Unconfirmed = 0,
Confirmed = 1,
Authorized = 2,
Blocked = 3,
}
impl<DB> ToSql<Integer, DB> for ConfirmState
where
DB: Backend,
i32: ToSql<Integer, DB>,
{
fn to_sql<W: std::io::Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
let int_value;
match &self {
ConfirmState::Unconfirmed => int_value = 0,
ConfirmState::Confirmed => int_value = 1,
ConfirmState::Authorized => int_value = 2,
ConfirmState::Blocked => int_value = 3,
}
println!("Writing to sql: i32:{:?}", &int_value);
<i32 as ToSql<Integer, DB>>::to_sql(&int_value, out)
}
}
/*
impl FromSql<Integer, Sqlite>
for ConfirmState
{
fn from_sql(
bytes: Option<&<diesel::sqlite::Sqlite as diesel::backend::Backend>::RawValue>,
) -> diesel::deserialize::Result<Self> {
<i32 as diesel::deserialize::FromSql<
diesel::sql_types::Integer, diesel::sqlite::Sqlite>>::from_sql()
.map(ConfirmState::Confirmed)
}
}
*/
impl<DB> FromSql<Integer, DB> for ConfirmState
where
DB: Backend<RawValue = [u8]>,
i32: FromSql<Integer, DB>,
{
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
match <i32 as FromSql<Integer, DB>>::from_sql(bytes)? {
0 => Ok(ConfirmState::Unconfirmed),
1 => Ok(ConfirmState::Confirmed),
2 => Ok(ConfirmState::Authorized),
3 => Ok(ConfirmState::Blocked),
x => Err(format!("Unrecognized variant {}", x).into()),
}
}
}
/*
// WIP
impl<DB> FromSql<Integer, DB> for ConfirmState
where
DB: Backend,
i32: FromSql<Bool, DB> {
//fn from_sql(bytes: Option<diesel::backend::Backend>::RawValue<DB>) -> diesel::deserialize::Result<Self> {
fn from_sql(
bytes: Option<&<DB>::RawValue>,
) -> diesel::deserialize::Result<Self> {
//println!("Reading from sql: bytes:{:?}", bytes);
match bytes {
<i32 as diesel::deserialize::FromSql<Integer, DB>>::from_sql(bytes)
.map(ConfirmState::Confirmed)
}
/*
Some(bytes) => if bytes[0] != 0 {
Ok(ConfirmState::Confirmed) }
else { Ok(ConfirmState::Unconfirmed) }
}
//<i32 as diesel::deserialize::FromSql<Integer, DB>>::from_sql(bytes).map(ConfirmState::Confirmed)
//fn from_sql(bytes: Option<Bool>) -> diesel::deserialize::Result<Self> {
// println!("Reading from sql: bytes:{:?}", bytes);
// match bytes {
// Some(bytes) => if bytes[0] != 0 {
// Ok(ConfirmState::Confirmed) }
// else { Ok(ConfirmState::Unconfirmed) },
// None => Ok(ConfirmState::Unconfirmed),
// }
*/
}
}
*/
/*
impl<DB: diesel::backend::Backend<RawValue = [u8]>>
diesel::deserialize::FromSql<diesel::sql_types::Integer, DB> for ConfirmState
{
fn from_sql(bytes: Option<&[u8]>) -> diesel::deserialize::Result<Self> {
<i32 as diesel::deserialize::FromSql<diesel::sql_types::Integer, DB>>::from_sql(
bytes,
)
.map($name)
}
}
*/
struct ConfirmStateVisitor;
use serde::de::Deserialize;
use serde::de::{self, Visitor};
impl<'de> Visitor<'de> for ConfirmStateVisitor {
type Value = ConfirmState;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("an integer or string of ",
"\"Unconfirmed (0)\",",
"\"Confirmed (1)\"",
"\"Authorized (2)\"",
"\"Blocked (3)\".");
}
//fn visit_bool<E>(self, value: bool) -> Result<ConfirmState, E>
//where
// E: de::Error,
//{
// match value {
// true => Ok(ConfirmState::Confirmed),
// false => Ok(ConfirmState::Unconfirmed),
// }
//}
fn visit_i32<E>(self, value: &'a i32) -> Result<self::Value, E>
where
E: de::Error,
{
match <i32 as FromSql<Integer, DB>>::from_sql(bytes)? {
0 => Ok(ConfirmState::Unconfirmed),
1 => Ok(ConfirmState::Confirmed),
2 => Ok(ConfirmState::Authorized),
3 => Ok(ConfirmState::Blocked),
x => Err(format!("Unrecognized variant {}", x).into()),
0 => Ok(ConfirmState::Confirmed),
false => Ok(ConfirmState::Unconfirmed),
}
}
fn visit_str<E>(self, value: &str) -> Result<self::Value, E>
where
E: de::Error,
{
match value {
//"Confirmed" | "Authorized" => Ok(ConfirmState::Confirmed),
//"Unconfirmed" | "Unauthorized" => Ok(ConfirmState::Unconfirmed),
"Unconfirmed" => Ok(ConfirmState::Unconfirmed),
"Confirmed" => Ok(ConfirmState::Confirmed),
"Authorized" => Ok(ConfirmState::Authorized),
"Bolcked" => Ok(ConfirmState::Blocked),
_s => Err(E::custom(format!("Unknown string value: {}", _s))),
}
}
}
impl<'de> Deserialize<'de> for ConfirmState {
fn deserialize<D>(deserializer: D) -> Result<self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(ConfirmStateVisitor)
}
}

View File

@@ -0,0 +1,28 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use crate::schema::user_roles;
use serde::Deserialize;
/// Structure of a user role record
#[derive(Debug, Queryable, PartialEq)]
pub struct UserRole {
/// id of the referenced user
pub id_user: i32,
/// id of the referenced role
pub id_role: i32,
}
/// Structure of a new user role record
#[derive(Deserialize, Insertable)]
#[table_name = "user_roles"]
pub struct NewUserRole {
/// id of the referenced user
pub id_user: i32,
/// id of the referenced role
pub id_role: i32,
}

View File

@@ -0,0 +1,98 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use crate::schema::users;
/// Structure of a user record
#[derive(AsChangeset, Debug, Deserialize, Identifiable, PartialEq, Queryable, Serialize)]
pub struct User {
/// the auto incremented primary index
pub id: i32,
/// last name of the user
pub last_name: String,
// Option -> returns "None", if db value is null
/// first name of the user
pub first_name: Option<String>,
/// alias of the user name
pub alias_name: Option<String>,
/// users email address
pub email: Option<String>,
/// confirmation state of users email address
pub email_confirmed: Option<i32>,
/// users initials
pub initials: Option<String>,
/// users password hash
pub password_hash: Option<String>,
/// timestamp when the record was created
pub date_created: NaiveDateTime,
/// user id that has changed the record
pub id_changed: i32,
/// timestamp when the record was changed
pub date_changed: NaiveDateTime,
}
/// Structure of a new user record
#[derive(Debug, Deserialize, Insertable, Serialize)]
#[table_name = "users"]
pub struct NewUser<'a> {
/// Lifetime for users last name
pub last_name: &'a str,
/// Lifetime for users first name
pub first_name: Option<&'a str>,
/// Lifetime for users alias name
pub alias_name: Option<&'a str>,
/// Lifetime for users users email
pub email: Option<&'a str>,
/// Lifetime for users email-confirmed
pub email_confirmed: Option<i32>,
/// Lifetime for users initials
pub initials: Option<&'a str>,
/// Lifetime for users password hash
pub password_hash: &'a str,
/// Optional timestamp for cration date
pub date_created: Option<NaiveDateTime>,
/// Optional userid that changed the record
pub id_changed: i32,
/// Optional timestamp for the change date
pub date_changed: Option<NaiveDateTime>,
}
/// Structure of a user registration
#[derive(Debug, Deserialize, Queryable)]
pub struct RegisterUser<'a> {
/// Lifetime of users last name
pub last_name: &'a str,
/// Lifetime of users first name
pub first_name: Option<&'a str>,
/// Lifetime for users alias name column
pub alias: Option<&'a str>,
/// Lifetime for users email column
pub email: Option<&'a str>,
/// Lifetime for users email confirmed column
pub email_confirmed: Option<i32>,
/// Lifetime for users initials
pub initials: Option<&'a str>,
/// Lifetime for users password hash
pub password_hash: &'a str,
/// Lifetime for users password confirmation
pub password_confirmation: &'a str,
/// Optional userid that changed the record
pub id_changed: i32,
}
// WIP
//pub mod traits;
//use types::ConfirmState;
//use crate::types::ConfirmStateVisitor;
//#[serde(skip)]
//#[derive(Serialize, Deserialize)]
//pub struct UserList(pub Vec<User>);

View File

@@ -0,0 +1,74 @@
#![allow(missing_docs)]
table! {
claims (id) {
id -> Integer,
id_user -> Integer,
#[sql_name = "type"]
type_ -> Nullable<Text>,
value -> Nullable<Text>,
date_created -> Timestamp,
id_user_changed -> Integer,
date_changed -> Timestamp,
}
}
table! {
harms (id) {
id -> Integer,
id_harm -> Text,
id_policyholder -> Nullable<Text>,
id_callback -> Nullable<Text>,
date_fallback -> Nullable<Timestamp>,
date_recording -> Timestamp,
id_user -> Integer,
date_created -> Timestamp,
id_user_changed -> Integer,
date_changed -> Timestamp,
}
}
table! {
roles (id) {
id -> Integer,
name -> Text,
date_created -> Timestamp,
id_user_changed -> Integer,
date_changed -> Timestamp,
}
}
table! {
user_roles (id_user, id_role) {
id_user -> Integer,
id_role -> Integer,
}
}
table! {
users (id) {
id -> Integer,
last_name -> Text,
first_name -> Nullable<Text>,
alias_name -> Nullable<Text>,
email -> Nullable<Text>,
email_confirmed -> Nullable<Integer>,
initials -> Nullable<Text>,
password_hash -> Nullable<Text>,
date_created -> Timestamp,
id_changed -> Integer,
date_changed -> Timestamp,
}
}
joinable!(claims -> users (id_user));
joinable!(user_roles -> roles (id_role));
joinable!(user_roles -> users (id_user));
allow_tables_to_appear_in_same_query!(
claims,
harms,
roles,
user_roles,
users,
);