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:
4
crates/advotrackerd/.env
Normal file
4
crates/advotrackerd/.env
Normal file
@@ -0,0 +1,4 @@
|
||||
TEST_LANG=en
|
||||
RUST_LOG=advotracker=info
|
||||
DATABASE_URL=./advotracker.sqlite3
|
||||
#DATABASE_URL=postgres://username:password@localhost/advotracker
|
||||
10
crates/advotrackerd/.gitignore
vendored
Normal file
10
crates/advotrackerd/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file should only ignore things that are generated during a build,
|
||||
# generated by common IDEs, and optional files controlled by the user that
|
||||
# affect the build (such as config.toml).
|
||||
.#*
|
||||
.DS_Store
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
**/*~
|
||||
/target/
|
||||
/config.toml
|
||||
30
crates/advotrackerd/Cargo.toml
Normal file
30
crates/advotrackerd/Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "advotrackerd"
|
||||
version = "0.1.0"
|
||||
authors = ["Ralf Zerres <ralf.zerres@networkx.de>"]
|
||||
description = "Supports lawyers to capture relevant data encountered during an online legal advice\n"
|
||||
readme = "README.md"
|
||||
license = "(0BSD OR MIT)"
|
||||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["winuser"] }
|
||||
#diesel = { version = "1.4", features = [ "msql", "postgres", "sqlite" ] }
|
||||
|
||||
[dependencies]
|
||||
advotracker_db = { path = "../advotracker-db" }
|
||||
|
||||
clap = { version = "~2.33", features = [ "suggestions", "color" ] }
|
||||
dotenv = { version = "~0.15.0" }
|
||||
#env_logger = "~0.7.1"
|
||||
envy = { version = "~0.4" }
|
||||
locales = { version = "0.1" }
|
||||
#log = { version = "~0.4.8" }
|
||||
serde = { version = "~1.0", features = [ "derive" ] }
|
||||
serde_json = { version = "~1.0" }
|
||||
tracing = { version = "0.1" }
|
||||
tracing-subscriber = { version = "0.2.0-alpha", features = ["tracing-log"] }
|
||||
viperus = { git = "https://github.com/maurocordioli/viperus", features = ["cache", "watch", "fmt-clap", "fmt-env"] }
|
||||
|
||||
#[replace]
|
||||
#"foo:0.1.0" = { git = 'https://github.com/example/foo' }
|
||||
12
crates/advotrackerd/LICENSE-0BSD
Normal file
12
crates/advotrackerd/LICENSE-0BSD
Normal file
@@ -0,0 +1,12 @@
|
||||
Copyright (C) 2019 by Ralf Zerres <ralf.zerres@networkx.de>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
19
crates/advotrackerd/LICENSE-MIT
Normal file
19
crates/advotrackerd/LICENSE-MIT
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2019 Ralf Zerres <ralf.zerres@networkx.de>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
6
crates/advotrackerd/LICENSE.spdx
Normal file
6
crates/advotrackerd/LICENSE.spdx
Normal file
@@ -0,0 +1,6 @@
|
||||
SPDXVersion: SPDX-2.1
|
||||
DataLicense: CC0-1.0
|
||||
PackageName: advotracker
|
||||
PackageOriginator: Ralf Zerres
|
||||
PackageHomePage: https://github.com/rzerres/advotracker/
|
||||
PackageLicenseDeclared: MIT, 0BSD
|
||||
52
crates/advotrackerd/README.md
Executable file
52
crates/advotrackerd/README.md
Executable file
@@ -0,0 +1,52 @@
|
||||
<!-- AdvoTracker.markdown -->
|
||||
<!-- version: 1.1 -->
|
||||
|
||||
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-generate-toc again -->
|
||||
<!-- markdown-toc end -->
|
||||
|
||||
# AdvoTracker - Backend #
|
||||
|
||||
AdvoTracker unterstützt Anwälte bei der Erfassung von Mandatsdaten zu einer Online-Beratung.
|
||||
|
||||
Dieses crate implementiert das Backend.
|
||||
|
||||
Als Programmiersprache wird *Rust* verwendet. Die Implementierung der
|
||||
GUI Elemente erfolgt mit der Klassenbibliothek *OrbTk*.
|
||||
|
||||
Als Dokumentationsquellen wird auf die offiziellen Projektseiten [Rust Book][^1] und [OrbTk][^2] verwiesen.
|
||||
|
||||
# Internationalisierung #
|
||||
|
||||
AdvoTracker wurde mit Unterstützung der Mehrsprachenfähigkeit implementiert.
|
||||
Existieren für aktive Umgebung defnierte Sprache (Umgebungsvariable LOCALE) Übersetzungen,
|
||||
werden diese in allen Dialogen verwendet. Andernfalls erfolgen alle Ausgaben in englischer Sprache
|
||||
, die als default-Wert (LANG = C) hinterlegt ist.
|
||||
|
||||
## Übersetzungen für neue Sprachen ##
|
||||
|
||||
### derzeit: crate locales
|
||||
* Übersetzungen für weiter Sprachen als JSON Dateien
|
||||
im Unerordner ./locales/*.json
|
||||
z.B. für Französisch: advotracker_fr.json
|
||||
|
||||
### todo: crate fluent
|
||||
|
||||
Die zu verwendende Sprache wird aus der in der Umgebungsvariable des Betriebssystems hinterlegten Sprache
|
||||
ausgewählt.
|
||||
|
||||
---
|
||||
|
||||
[Logo-CC_BY]: https://i.creativecommons.org/l/by/4.0/88x31.png "Creative Common Logo"
|
||||
[License-CC_BY]: https://creativecommons.org/licenses/by/4.0/legalcode "Creative Common License"
|
||||
This work is licensed under a [Creative Common License 4.0][License-CC_BY]
|
||||
|
||||
![Creative Common Logo][Logo-CC_BY]
|
||||
|
||||
© 2019 Ralf Zerres, Networkx GmbH
|
||||
|
||||
---
|
||||
|
||||
Foodnotes
|
||||
|
||||
[^1]: RUST Book: https://doc.rust-lang.org/book/
|
||||
[^2]: OrbTK GUI: https://gitlab.redox-os.org/redox-os/orbtk
|
||||
78
crates/advotrackerd/locales/main.json
Normal file
78
crates/advotrackerd/locales/main.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"err.lang.not_found": {
|
||||
"de_DE.UTF-8": "Konnte Sprachkode nicht auslesen",
|
||||
"de": "Konnte Sprachkode nicht auslesen",
|
||||
"en": "Couldn't read LANG"
|
||||
},
|
||||
"err.user.not_found": {
|
||||
"fr": "Utilisateur introuvable: $email, $id",
|
||||
"de-DE.UTF-8": "Anwender nicht gefunden: $email, $id",
|
||||
"de": "Anwender nicht gefunden: $email, $id",
|
||||
"en": "User not found: $email, $id"
|
||||
},
|
||||
"main.started": {
|
||||
"de_DE.UTF-8": "Programmlogik starten",
|
||||
"de": "Programmlogik starten",
|
||||
"en": "Program logic started"
|
||||
},
|
||||
"main.finished": {
|
||||
"de_DE.UTF-8": "Programmlogik beendet",
|
||||
"de": "Programmlogik beendet",
|
||||
"en": "Program logic finished"
|
||||
},
|
||||
"parse.arguments": {
|
||||
"de_DE.UTF-8": "Programmargumente prüfen",
|
||||
"de": "Programmargumente prüfen",
|
||||
"en": "Parsing arguments"
|
||||
},
|
||||
"parse.environment": {
|
||||
"de_DE.UTF-8": "Umgebungsvariablen prüfen",
|
||||
"de": "Umgebungsvariablen prüfen",
|
||||
"en": "Parsing environment"
|
||||
},
|
||||
"parse.results": {
|
||||
"de_DE.UTF-8": "Ergebnisse der Konfigurations-Parameterprüfung",
|
||||
"de": "Ergebnisse der Konfigurationsparameterprüfung",
|
||||
"en": "Config parsing results"
|
||||
},
|
||||
"config.name": {
|
||||
"de_DE.UTF-8": "Konfigurationswert für",
|
||||
"de": "Konfigurationswert für",
|
||||
"en": "Config Value for"
|
||||
},
|
||||
"config.name.lang": {
|
||||
"de_DE.UTF-8": "Sprach-Code",
|
||||
"de": "Sprach-Code",
|
||||
"en": "Language code"
|
||||
},
|
||||
"config.name.verbositylevel": {
|
||||
"de_DE.UTF-8": "Ausgabe-Ebene",
|
||||
"de": "Ausgabe-Ebene",
|
||||
"en": "verbosity level"
|
||||
},
|
||||
"config.name.environment": {
|
||||
"de_DE.UTF-8": "Umgebungsvariablen",
|
||||
"de": "Umgebungsvariablen",
|
||||
"en": "environment"
|
||||
},
|
||||
"config.name.configfile": {
|
||||
"de_DE.UTF-8": "Konfigurations-Datei",
|
||||
"de": "Konfigurations-Datei",
|
||||
"en": "config file"
|
||||
},
|
||||
"config.name.dbdriver": {
|
||||
"de_DE.UTF-8": "Datenbank-Treiber",
|
||||
"de": "Datenbank-Treiber",
|
||||
"en": "database driver"
|
||||
},
|
||||
"state.started": {
|
||||
"de_DE.UTF-8": "gestartet",
|
||||
"de": "gestartet",
|
||||
"en": "started"
|
||||
},
|
||||
"state.finished": {
|
||||
"de_DE.UTF-8": "beendet",
|
||||
"de": "beended",
|
||||
"en": "finished"
|
||||
}
|
||||
}
|
||||
41
crates/advotrackerd/src/cli.yml
Normal file
41
crates/advotrackerd/src/cli.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
name: advotrackerd
|
||||
version: "1.0"
|
||||
author: Networkx GmbH <info@networkx.de>
|
||||
about: capture relevant data encountered during an online legal advice
|
||||
after_help: in Zusammenarbeit mit HIEDEMANN Rechtsanwälte
|
||||
args:
|
||||
- config:
|
||||
short: c
|
||||
long: config
|
||||
value_name: FILE
|
||||
help: Sets a custom config file
|
||||
takes_value: true
|
||||
- dbdriver:
|
||||
short: D
|
||||
long: dbdriver
|
||||
help: Driver used to connect to database
|
||||
possible_values:
|
||||
- mysql
|
||||
- postgres
|
||||
- sqlite
|
||||
takes_value: true
|
||||
- verbose:
|
||||
short: v
|
||||
long: verbose
|
||||
multiple: true
|
||||
help: Sets the level of verbosity
|
||||
subcommands:
|
||||
- config:
|
||||
about: configure the program environment
|
||||
version: "0.1.0"
|
||||
author: Ralf Zerres <ralf.zerres@networkx.de>
|
||||
value_name: "FILE"
|
||||
default_value: advotracker.conf
|
||||
- test:
|
||||
about: run testing features
|
||||
version: "0.1.0"
|
||||
author: Ralf Zerres <ralf.zerres@networkx.de>
|
||||
args:
|
||||
- debug:
|
||||
short: d
|
||||
help: print debug information
|
||||
327
crates/advotrackerd/src/database.rs
Normal file
327
crates/advotrackerd/src/database.rs
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* advotracker - Hotline tackingtool for Advocats
|
||||
*
|
||||
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
|
||||
* SPDX-License-Identifier: (0BSD or MIT)
|
||||
*/
|
||||
|
||||
// module: db
|
||||
#![warn(clippy::pedantic)]
|
||||
#![warn(clippy::nursery)]
|
||||
|
||||
//#[cfg(test)]
|
||||
use diesel::debug_query;
|
||||
use diesel::dsl::*;
|
||||
use diesel::prelude::*;
|
||||
//use diesel::sql_query;
|
||||
use diesel::sqlite::Sqlite;
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
use dotenv::dotenv;
|
||||
//use serde_derive;
|
||||
use serde_json;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
|
||||
// modules
|
||||
pub mod models;
|
||||
pub mod schema;
|
||||
pub mod types;
|
||||
|
||||
//use crate::db::models::Users;
|
||||
use crate::db::models::Harm;
|
||||
use models::User;
|
||||
use models::UserRole;
|
||||
use schema::*;
|
||||
|
||||
// functions
|
||||
pub fn establish_connection() -> SqliteConnection {
|
||||
dotenv().ok();
|
||||
|
||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
SqliteConnection::establish(&database_url)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", &database_url))
|
||||
/*
|
||||
* WIP: integrate tracing!
|
||||
trace!(
|
||||
target: "diesel",
|
||||
type: "Sqlite3",
|
||||
status: "connected"
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* base functions
|
||||
pub fn users_insert_default_values(conn: &SqliteConnection) -> QueryResult<usize> {
|
||||
//use schema::users::dsl::*;
|
||||
|
||||
insert_into(users).default_values().execute(conn)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn examine_sql_users_insert_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());
|
||||
}
|
||||
|
||||
pub fn user_roles_insert_default_values(conn: &SqliteConnection) -> QueryResult<usize> {
|
||||
use schema::user_roles::dsl::*;
|
||||
|
||||
insert_into(user_roles).default_values().execute(conn)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn examine_sql_user_roles_insert_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());
|
||||
}
|
||||
|
||||
pub fn user_harms_insert_default_values(conn: &SqliteConnection) -> QueryResult<usize> {
|
||||
use schema::harms::dsl::*;
|
||||
|
||||
insert_into(harms).default_values().execute(conn)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn examine_sql_harms_insert_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());
|
||||
}
|
||||
|
||||
pub fn users_insert_single_column(conn: &SqliteConnection) -> QueryResult<usize> {
|
||||
use schema::users::dsl::*;
|
||||
|
||||
insert_into(users)
|
||||
.values(alias.eq("Hiedemann"))
|
||||
.execute(conn)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn examine_sql_users_insert_single_column() {
|
||||
use schema::users::dsl::*;
|
||||
|
||||
let query = insert_into(users).values(alias.eq("Hiedemann"));
|
||||
let sql = "INSERT INTO `users` (`alias`) VALUES (?) \
|
||||
-- binds: [\"Hiedemann\"]";
|
||||
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
|
||||
}
|
||||
|
||||
pub fn users_insert_multiple_columns(conn: &SqliteConnection) -> QueryResult<usize> {
|
||||
use schema::users::dsl::*;
|
||||
|
||||
insert_into(users)
|
||||
.values((
|
||||
first_name.eq("Lothar"),
|
||||
last_name.eq("Schlömer"),
|
||||
alias.eq("102"),
|
||||
))
|
||||
.execute(conn)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn examine_sql_user_insert_multiple_columns() {
|
||||
use models::Users;
|
||||
//use crate::db::models::Users;
|
||||
use crate::db::schema::users::dsl::*;
|
||||
|
||||
let query = insert_into(users).values((
|
||||
first_name.eq("Lothar"),
|
||||
last_name.eq("Schlömer"),
|
||||
alias.eq("102"),
|
||||
));
|
||||
let sql = "INSERT INTO `users` (`first_name`, `last_name`, `alias`) \
|
||||
VALUES (?, ?, ?) \
|
||||
-- binds: [\"Lothar\", \"Schlömer\", \"102\"]";
|
||||
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
|
||||
}
|
||||
|
||||
pub fn user_insert_struct_via_json(conn: &SqliteConnection) -> Result<(), Box<dyn Error>> {
|
||||
use models::insert::NewUser;
|
||||
use schema::users::dsl::*;
|
||||
|
||||
let json = r#"{ "alias": "Daniela", "first_name": "Daniela","last_name": "Knocke" }"#;
|
||||
let user_struct = serde_json::from_str::<NewUser>(json)?;
|
||||
|
||||
insert_into(users).values(&user_struct).execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn examine_sql_user_insert_struct_via_json() {
|
||||
use models::NewUser;
|
||||
use schema::users::dsl::*;
|
||||
|
||||
let json = r#"{ "last_name": "Knocke", "first_name": "Daniela", "alias": "Sekretariat" }"#;
|
||||
let user_form = serde_json::from_str::<NewUser>(json).unwrap();
|
||||
let query = insert_into(users).values(&user_form);
|
||||
let sql = "INSERT INTO `users` (`last_name`, `first_name`, `alias`) \
|
||||
VALUES (?, ?, ?) \
|
||||
-- binds: [\"Knocke\", \"Daniela\", \"Sekretariat\"]";
|
||||
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
pub fn user_insert_struct_json_option(conn: &SqliteConnection) -> Result<(), Box<dyn Error>> {
|
||||
use models::NewUser;
|
||||
use schema::users::dsl::*;
|
||||
|
||||
let json = r#"{ "alias": "Networkx", "email_confirmed": true,
|
||||
"email": "support@networkx.de", "first_name": null, "last_name": null }"#; let user_form =
|
||||
serde_json::from_str::<NewUser>(json)?;
|
||||
|
||||
insert_into(users).values(&user_form).execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn examine_sql_user_insert_struct_json_option() {
|
||||
use schema::users::dsl::*;
|
||||
use models::NewUser;
|
||||
|
||||
let json = r#"{ "alias": "Networkx", "email_confirmed": true, "email": "support@networkx.de", "first_name": null, "last_name": null }"#;
|
||||
let user_form = serde_json::from_str::<NewUser>(json).unwrap();
|
||||
let query = insert_into(users).values(&user_form);
|
||||
let sql = "INSERT INTO `users` (`alias`, `email`, `email_confirmed`) \
|
||||
VALUES (?, ?, ?) \
|
||||
-- binds: [\"Networkx\", \"support@networkx.de\", \"$true\"]";
|
||||
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
|
||||
}
|
||||
*/
|
||||
|
||||
// WIP
|
||||
/*
|
||||
#[test]
|
||||
fn examine_sql_users_insert_get_results() {
|
||||
use diesel::result::Error;
|
||||
|
||||
let conn = establish_connection();
|
||||
conn.test_transaction::<_, Error, _>(|| {
|
||||
use diesel::select;
|
||||
use chrono::NaiveDateTime;
|
||||
use schema::users::dsl::*;
|
||||
//use schema::users::*;
|
||||
|
||||
let now = select(diesel::dsl::now).get_result::<NaiveDateTime>(&conn)?;
|
||||
|
||||
let inserted_users = conn.transaction::<_, Error, _>(|| {
|
||||
let inserted_count = insert_into(users)
|
||||
.values(&vec![
|
||||
(id.eq(1), last_name.eq("Hiedemann"), first_name.eq("Eric")),
|
||||
(id.eq(2), last_name.eq("Schlömer"), first_name.eq("Lothar")),
|
||||
//(id.eq(1), first_name.eq("Eric"), last_name.eq("Hiedemann"), alias.eq("Eric.Hiedemann")),
|
||||
//(id.eq(2), first_name.eq("Lothar"), last_name.eq("Schlömer"), alias.eq("othar.Schlömer")),
|
||||
])
|
||||
.execute(&conn)?;
|
||||
|
||||
/*
|
||||
Ok(users
|
||||
.order(id.desc())
|
||||
.limit(inserted_count as i64)
|
||||
.load(&conn)?
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect::<Vec<_>>())
|
||||
*/
|
||||
})?;
|
||||
|
||||
/*
|
||||
let expected_users = vec![
|
||||
User {
|
||||
id: 1,
|
||||
last_name: "Hiedemann".into(),
|
||||
first_name: "Eric".into(),
|
||||
alias: "Eric.Hiedemann".into(),
|
||||
email: None,
|
||||
email_confirmed: false,
|
||||
password_hash: None,
|
||||
initials: None,
|
||||
date_created: now,
|
||||
date_updated: now,
|
||||
},
|
||||
User {
|
||||
id: 2,
|
||||
last_name: "Schlömer".into(),
|
||||
first_name: "Lothar".into(),
|
||||
alias: "Lothar.Schlömer".into(),
|
||||
email: None,
|
||||
email_confirmed: false,
|
||||
password_hash: None,
|
||||
initials: None,
|
||||
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");
|
||||
}
|
||||
*/
|
||||
43
crates/advotrackerd/src/lib.rs
Normal file
43
crates/advotrackerd/src/lib.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* advotracker - Hotline tackingtool for Advocats
|
||||
*
|
||||
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
|
||||
* SPDX-License-Identifier: 0BSD, MIT
|
||||
*/
|
||||
|
||||
#![warn(missing_docs, rust_2018_idioms, rust_2018_compatibility)]
|
||||
|
||||
//! advotrackerd: crate documentation
|
||||
|
||||
// This function adds two integers (given as arguments) and returns the sum.
|
||||
//
|
||||
// # Examples
|
||||
//
|
||||
// ```
|
||||
// assert_eq!(8, advotrackerd::internal_adder(4, 4));
|
||||
// ```
|
||||
fn internal_adder(a: i32, b: i32) -> i32 {
|
||||
a + b
|
||||
}
|
||||
|
||||
/// This function adds two to its argument.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(4, advotrackerd::add_two(2));
|
||||
/// ```
|
||||
pub fn add_two(a: i32) -> i32 {
|
||||
internal_adder(a, 2)
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn internal_test() {
|
||||
assert_eq!(8, internal_adder(4, 4));
|
||||
}
|
||||
}
|
||||
213
crates/advotrackerd/src/main.rs
Normal file
213
crates/advotrackerd/src/main.rs
Normal file
@@ -0,0 +1,213 @@
|
||||
/* advotracker infrastructure.
|
||||
*
|
||||
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
|
||||
* SPDX-License-Identifier: (0BSD or MIT)
|
||||
*/
|
||||
|
||||
// Rust nightly supports procedural macros!
|
||||
//#![feature(proc_macro)]
|
||||
//#![deny(rust_2018_idioms)]
|
||||
|
||||
/// advotrackerd: the main binary
|
||||
|
||||
//use log::info; //substituted with tracing
|
||||
use dotenv::dotenv;
|
||||
use locales::t;
|
||||
use serde::Deserialize;
|
||||
//use std::{env, process};
|
||||
use std::env;
|
||||
//use tracing::{debug, info, instrument, span, Level};
|
||||
//use tracing::{debug, info, instrument, Level, Metadata, span::{Id, Attributes, Record}, trace};
|
||||
//use tracing::{debug, instrument, span::*, trace, Level};
|
||||
use tracing::{debug, trace, Level};
|
||||
|
||||
//use diesel::prelude::*;
|
||||
//use diesel::sqlite::SqliteConnection;
|
||||
|
||||
mod parse_args;
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Environment {
|
||||
test_lang: String,
|
||||
}
|
||||
|
||||
/*
|
||||
pub struct AdvoTrackerSubscriber;
|
||||
|
||||
impl tracing::Subscriber for AdvoTrackerSubscriber{
|
||||
fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
|
||||
fn record(&self, _: &Id, _: &Record) {}
|
||||
fn event(&self, _: &tracing::Event) {}
|
||||
fn record_follows_from(&self, _: &Id, _: &Id) {}
|
||||
fn enabled(&self, _: &Metadata) -> bool { false }
|
||||
fn enter(&self, _: &Id) {}
|
||||
fn exit(&self, _: &Id) {}
|
||||
}
|
||||
|
||||
impl AdvoTrackerSubscriber {
|
||||
fn new() -> Self { AdvoTrackerSubscriber }
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
fn run_subcommand(matches: &ArgMatches) -> Result<(), String> {
|
||||
//info!("inside run_subcommand");
|
||||
match matches.subcommand() {
|
||||
("config", Some(cmd)) => run_config(cmd),
|
||||
("test", Some(cmd)) => run_test(cmd),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn run_config(matches: &ArgMatches) -> Result<(), String> {
|
||||
//info!("inside run_config");
|
||||
let _input = matches.value_of("FILE").unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
fn run_test(matches: &ArgMatches) -> Result<(), String> {
|
||||
//info!("inside run_test");
|
||||
|
||||
if let Some(matches) = matches.subcommand_matches("test") {
|
||||
if matches.is_present("debug") {
|
||||
println!("test: Printing debug info...");
|
||||
} else {
|
||||
println!("test: Printing normally...");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
|
||||
/// `advotrackerd` is the daemon that keeps track of legal mandate data
|
||||
/// that are backed up in a database.
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
use parse_args::parse_args;
|
||||
use tracing_subscriber::fmt;
|
||||
use viperus::Viperus;
|
||||
|
||||
//let advotracker_subscriber = AdvoTrackerSubscriber::new();
|
||||
//tracing::subscriber::set_global_default(advotracker_subscriber)
|
||||
// .expect("setting tracing default failed");
|
||||
|
||||
// initialize the tracing subsystem
|
||||
// a drop in replacement for classical logging
|
||||
// reference: https://tokio.rs/blog/2019-08-tracing/
|
||||
let span = tracing::span!(Level::TRACE, "advotracker_main");
|
||||
let _enter = span.enter();
|
||||
let subscriber = fmt::Subscriber::builder()
|
||||
.with_env_filter("advotracker=trace")
|
||||
.finish();
|
||||
|
||||
// initialize logger
|
||||
// TODO: exchange with tracing!
|
||||
//env_logger::init();
|
||||
//info!("Commencing the proxy!");
|
||||
|
||||
tracing::subscriber::with_default(subscriber, || {
|
||||
// get system environment
|
||||
let mut lang = env::var("LANG").unwrap_or("en".to_string());
|
||||
let mut res = t!("parse.environment", lang);
|
||||
let mut state = t!("state.started", lang);
|
||||
trace!(target: "advotracker", message = ?res, state = ?state);
|
||||
//debug!(message = ?res, state = ?state);
|
||||
trace!(target: "advotracker", environment = "system", lang = ?lang);
|
||||
|
||||
// get testing environment (.env)
|
||||
dotenv().ok();
|
||||
match envy::from_env::<Environment>() {
|
||||
Ok(environment) => {
|
||||
if environment.test_lang != lang { lang = environment.test_lang; }
|
||||
},
|
||||
Err(e) => { debug!(target: "advotracker", "{}", e); }
|
||||
}
|
||||
res = t!("parse.environment", lang);
|
||||
trace!(target: "advotracker", environment = "envy", lang = ?lang);
|
||||
state = t!("state.finished", lang);
|
||||
trace!(target: "advotracker", message = ?res, state = ?state);
|
||||
//debug!(message = ?res, state = ?state);
|
||||
|
||||
// initialize viperus structure
|
||||
let mut v = Viperus::new();
|
||||
|
||||
// parse commandline arguments
|
||||
res = t!("parse.arguments", lang);
|
||||
state = t!("state.started", lang);
|
||||
trace!(target: "advotracker", process = ?res, state = ?state);
|
||||
//info!(target: "advotracker", "{}", res);
|
||||
//debug!(message = ?res, state = ?state);
|
||||
//info!(target: "advotracker", "parsing commandline args");
|
||||
let _ = parse_args(&mut v);
|
||||
state = t!("state.finished", lang);
|
||||
trace!(target: "advotracker", process = ?res, state = ?state);
|
||||
//trace!(target: "Viperus", "Config results: {:?}", v);
|
||||
|
||||
/*
|
||||
if verbose > 1 {
|
||||
for (key, value) in env::vars() {
|
||||
println!("{}={}", key, value);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//state = t!("state.finished", lang);
|
||||
//trace!(target: "advotracker", process = ?res, state = ?state);
|
||||
//debug!(message = ?res, state = ?state);
|
||||
|
||||
/*
|
||||
// handle subcommands
|
||||
if let Err(e) = run_subcommand(&matches) {
|
||||
println!("Subcommand error: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
// Starting the program logic
|
||||
res = t!("main.started", lang);
|
||||
state = t!("state.started", lang);
|
||||
//info!(target: "advotracker", "{}", res);
|
||||
trace!(target: "advotracker", process = ?res, state = ?state);
|
||||
|
||||
//use advotracker_backend::*;
|
||||
//use advotracker_backend::schema::users::dsl::*;
|
||||
|
||||
/*
|
||||
let connection = establish_connection();
|
||||
|
||||
trace!(
|
||||
target: "advotracker",
|
||||
process = "Sqlite3",
|
||||
status = "connected",
|
||||
);
|
||||
*/
|
||||
|
||||
/*
|
||||
//User::table.load(&connection);
|
||||
//user::belonging_to(users).load(&connection);
|
||||
use advotracker_backend::models::*;
|
||||
|
||||
|
||||
let results = users
|
||||
//.filter(published.eq(true))
|
||||
.limit(5)
|
||||
.load::<User>(&connection)
|
||||
.expect("Error loading users");
|
||||
|
||||
println!("Displaying {} users", results.len());
|
||||
for user in results {
|
||||
println!("{}", user.user_id);
|
||||
println!("----------\n");
|
||||
println!("{}", user.first_name);
|
||||
println!("{}", user.last_name);
|
||||
println!("{}", user.alias);
|
||||
println!("{}", user.email);
|
||||
}
|
||||
*/
|
||||
|
||||
state = t!("state.finished", lang);
|
||||
res = t!("main.finished", lang);
|
||||
//info!(target: "advotracker", "{}", res);
|
||||
trace!(target: "advotracker", process = ?res, state = ?state);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
145
crates/advotrackerd/src/parse_args.rs
Normal file
145
crates/advotrackerd/src/parse_args.rs
Normal file
@@ -0,0 +1,145 @@
|
||||
/* advotracker infrastructure.
|
||||
*
|
||||
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
|
||||
* SPDX-License-Identifier: (0BSD or MIT)
|
||||
*/
|
||||
|
||||
use viperus::Viperus;
|
||||
|
||||
/// The given Viperus structure will be muted according to the
|
||||
/// processed default, environment and commandline arguments
|
||||
pub fn parse_args(v: &mut Viperus) -> Result<(), Box<dyn std::error::Error>> {
|
||||
//use log::{debug, info, trace, warn};
|
||||
//use log::trace;
|
||||
use tracing::{trace, Level};
|
||||
use std::env;
|
||||
|
||||
if cfg!(feature = "yaml") {
|
||||
trace!(target:"feature", "Clap feature 'yaml' enabled.");
|
||||
println!("Using feature yaml.");
|
||||
}
|
||||
if cfg!(feature = "fmt-clap") {
|
||||
trace!(target: "Viperus", "Viperus feature 'fmt-clap' enabled.");
|
||||
println!("Using feature fmt-clap");
|
||||
}
|
||||
|
||||
// preset default key/value pairs (lowest priority)
|
||||
v.add_default("config_file", String::from("advotrackerd.yml"));
|
||||
v.add_default("db_driver", String::from("sqlite"));
|
||||
v.add_default("verbose", 0);
|
||||
|
||||
//if cfg!(feature = "fmt-clap") {
|
||||
println!("With fmt-clap...");
|
||||
|
||||
// parse CLI commandline arguments with clap
|
||||
use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg};
|
||||
|
||||
// CLI arguments are defined inline
|
||||
let matches = App::new("advotrackerd")
|
||||
.name(crate_name!())
|
||||
.version(crate_version!())
|
||||
.author(crate_authors!())
|
||||
.about(crate_description!())
|
||||
.after_help("in Zusammenarbeit mit Hiedemann Rechtsanwälte <info@hiedemann.de>")
|
||||
.template(
|
||||
"\
|
||||
{bin} v{version}
|
||||
{about}
|
||||
|
||||
{all-args}
|
||||
|
||||
(C) 2020 {author}
|
||||
{after_help}",
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("configFile")
|
||||
.short("c")
|
||||
.long("configFile")
|
||||
.value_name("FILE")
|
||||
.help("Sets a custom config file")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("dbdriver")
|
||||
.short("d")
|
||||
.long("dbdriver")
|
||||
.value_name("DatabaseDriver")
|
||||
.help("Driver used to connect to database")
|
||||
.possible_values(&["mysql", "postgres", "sqlite"])
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("verbose")
|
||||
.short("v")
|
||||
.long("verbose")
|
||||
.help("Sets verbosity level")
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches();
|
||||
//}
|
||||
if matches.occurrences_of("verbose") > 0 {
|
||||
// clap is using i64, viperus i32
|
||||
let n = matches.occurrences_of("verbose") as i32;
|
||||
v.add("verbose", n);
|
||||
}
|
||||
//}
|
||||
|
||||
// preset the prefix for relevant environment variables ("ADVOTRACKERD_")
|
||||
//if cfg!(feature = "fmt-clap") {
|
||||
let mut env_prefix: String = crate_name!().to_uppercase();
|
||||
env_prefix.push_str("_");
|
||||
v.set_env_prefix(&env_prefix);
|
||||
//}
|
||||
|
||||
// respect dotenv environment (e.g for testing)
|
||||
// -> overwrites the preset default values
|
||||
println!(
|
||||
"RUST_LOG={}",
|
||||
dotenv::var("RUST_LOG").unwrap_or_else(|_| String::from("None"))
|
||||
);
|
||||
//v.load_file(".env", v.Format::ENV).unwrap();
|
||||
|
||||
// enable caching and automatic update of environment values
|
||||
if cfg!(feature = "fmt-cache") {
|
||||
v.cache(true);
|
||||
}
|
||||
if cfg!(feature = "fmt-env") {
|
||||
v.automatic_env(true);
|
||||
}
|
||||
|
||||
//if cfg!(feature = "fmt-clap") {
|
||||
// load user selected call arguments
|
||||
// -> overwrites values given via environment variables
|
||||
v.load_clap(matches)?;
|
||||
|
||||
// bond the clap names to camel_case rust variable names
|
||||
v.bond_clap("configFile", "config_file");
|
||||
v.bond_clap("dbdriver", "db_driver");
|
||||
v.bond_clap("verbose", "verbose");
|
||||
//}
|
||||
|
||||
trace!("verbose {:?}", v.get::<i32>("verbose").unwrap());
|
||||
if v.get::<i32>("verbose").unwrap() > 0 {
|
||||
println!(
|
||||
"config_file: {:?}",
|
||||
v.get::<String>("config_file").unwrap_or_default()
|
||||
);
|
||||
println!(
|
||||
"db_driver: {:?}",
|
||||
v.get::<String>("db_driver").unwrap_or_default()
|
||||
);
|
||||
println!(
|
||||
"verbosity level: {:?}",
|
||||
v.get::<i32>("verbose").unwrap_or_default()
|
||||
);
|
||||
}
|
||||
|
||||
if v.get::<i32>("verbose").unwrap() > 1 {
|
||||
println!("\nEnvironment:");
|
||||
for (key, value) in env::vars() {
|
||||
println!("{}={}", key, value);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
7
crates/advotrackerd/tests/integration_test.rs
Normal file
7
crates/advotrackerd/tests/integration_test.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
//use advotracker;
|
||||
|
||||
#[test]
|
||||
fn integration_add_two() {
|
||||
assert_eq!(4, advotracker_backend::add_two(2));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user