First release

This commit is contained in:
Johannes Randerath 2024-08-27 18:25:04 +02:00
parent 218c7e8f40
commit c06ddc9498
125 changed files with 12726 additions and 244 deletions

3
.env~ Normal file
View File

@ -0,0 +1,3 @@
R_DATABASES_URL=mysql://inventur:noiqC3OlFGVlRmU8KVPtyzVBLj4W9bbQhnu1zJ5cF75FH4JM2luhI2fvp5YXlTAuKr0Ayw2ZiUGfzortQ0GxqEQ5ICfEQgJtNfto@localhost:3306/inventur
ROCKET_SECRET_KEY=xT0JL6E1W4P+DNh0bRecNwsgtk0QfJ62t5zxe920s00=
ROCKET_CLIENT_SECRET=2vftRCu1WhaFezVoFgsNDlx66XOASBmX

3
.gitignore vendored
View File

@ -181,3 +181,6 @@ cython_debug/
# Added by cargo
/target
.env
/private/
Rocket.toml

View File

@ -4,14 +4,18 @@ version = "0.1.0"
edition = "2021"
[dependencies]
rocket = "0.5.1"
rocket = { version = "0.5.1", features = ["json", "tls"] }
diesel = "2"
inventur_db = { path = "inventur_db/" }
rocket_oauth2 = "0.5"
reqwest = { version = "0.11", features = ["json"] }
dotenvy = "0.15"
[dependencies.rocket_dyn_templates]
version = "0.2.0"
features = ["tera"]
[dependencies.rocket_db_pools]
version = "0.2.0"
features = ["diesel_mysql"]
[dependencies.rocket_sync_db_pools]
version = "0.1"
features = ["diesel_mysql_pool"]

View File

@ -1,5 +0,0 @@
[default]
template_dir = "templates"
[default.databases.inventur]
url = "mysql://inventur:inventur@localhost/inventur?socket=/var/lib/mysql/mysql.sock"

20
__Rocket.toml__ Normal file
View File

@ -0,0 +1,20 @@
[default]
template_dir = "templates"
secret_key = "${ROCKET_SECRET_KEY}"
address = "0.0.0.0"
port = 8001
ident = "Randerath Inventur"
[default.tls]
certs="private/cert.pem"
key="private/key.pem"
#[default.databases.inventur]
#url = "${ROCKET_DATABASE_URL}"
[default.oauth.oauth]
auth_uri = "https://ldap.randerath.eu/realms/master/protocol/openid-connect/auth"
token_uri = "https://ldap.randerath.eu/realms/master/protocol/openid-connect/token"
client_id = "randy_inventur"
client_secret = "${ROCKET_CLIENT_SECRET}"
redirect_uri = "https://inventur.rander.at/auth"

14
inventur.service Normal file
View File

@ -0,0 +1,14 @@
[Unit]
Description=Table based database web app in rocket
After=keycloak
[Service]
Type=Simple
WorkingDirectory=/usr/share/nginx/inventur/
ExecStart=/usr/bin/inventur
User=nginx
Group=nginx
Restart=always
[Install]
WantedBy=multi-user.target

3
inventur_db/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.env
target
bin/*~

8
inventur_db/Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "inventur_db"
version = "0.1.0"
edition = "2021"
[dependencies]
diesel = { version = "2.2.0", features = ["mysql"] }
dotenvy = "0.15"

4
inventur_db/README.md Normal file
View File

@ -0,0 +1,4 @@
Inventur DB
===========
This crate aids setting up a database system for a table-based information structuring system combining the intuitive use of spreadsheats with the data stability of databases.

View File

@ -6,4 +6,4 @@ file = "src/schema.rs"
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
[migrations_directory]
dir = "/home/user/code/inventur/migrations"
dir = "/home/johannes/code/inventur/inventur_db/migrations"

View File

@ -0,0 +1,5 @@
CREATE TABLE jrtables (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
num_fields INTEGER NOT NULL
);

View File

@ -0,0 +1 @@
DROP TABLE jrtables;

View File

@ -0,0 +1,5 @@
CREATE TABLE jrtables (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
num_fields INTEGER NOT NULL
);

View File

@ -0,0 +1 @@
DROP TABLE jrcolumns;

View File

@ -1,2 +1 @@
-- This file should undo anything in `up.sql`
DROP TABLE users;

View File

@ -0,0 +1,9 @@
CREATE TABLE jrcolumns (
id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
jrtable_id INTEGER NOT NULL,
FOREIGN KEY jrtable(jrtable_id) REFERENCES jrtables(id)
ON DELETE CASCADE
ON UPDATE CASCADE,
id_in_table INTEGER NOT NULL
);

View File

@ -0,0 +1,9 @@
CREATE TABLE jrcolumns (
id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
jrtable_id INTEGER NOT NULL,
FOREIGN KEY jrtable(jrtable_id) REFERENCES jrtables(id)
ON DELETE CASCADE
ON UPDATE CASCADE,
id_in_table INTEGER NOT NULL
);

View File

@ -0,0 +1 @@
DROP TABLE jrentries;

View File

@ -0,0 +1 @@
-- This file should undo anything in `up.sql`

View File

@ -0,0 +1,8 @@
CREATE TABLE jrentries (
id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
row_pos INTEGER NOT NULL,
jrtable_id INTEGER NOT NULL,
FOREIGN KEY (jrtable_id) REFERENCES jrtables(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View File

@ -0,0 +1 @@
-- Your SQL goes here

View File

@ -0,0 +1 @@
DROP TABLE jrcells;

View File

@ -0,0 +1 @@
-- This file should undo anything in `up.sql`

View File

@ -0,0 +1,13 @@
CREATE TABLE jrcells (
id INTEGER AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id),
cell_value VARCHAR(2048) NOT NULL,
jrentry_id INTEGER NOT NULL,
FOREIGN KEY (jrentry_id) REFERENCES jrentries(id)
ON DELETE CASCADE
ON UPDATE CASCADE,
jrcolumn_id INTEGER NOT NULL,
FOREIGN KEY (jrcolumn_id) REFERENCES jrcolumns(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View File

@ -0,0 +1 @@
-- Your SQL goes here

View File

@ -0,0 +1,2 @@
ALTER TABLE jrtables
ADD num_fields INTEGER NOT NULL;

View File

@ -0,0 +1 @@
-- This file should undo anything in `up.sql`

View File

@ -0,0 +1,2 @@
ALTER TABLE jrtables
DROP COLUMN num_fields;

View File

@ -0,0 +1 @@
-- Your SQL goes here

View File

@ -0,0 +1 @@
DROP TABLE users;

View File

@ -0,0 +1 @@
-- This file should undo anything in `up.sql`

View File

@ -0,0 +1,6 @@
CREATE TABLE users (
id INTEGER AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id),
username VARCHAR(255) NOT NULL,
email VARCHAR(512) NOT NULL
);

View File

@ -0,0 +1 @@
-- Your SQL goes here

View File

@ -0,0 +1,5 @@
SET FOREIGN_KEY_CHECKS=0;
UPDATE TABLE jrtables
DROP COLUMN owner_id
DROP COLUMN fk_owner_id;
SET FOREIGN_KEY_CHECKS=1;

View File

@ -0,0 +1 @@
-- This file should undo anything in `up.sql`

View File

@ -0,0 +1,10 @@
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE jrtables
ADD owner_id INTEGER NOT NULL;
ALTER TABLE jrtables
ADD CONSTRAINT fk_owner_id
FOREIGN KEY (owner_id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE;
SET FOREIGN_KEY_CHECKS=1;

View File

@ -0,0 +1 @@
-- Your SQL goes here

View File

@ -0,0 +1,2 @@
ALTER TABLE jrcolumns
DROP COLUMN column_type;

View File

@ -0,0 +1 @@
-- This file should undo anything in `up.sql`

View File

@ -0,0 +1,2 @@
ALTER TABLE jrcolumns
ADD column_type INTEGER NOT NULL DEFAULT 0;

View File

@ -0,0 +1 @@
-- Your SQL goes here

View File

@ -0,0 +1,28 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: add_cell <tblid> <rowpos> <idintbl> <value>.")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: add_cell <tblid> <rowpos> <idintbl> <value>.")
.parse::<i32>()
.expect("Expected a number.");
let idintbl = args()
.nth(3)
.expect("Usage: add_cell <tblid> <rowpos> <idintbl> <value>.")
.parse::<i32>()
.expect("Expected a number.");
let value = args()
.nth(4)
.expect("Usage: add_cell <tblid> <clmnid> <value>.");
println!("{:?}", create_jrcell_relative(&mut establish_connection(), tblid, rowpos, idintbl, value));
}

View File

@ -0,0 +1,21 @@
use inventur_db::*;
use std::env::args;
fn main() {
let table_id = args()
.nth(1)
.expect("Usage: add_column <tblid> <name> <uid>.")
.parse::<i32>()
.expect("Usage: add_column <tblid> <name> <uid>.");
let name = args()
.nth(2)
.expect("Usage: add_column <tblid> <name> <uid>.");
let uid = args()
.nth(3)
.expect("Usage: add_column <tblid> <name> <uid>.")
.parse::<i32>()
.expect("Usage: add_column <tblid> <name> <uid>.");
let conn = &mut establish_connection();
println!("{}", add_column(conn, table_id, name, uid).expect("Error"));
}

View File

@ -0,0 +1,15 @@
use inventur_db::*;
use std::env::args;
fn main() {
let name = args()
.nth(1)
.expect("Name missing");
let table_id = args()
.nth(2)
.expect("Table_id missing.")
.parse::<i32>()
.expect("Expected a number as table id.");
let conn = &mut establish_connection();
jrcolumns::create_jrcolumn(conn, name, table_id);
}

View File

@ -0,0 +1,36 @@
use inventur_db::*;
use std::env::args;
use std::io::{stdin, Read};
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: add_entry <tblid> <uid>.")
.parse::<i32>()
.expect("Usage: add_entry <tblid> <uid>.");
let uid = args()
.nth(2)
.expect("Usage: add_entry <tblid> <uid>.")
.parse::<i32>()
.expect("Usage: add_entry <tblid> <uid>.");
let conn = &mut establish_connection();
let tbl = get_table(conn, tblid, uid);
if tbl.is_none() {
panic!("Table not found.");
}
let tbl = tbl.unwrap();
let mut cells = Vec::new();
for clm in tbl.column_names {
println!("{}:", clm);
let mut cell = String::new();
stdin().read_line(&mut cell);
cells.push(cell.clone());
}
println!("{}", add_row(conn, tblid, cells, uid).unwrap());
}

View File

@ -0,0 +1,36 @@
use inventur_db::*;
use std::env::args;
use std::io::{stdin, Read};
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: add_entry <tblid> <uid>.")
.parse::<i32>()
.expect("Usage: add_entry <tblid> <uid>.");
let uid = args()
.nth(2)
.expect("Usage: add_entry <tblid> <uid>.")
.parse::<i32>()
.expect("Usage: add_entry <tblid> <uid>.");
let conn = &mut establish_connection();
let tbl = get_table(conn, tblid, uid);
if tbl.is_none() {
panic!("Table not found.");
}
let tbl = tbl.unwrap();
let mut rows = Vec::new();
for clm in tbl.column_names {
println!("{}:", clm);
let mut cell = String::new();
stdin().read_line(&mut cell);
rows.push(cell.clone());
}
println!("{}", add_row(conn, tblid, rows, uid).expect("Error"));
}

View File

@ -0,0 +1,34 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.")
.parse::<i32>()
.expect("Expected a number.");
let idintbl = args()
.nth(3)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.")
.parse::<i32>()
.expect("Expected a number.");
let newvalue = args()
.nth(4)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.");
let uid = args()
.nth(5)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.")
.parse::<i32>()
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.");
println!("{:?}", edit_cell(&mut establish_connection(), tblid, rowpos, idintbl, newvalue, uid));
}

View File

@ -0,0 +1,28 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.")
.parse::<i32>()
.expect("Expected a number.");
let idintbl = args()
.nth(3)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.")
.parse::<i32>()
.expect("Expected a number.");
let newvalue = args()
.nth(4)
.expect("Usage: change_cell_value <tblid> <rowpos> <idintbl> <newvalue>.");
println!("{:?}", jrcells::change_jrcell_value_relative(&mut establish_connection(), tblid, rowpos, idintbl, newvalue));
}

View File

@ -0,0 +1,38 @@
use inventur_db::*;
use std::io::stdin;
fn main() {
let conn = &mut establish_connection();
let mut name = String::new();
let mut num_fields = String::new();
let mut uid = String::new();
println!("Name: ");
stdin().read_line(&mut name);
let name = name.trim();
println!("Number of fields: ");
stdin().read_line(&mut num_fields);
println!("Userid:");
stdin().read_line(&mut uid);
let uid = uid
.trim()
.parse::<i32>()
.expect("Number expected.");
let num_fields = num_fields
.trim()
.parse::<i32>()
.expect("Number expected");
let mut fields : Vec<String> = Vec::new();
for i in 0..num_fields {
let mut field = String::new();
stdin().read_line(&mut field);
let field = field.trim();
fields.push(field.to_string());
}
println!("{}", create_table(conn, name.to_string(), fields, uid).unwrap());
}

View File

@ -0,0 +1,38 @@
use inventur_db::*;
use std::io::stdin;
fn main() {
let conn = &mut establish_connection();
let mut name = String::new();
let mut num_fields = String::new();
let mut uid = String::new();
println!("Name: ");
stdin().read_line(&mut name).unwrap();
let name = name.trim_end();
println!("Number of fields: ");
stdin().read_line(&mut num_fields);
println!("Userid:");
stdin().read_line(&mut uid);
let uid = uid
.trim()
.parse::<i32>()
.expect("Number expected.");
let num_fields = num_fields
.trim()
.parse::<i32>()
.expect("Number expected");
let mut fields = Vec::new();
for i in 0..num_fields {
let mut field = String::new();
stdin().read_line(&mut field);
field.trim();
fields.push(field);
}
println!("{}", create_table(conn, name.to_string(), fields, uid).unwrap());
}

View File

@ -0,0 +1,14 @@
use inventur_db::*;
use std::env::args;
fn main() {
let uname = args()
.nth(1)
.expect("Usage: create_user <username> <email>.");
let mail = args()
.nth(2)
.expect("Usage: create_user <username> <email>.");
println!("{}", register_or_login(&mut establish_connection(), uname, mail).unwrap().uid);
}

View File

@ -0,0 +1,14 @@
use inventur_db::*;
use std::env::args;
fn main() {
let uname = args()
.nth(1)
.expect("Usage: create_user <username> <email>.");
let mail = args()
.nth(2)
.expect("Usage: create_user <username> <email>.");
println!("{}", register_or_login(&mut establish_connection(), uname, mail).unwrap().uid);
}

View File

@ -0,0 +1,24 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: add_cell <tblid> <rowpos> <idintbl> <value>.")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: add_cell <tblid> <rowpos> <idintbl> <value>.")
.parse::<i32>()
.expect("Expected a number.");
let idintbl = args()
.nth(3)
.expect("Usage: add_cell <tblid> <rowpos> <idintbl> <value>.")
.parse::<i32>()
.expect("Expected a number.");
println!("{:?}", delete_jrcell_relative(&mut establish_connection(), tblid, rowpos, idintbl));
}

View File

@ -0,0 +1,26 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: delete_column <tblid> <column pos> <uid>.")
.parse::<i32>()
.expect("Usage: delete_column <tblid> <column pos> <uid>.");
let idintbl = args()
.nth(2)
.expect("Usage: delete_column <tblid> <column pos> <uid>.")
.parse::<i32>()
.expect("Usage: delete_column <tblid> <column pos> <uid>.");
let uid = args()
.nth(3)
.expect("Usage: delete_column <tblid> <column pos> <uid>.")
.parse::<i32>()
.expect("Usage: delete_column <tblid> <column pos> <uid>.");
let conn = &mut establish_connection();
println!("{:?}", delete_column(conn, tblid, idintbl, uid));
}

View File

@ -0,0 +1,20 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Table id missing.")
.parse::<i32>()
.expect("Expected a number.");
let idintbl = args()
.nth(2)
.expect("Id in table missing.")
.parse::<i32>()
.expect("Expected a number.");
let conn = &mut establish_connection();
println!("{:?}", jrcolumns::delete_column_relative(conn, tblid, idintbl));
}

View File

@ -0,0 +1,25 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: delete_entry <tblid> <rowpos>")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: delete_entry <tblid> <rowpos>")
.parse::<i32>()
.expect("Expected a number.");
let uid = args()
.nth(3)
.expect("Usage: delete_entry <tblid> <rowpos>")
.parse::<i32>()
.expect("Usage: delete_entry <tblid> <rowpos>");
delete_row(&mut establish_connection(), tblid, rowpos, uid);
}

View File

@ -0,0 +1,19 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: delete_entry <tblid> <rowpos>")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: delete_entry <tblid> <rowpos>")
.parse::<i32>()
.expect("Expected a number.");
jrentries::delete_jrentry_relative(&mut establish_connection(), tblid, rowpos);
}

View File

@ -0,0 +1,17 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: delete_jrtable <tableid> <uid>.")
.parse::<i32>()
.expect("Expected a number.");
let uid = args()
.nth(2)
.expect("Usage: delete_jrtable <tableid> <uid>.")
.parse::<i32>()
.expect("Usage: delete_jrtable <tableid>.");
println!("{:?}", delete_table(&mut establish_connection(), tblid, uid));
}

View File

@ -0,0 +1,12 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: delete_jrtable <tableid>.")
.parse::<i32>()
.expect("Expected a number.");
println!("{:?}", jrtables::delete_jrtable(&mut establish_connection(), tblid));
}

View File

@ -0,0 +1,13 @@
use inventur_db::*;
use std::env::args;
fn main() {
let uid = args()
.nth(1)
.expect("Missing argument.")
.parse::<i32>()
.expect("");
let conn = &mut establish_connection();
delete_user(conn, uid);
}

View File

@ -0,0 +1,19 @@
use inventur_db::*;
use std::env::args;
fn main() {
let arg = args()
.nth(1)
.expect("Missing argument.");
let conn = &mut establish_connection();
let mut uid = users::get_uid_uname(conn, &arg);
if uid.is_err() {
uid = users::get_uid_email(conn, &arg);
}
if uid.is_err() {
panic!("User not found!");
}
let uid = uid.unwrap();
delete_user(conn, uid);
}

View File

@ -0,0 +1,31 @@
use std::env::args;
use inventur_db::*;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: move_column <tblid> <position> <new position> <uid>.")
.parse::<i32>()
.expect("Usage: move_column <tblid> <position> <new position> <uid>.");
let idintbl = args()
.nth(2)
.expect("Usage: move_column <tblid> <position> <new position> <uid>.")
.parse::<i32>()
.expect("Usage: move_column <tblid> <position> <new position> <uid>.");
let newidintbl = args()
.nth(3)
.expect("Usage: move_column <tblid> <position> <new position> <uid>.")
.parse::<i32>()
.expect("Usage: move_column <tblid> <position> <new position> <uid>.");
let uid = args()
.nth(4)
.expect("Usage: move_column <tblid> <position> <new position> <uid>.")
.parse::<i32>()
.expect("Usage: move_column <tblid> <position> <new position> <uid>.");
let conn = &mut establish_connection();
move_column(conn, tblid, idintbl, newidintbl, uid);
}

View File

@ -0,0 +1,25 @@
use std::env::args;
use inventur_db::*;
fn main() {
let tblid = args()
.nth(1)
.expect("Table id missing.")
.parse::<i32>()
.expect("Expected a number.");
let idintbl = args()
.nth(2)
.expect("Id in table missing.")
.parse::<i32>()
.expect("Expected a number.");
let newidintbl = args()
.nth(3)
.expect("New id in table missing.")
.parse::<i32>()
.expect("Expected a number.");
let conn = &mut establish_connection();
jrcolumns::move_column_relative(conn, tblid, idintbl, newidintbl);
}

View File

@ -0,0 +1,31 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: move_entry <tblid> <rowpos> <newpos> <uid>.")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: move_entry <tblid> <rowpos> <newpos> <uid>.")
.parse::<i32>()
.expect("Expected a number.");
let newpos = args()
.nth(3)
.expect("Usage: move_entry <tblid> <rowpos> <newpos> <uid>.")
.parse::<i32>()
.expect("Expected a number.");
let uid = args()
.nth(4)
.expect("Usage: move_entry <tblid> <rowpos> <newpos> <uid>.")
.parse::<i32>()
.expect("Usage: move_entry <tblid> <rowpos> <newpos> <uid>.");
println!("{:?}", move_row(&mut establish_connection(), tblid, rowpos, newpos, uid));
}

View File

@ -0,0 +1,25 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: move_entry <tblid> <rowpos> <newpos>.")
.parse::<i32>()
.expect("Expected a number.");
let rowpos = args()
.nth(2)
.expect("Usage: move_entry <tblid> <rowpos> <newpos>.")
.parse::<i32>()
.expect("Expected a number.");
let newpos = args()
.nth(3)
.expect("Usage: move_entry <tblid> <rowpos> <newpos>.")
.parse::<i32>()
.expect("Expected a number.");
println!("{:?}", jrentries::move_jrentry(&mut establish_connection(), tblid, rowpos, newpos));
}

View File

@ -0,0 +1,30 @@
use inventur_db::*;
use std::env::args;
fn main() {
let table_id = args()
.nth(1)
.expect("Usage: rename_column <tblid> <column position> <new name> <uid>.")
.parse::<i32>()
.expect("Usage: rename_column <tblid> <column position> <new name> <uid>.");
let id_in_table = args()
.nth(2)
.expect("Usage: rename_column <tblid> <column position> <new name> <uid>.")
.parse::<i32>()
.expect("Usage: rename_column <tblid> <column position> <new name> <uid>.");
let name = args()
.nth(3)
.expect("Usage: rename_column <tblid> <column position> <new name> <uid>.");
let uid = args()
.nth(4)
.expect("Usage: rename_column <tblid> <column position> <new name> <uid>.")
.parse::<i32>()
.expect("Usage: rename_column <tblid> <column position> <new name> <uid>.");
let conn = &mut establish_connection();
rename_column(conn, table_id, id_in_table, name, uid);
}

View File

@ -0,0 +1,27 @@
use inventur_db::*;
use std::env::args;
fn main() {
if args().len() != 4 {
panic!("Usage: rename_column <table_id> <id_in_table> <new name>.");
}
let table_id = args()
.nth(1)
.unwrap()
.parse::<i32>()
.expect("Table id must be a number.");
let id_in_table = args()
.nth(2)
.unwrap()
.parse::<i32>()
.expect("id in table must be a number.");
let name = args()
.nth(3)
.unwrap();
let conn = &mut establish_connection();
jrcolumns::rename_column_relative(conn, table_id, id_in_table, name);
}

View File

@ -0,0 +1,23 @@
use inventur_db::*;
use std::env::args;
fn main() {
let table_id = args()
.nth(1)
.expect("Usage: rename_jrtable <tblid> <new name> <uid>.")
.parse::<i32>()
.expect("number expected for id.");
let new_name = args()
.nth(2)
.expect("Usage: rename_jrtable <tblid> <new name> <uid>.");
let uid = args()
.nth(3)
.expect("Usage: rename_jrtable <tblid> <new name> <uid>.")
.parse::<i32>()
.expect("Usage: rename_jrtable <tblid> <new name> <uid>.");
let conn = &mut establish_connection();
rename_table(conn, table_id, new_name, uid);
}

View File

@ -0,0 +1,23 @@
use inventur_db::*;
use std::env::args;
fn main() {
let table_id = args()
.nth(1)
.expect("Usage: rename_jrtable <tblid> <uid> <new name>.")
.parse::<i32>()
.expect("number expected for id.");
let uid = args()
.nth(2)
.expect("Usage: rename_jrtable <tblid> <uid> <new name>.")
.parse::<i32>()
.expect("Usage: rename_jrtable <tblid> <uid> <new name>.");
let new_name = args()
.nth(3)
.expect("Usage: rename_jrtable <tblid> <uid> <new name>.");
let conn = &mut establish_connection();
rename_table(conn, table_id, uid, new_name);
}

View File

@ -0,0 +1,36 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: show_table <tblid> <uid>.")
.parse::<i32>()
.expect("Usage: show_table <tblid> <uid>.");
let uid = args()
.nth(2)
.expect("Usage: show_table <tblid> <uid>.")
.parse::<i32>()
.expect("Usage: show_table <tblid> <uid>.");
let tbl = get_table(&mut establish_connection(), tblid, uid);
if tbl.is_none() {
panic!("Couldn't get table.");
}
let tbl = tbl.unwrap();
println!("Table {}: {}", tbl.tblid, tbl.name.trim());
println!();
print!("|");
for clm in tbl.column_names {
print!(" {} |", clm.trim());
}
println!();
for row in tbl.rows {
print!("|");
for cell in row.cells {
print!(" {} |", cell.trim());
}
println!();
}
}

View File

@ -0,0 +1,29 @@
use inventur_db::*;
use std::env::args;
fn main() {
let tblid = args()
.nth(1)
.expect("Usage: show_table <tblid>.")
.parse::<i32>()
.expect("Expected a number.");
let tbl = get_table(&mut establish_connection(), tblid, 1);
if tbl.is_none() {
panic!("Couldn't get table.");
}
let tbl = tbl.unwrap();
println!("Table {}: {}", tbl.tblid, tbl.name);
println!();
print!("|");
for clm in tbl.column_names {
print!(" {} |", clm);
}
println!();
for row in tbl.rows {
print!("|");
for cell in row.cells {
print!(" {} |", cell);
}
println!();
}
}

View File

@ -0,0 +1,16 @@
use inventur_db::*;
fn main() {
let conn = &mut establish_connection();
let results = get_all_tables(conn).expect("Error loading tables.");
println!("Total: {} tables.", results.len());
for table in results {
println!("{}: {} has {} columns.", table.id, table.name, table.num_fields);
let columns = get_columns_of(conn, table.id).expect(format!("Error reading columns for table {}.", table.id).as_str());
for column in columns {
print!("{} ", column.name);
}
}
}

View File

@ -0,0 +1,11 @@
use inventur_db::*;
use std::env::args;
fn main() {
let uid = args()
.nth(1)
.expect("Usage: show_user_tblids <uid>.")
.parse::<i32>()
.expect("Usage: show_user_tblids <uid>.");
println!("{:?}", get_user_tblids(&mut establish_connection(), uid).unwrap());
}

View File

@ -0,0 +1,10 @@
use inventur_db::*;
use std::env::args;
fn main() {
let uid = args()
.nth(1)
.parse::<i32>()
.expect("Usage: show_user_tblids <uid>.");
println!("{:?}", get_user_tblids(uid));
}

View File

@ -0,0 +1,98 @@
use crate::schema;
use crate::models;
use crate::jrcolumns;
use crate::jrentries;
use models::{ Jrcell, NewJrcell };
use schema::jrcells::dsl::{jrcells, id, jrentry_id, jrcolumn_id, cell_value};
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
pub fn create_jrcell_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32, value: String) -> Result<usize, diesel::result::Error> {
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
if ntrid.is_err() {
return Err(ntrid.err().unwrap());
}
let ntrid = ntrid.unwrap();
let clmid = jrcolumns::get_clmid_relative(conn, tblid, idintbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
let clmid = clmid.unwrap();
create_jrcell(conn, ntrid, clmid, &value)
}
pub fn change_jrcell_value_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32, new_value: String) -> Result<usize, diesel::result::Error> {
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
if ntrid.is_err() {
return Err(ntrid.err().unwrap());
}
let ntrid = ntrid.unwrap();
let clmid = jrcolumns::get_clmid_relative(conn, tblid, idintbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
let clmid = clmid.unwrap();
change_jrcell_value(conn, ntrid, clmid, new_value)
}
pub fn delete_jrcell_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32) -> Result<usize, diesel::result::Error> {
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
if ntrid.is_err() {
return Err(ntrid.err().unwrap());
}
let ntrid = ntrid.unwrap();
let clmid = jrcolumns::get_clmid_relative(conn, tblid, idintbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
let clmid = clmid.unwrap();
delete_jrcell(conn, ntrid, clmid)
}
pub fn create_jrcell(conn: &mut MysqlConnection, entryid: i32, columnid: i32, value: &String) -> Result<usize, diesel::result::Error> {
use self::schema::jrentries::dsl::jrentries;
use self::schema::jrcolumns::dsl::jrcolumns;
let ntr = jrentries
.find(entryid)
.execute(conn);
if ntr.is_err() {
return ntr;
}
let clmn = jrcolumns
.find(columnid)
.execute(conn);
if clmn.is_err() {
return clmn;
}
let cell = NewJrcell { cell_value: value.to_string(), jrentry_id: entryid, jrcolumn_id: columnid };
diesel::insert_into(crate::schema::jrcells::table)
.values(cell)
.execute(conn)
}
pub fn change_jrcell_value(conn: &mut MysqlConnection, entryid: i32, columnid: i32, new_value: String) -> Result<usize, diesel::result::Error> {
diesel::update(jrcells.filter(jrentry_id.eq(entryid)).filter(jrcolumn_id.eq(columnid)))
.set(cell_value.eq(new_value))
.execute(conn)
}
pub fn delete_jrcell(conn: &mut MysqlConnection, entryid: i32, columnid: i32) -> Result<usize, diesel::result::Error> {
diesel::delete(jrcells.filter(jrentry_id.eq(entryid)).filter(jrcolumn_id.eq(columnid)))
.execute(conn)
}
pub fn get_entry_cells(conn: &mut MysqlConnection, entryid: i32) -> Result<Vec<Jrcell>, diesel::result::Error> {
jrcells
.filter(jrentry_id.eq(entryid))
.select(Jrcell::as_select())
.load(conn)
}

View File

@ -0,0 +1,98 @@
use crate::schema;
use crate::models;
use crate::jrcolumns;
use crate::jrentries;
use models::{ Jrcell, NewJrcell };
use schema::jrcells::dsl::{jrcells, id, jrentry_id, jrcolumn_id, cell_value};
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
pub fn create_jrcell_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32, value: String) -> Result<usize, diesel::result::Error> {
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
if ntrid.is_err() {
return Err(ntrid.err().unwrap());
}
let ntrid = ntrid.unwrap();
let clmid = jrcolumns::get_clmid_relative(conn, tblid, idintbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
let clmid = clmid.unwrap();
create_jrcell(conn, ntrid, clmid, value)
}
pub fn change_jrcell_value_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32, new_value: String) -> Result<usize, diesel::result::Error> {
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
if ntrid.is_err() {
return Err(ntrid.err().unwrap());
}
let ntrid = ntrid.unwrap();
let clmid = jrcolumns::get_clmid_relative(conn, tblid, idintbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
let clmid = clmid.unwrap();
change_jrcell_value(conn, ntrid, clmid, new_value)
}
pub fn delete_jrcell_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32) -> Result<usize, diesel::result::Error> {
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
if ntrid.is_err() {
return Err(ntrid.err().unwrap());
}
let ntrid = ntrid.unwrap();
let clmid = jrcolumns::get_clmid_relative(conn, tblid, idintbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
let clmid = clmid.unwrap();
delete_jrcell(conn, ntrid, clmid)
}
pub fn create_jrcell(conn: &mut MysqlConnection, entryid: i32, columnid: i32, value: String) -> Result<usize, diesel::result::Error> {
use self::schema::jrentries::dsl::jrentries;
use self::schema::jrcolumns::dsl::jrcolumns;
let ntr = jrentries
.find(entryid)
.execute(conn);
if ntr.is_err() {
return ntr;
}
let clmn = jrcolumns
.find(columnid)
.execute(conn);
if clmn.is_err() {
return clmn;
}
let cell = NewJrcell { cell_value: value, jrentry_id: entryid, jrcolumn_id: columnid };
diesel::insert_into(crate::schema::jrcells::table)
.values(cell)
.execute(conn)
}
pub fn change_jrcell_value(conn: &mut MysqlConnection, entryid: i32, columnid: i32, new_value: String) -> Result<usize, diesel::result::Error> {
diesel::update(jrcells.filter(jrentry_id.eq(entryid)).filter(jrcolumn_id.eq(columnid)))
.set(cell_value.eq(new_value))
.execute(conn)
}
pub fn delete_jrcell(conn: &mut MysqlConnection, entryid: i32, columnid: i32) -> Result<usize, diesel::result::Error> {
diesel::delete(jrcells.filter(jrentry_id.eq(entryid)).filter(jrcolumn_id.eq(columnid)))
.execute(conn)
}
pub fn get_entry_cells(conn: &mut MysqlConnection, entryid: i32) -> Result<Vec<Jrcell>, diesel::result::Error> {
jrcells
.filter(jrentry_id.eq(entryid))
.select(Jrcell::as_select())
.load(conn)
}

View File

@ -0,0 +1,217 @@
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
use crate::models;
use crate::schema;
use crate::jrtables;
use models::{ Jrcolumn, NewJrcolumn };
use schema::jrcolumns::dsl::{ jrcolumns, id, name, jrtable_id, id_in_table };
pub fn create_jrcolumn(conn: &mut MysqlConnection, tblid: i32, clmnname: String) -> Result<usize, diesel::result::Error> {
use schema::jrentries::dsl::{ jrentries, jrtable_id };
use models::{ Jrentry, NewJrcell };
let ncols = jrtables::get_ncols(conn, tblid);
if ncols.is_err() {
return ncols;
}
let ncols = ncols.unwrap() as i32;
let jrcolumn = NewJrcolumn { name: clmnname, jrtable_id: tblid, id_in_table: ncols + 1 };
let res = diesel::insert_into(crate::schema::jrcolumns::table)
.values(&jrcolumn)
.execute(conn);
if res.is_err() {
return res;
}
let colid = get_clmid_relative(conn, tblid, ncols+1);
if colid.is_err() {
return Err(colid.err().unwrap());
}
let colid = colid.unwrap();
let rows = jrentries
.filter(jrtable_id.eq(tblid))
.select(Jrentry::as_select())
.load(conn);
if rows.is_err() {
return Err(rows.err().unwrap());
}
let rows = rows.unwrap();
let mut cells = Vec::new();
for row in rows {
cells.push(NewJrcell { jrentry_id: row.id, jrcolumn_id: colid, cell_value: "".to_string() });
}
diesel::insert_into(crate::schema::jrcells::table)
.values(&cells)
.execute(conn)
}
pub fn create_jrcolumns_empty_tbl(conn: &mut MysqlConnection, tblid: i32, names: Vec<String>) -> Result<usize, diesel::result::Error> {
let mut cols : Vec<NewJrcolumn> = Vec::new();
let ncols = jrtables::get_ncols(conn, tblid);
if ncols.is_err() {
return ncols;
}
let mut ncols = ncols.unwrap() as i32;
for clmnname in names {
ncols += 1;
cols.push(NewJrcolumn { name: clmnname, jrtable_id: tblid, id_in_table: ncols});
}
let cols = cols;
diesel::insert_into(crate::schema::jrcolumns::table)
.values(&cols)
.execute(conn)
}
pub fn get_last_column_id_of(conn: &mut MysqlConnection, tblid: i32) -> Result<i32, diesel::result::Error> {
jrcolumns
.filter(jrtable_id.eq(tblid))
.order(id_in_table.desc())
.select(id)
.first::<i32>(conn)
}
pub fn get_clmid_relative(conn: &mut MysqlConnection, tblid: i32, idintbl: i32) -> Result<i32, diesel::result::Error> {
jrcolumns
.filter(jrtable_id.eq(tblid))
.filter(id_in_table.eq(idintbl))
.select(id)
.first::<i32>(conn)
}
pub fn rename_column_relative(conn: &mut MysqlConnection, tblid: i32, id_in_tbl: i32, new_name: String) -> Result<usize, diesel::result::Error> {
let clmid = get_clmid_relative(conn, tblid, id_in_tbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
rename_column(conn, clmid.unwrap(), new_name)
}
pub fn rename_column(conn: &mut MysqlConnection, clmnid: i32, new_name: String) -> Result<usize, diesel::result::Error> {
diesel::update(jrcolumns.find(clmnid))
.set(name.eq(new_name))
.execute(conn)
}
pub fn move_column_relative(conn: &mut MysqlConnection, tblid: i32, id_in_tbl: i32, new_id_in_tbl: i32) -> Result<usize, diesel::result::Error> {
let clmid = get_clmid_relative(conn, tblid, id_in_tbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
move_column(conn, clmid.unwrap(), new_id_in_tbl)
}
pub fn move_column(conn: &mut MysqlConnection, clmnid: i32, new_id_in_table: i32) -> Result<usize, diesel::result::Error>{
let tbl_id = jrcolumns
.find(clmnid)
.select(jrtable_id)
.first::<i32>(conn);
if tbl_id.is_err() {
return Err(tbl_id.err().unwrap());
}
let tbl_id = tbl_id.unwrap();
let cols = jrcolumns
.filter(jrtable_id.eq(tbl_id))
.order(id_in_table.asc())
.select(Jrcolumn::as_select())
.load(conn);
if cols.is_err() {
return Err(cols.err().unwrap());
}
let cols = cols.unwrap();
let ncols = cols.len() as i32;
if new_id_in_table > ncols || new_id_in_table < 0 {
return Err(diesel::result::Error::NotFound);
}
let cur_id_in_table =
jrcolumns
.find(clmnid)
.select(id_in_table)
.first::<i32>(conn);
if cur_id_in_table.is_err() {
return Err(cur_id_in_table.err().unwrap());
}
let cur_id_in_table = cur_id_in_table.unwrap();
let dir;
let a;
let b;
if cur_id_in_table < new_id_in_table {
dir = -1;
a = cur_id_in_table + 1;
b = new_id_in_table;
} else {
dir = 1;
a = new_id_in_table;
b = cur_id_in_table - 1;
}
for j in a..=b {
let upd = diesel::update(jrcolumns.find(cols[(j-1) as usize].id))
.set(id_in_table.eq(id_in_table + dir))
.execute(conn);
if upd.is_err() {
return upd;
}
}
diesel::update(jrcolumns.find(clmnid))
.set(id_in_table.eq(new_id_in_table))
.execute(conn)
}
pub fn delete_column_relative(conn: &mut MysqlConnection, tblid: i32, idinclm: i32) -> Result<usize, diesel::result::Error> {
let clmid = get_clmid_relative(conn, tblid, idinclm);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
delete_column(conn, clmid.unwrap())
}
pub fn delete_column(conn: &mut MysqlConnection, clmnid: i32) -> Result<usize, diesel::result::Error> {
let tblid = jrcolumns
.find(clmnid)
.select(jrtable_id)
.first::<i32>(conn);
if tblid.is_err() {
return Err(tblid.err().unwrap());
}
let tblid = tblid.unwrap();
let ncols = jrcolumns
.filter(jrtable_id.eq(tblid))
.execute(conn);
if ncols.is_err() {
return ncols;
}
let ncols = ncols.unwrap() as i32;
let mv = move_column(conn, clmnid, ncols);
if mv.is_err() {
return mv;
}
diesel::delete(jrcolumns.find(clmnid))
.execute(conn)
}
pub fn get_clmns_of(conn: &mut MysqlConnection, tblid: i32) -> Result<Vec<Jrcolumn>, diesel::result::Error> {
jrcolumns
.filter(jrtable_id.eq(tblid))
.order(id_in_table.asc())
.select(Jrcolumn::as_select())
.load(conn)
}

View File

@ -0,0 +1,197 @@
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
use crate::models;
use crate::schema;
use crate::jrtables;
use models::{ Jrcolumn, NewJrcolumn };
use schema::jrcolumns::dsl::{ jrcolumns, id, name, jrtable_id, id_in_table };
pub fn create_jrcolumn(conn: &mut MysqlConnection, tblid: i32, clmnname: String) -> Result<usize, diesel::result::Error> {
let ncols = jrtables::get_ncols(conn, tblid);
if ncols.is_err() {
return ncols;
}
let ncols = ncols.unwrap() as i32;
let jrcolumn = NewJrcolumn { name: clmnname, jrtable_id: tblid, id_in_table: ncols + 1 };
diesel::insert_into(crate::schema::jrcolumns::table)
.values(&jrcolumn)
.execute(conn)
}
pub fn create_jrcolumns(conn: &mut MysqlConnection, tblid: i32, names: Vec<String>) -> Result<usize, diesel::result::Error> {
let mut cols : Vec<NewJrcolumn> = Vec::new();
let ncols = jrtables::get_ncols(conn, tblid);
if ncols.is_err() {
return ncols;
}
let mut ncols = ncols.unwrap() as i32;
for clmnname in names {
ncols += 1;
cols.push(NewJrcolumn { name: clmnname, jrtable_id: tblid, id_in_table: ncols});
}
let cols = cols;
diesel::insert_into(crate::schema::jrcolumns::table)
.values(&cols)
.execute(conn)
}
pub fn get_last_column_id_of(conn: &mut MysqlConnection, tblid: i32) -> Result<i32, diesel::result::Error> {
jrcolumns
.filter(jrtable_id.eq(tblid))
.order(id_in_table.desc())
.select(id)
.first::<i32>(conn)
}
pub fn get_columns_of(conn: &mut MysqlConnection, tblid: i32) -> Result<Vec<Jrcolumn>, diesel::result::Error> {
jrcolumns
.filter(jrtable_id.eq(tblid))
.order(id_in_table.asc())
.select(Jrcolumn::as_select())
.load(conn)
}
pub fn get_clmid_relative(conn: &mut MysqlConnection, tblid: i32, idintbl: i32) -> Result<i32, diesel::result::Error> {
jrcolumns
.filter(jrtable_id.eq(tblid))
.filter(id_in_table.eq(idintbl))
.select(id)
.first::<i32>(conn)
}
pub fn rename_column_relative(conn: &mut MysqlConnection, tblid: i32, id_in_tbl: i32, new_name: String) -> Result<usize, diesel::result::Error> {
let clmid = get_clmid_relative(conn, tblid, id_in_tbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
rename_column(conn, clmid.unwrap(), new_name)
}
pub fn rename_column(conn: &mut MysqlConnection, clmnid: i32, new_name: String) -> Result<usize, diesel::result::Error> {
diesel::update(jrcolumns.find(clmnid))
.set(name.eq(new_name))
.execute(conn)
}
pub fn move_column_relative(conn: &mut MysqlConnection, tblid: i32, id_in_tbl: i32, new_id_in_tbl: i32) -> Result<usize, diesel::result::Error> {
let clmid = get_clmid_relative(conn, tblid, id_in_tbl);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
move_column(conn, clmid.unwrap(), new_id_in_tbl)
}
pub fn move_column(conn: &mut MysqlConnection, clmnid: i32, new_id_in_table: i32) -> Result<usize, diesel::result::Error>{
let tbl_id = jrcolumns
.find(clmnid)
.select(jrtable_id)
.first::<i32>(conn);
if tbl_id.is_err() {
return Err(tbl_id.err().unwrap());
}
let tbl_id = tbl_id.unwrap();
let cols = jrcolumns
.filter(jrtable_id.eq(tbl_id))
.order(id_in_table.asc())
.select(Jrcolumn::as_select())
.load(conn);
if cols.is_err() {
return Err(cols.err().unwrap());
}
let cols = cols.unwrap();
let ncols = cols.len() as i32;
if new_id_in_table > ncols || new_id_in_table < 0 {
return Err(diesel::result::Error::NotFound);
}
let cur_id_in_table =
jrcolumns
.find(clmnid)
.select(id_in_table)
.first::<i32>(conn);
if cur_id_in_table.is_err() {
return Err(cur_id_in_table.err().unwrap());
}
let cur_id_in_table = cur_id_in_table.unwrap();
let dir;
let a;
let b;
if cur_id_in_table < new_id_in_table {
dir = -1;
a = cur_id_in_table + 1;
b = new_id_in_table;
} else {
dir = 1;
a = new_id_in_table;
b = cur_id_in_table - 1;
}
for j in a..=b {
let upd = diesel::update(jrcolumns.find(cols[(j-1) as usize].id))
.set(id_in_table.eq(id_in_table + dir))
.execute(conn);
if upd.is_err() {
return upd;
}
}
diesel::update(jrcolumns.find(clmnid))
.set(id_in_table.eq(new_id_in_table))
.execute(conn)
}
pub fn delete_column_relative(conn: &mut MysqlConnection, tblid: i32, idinclm: i32) -> Result<usize, diesel::result::Error> {
let clmid = get_clmid_relative(conn, tblid, idinclm);
if clmid.is_err() {
return Err(clmid.err().unwrap());
}
delete_column(conn, clmid.unwrap())
}
pub fn delete_column(conn: &mut MysqlConnection, clmnid: i32) -> Result<usize, diesel::result::Error> {
let tblid = jrcolumns
.find(clmnid)
.select(jrtable_id)
.first::<i32>(conn);
if tblid.is_err() {
return Err(tblid.err().unwrap());
}
let tblid = tblid.unwrap();
let ncols = jrcolumns
.filter(jrtable_id.eq(tblid))
.execute(conn);
if ncols.is_err() {
return ncols;
}
let ncols = ncols.unwrap() as i32;
let mv = move_column(conn, clmnid, ncols);
if mv.is_err() {
return mv;
}
diesel::delete(jrcolumns.find(clmnid))
.execute(conn)
}
pub fn get_clmns_of(conn: &mut MysqlConnection, tblid: i32) -> Result<Vec<Jrcolumn>, diesel::result::Error> {
jrcolumns
.filter(jrtable_id.eq(tblid))
.order(id_in_table.asc())
.select(Jrcolumn::as_select())
.load(conn)
}

View File

@ -0,0 +1,132 @@
use crate::models;
use crate::schema;
use schema::jrentries::dsl::{jrentries, id, jrtable_id, row_pos};
use models::{ Jrentry, NewJrentry };
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
pub fn create_jrentry(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
let rowpos = jrentries
.filter(jrtable_id.eq(tblid))
.select(row_pos)
.load::<i32>(conn);
if rowpos.is_err() {
return Err(rowpos.err().unwrap());
}
let rowpos = rowpos.unwrap().len() + 1;
let ntr = NewJrentry { jrtable_id: tblid, row_pos: rowpos as i32 };
diesel::insert_into(crate::schema::jrentries::table)
.values(&ntr)
.execute(conn)
}
pub fn move_jrentry(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, newrowpos: i32) -> Result<usize, diesel::result::Error> {
let ntrids = jrentries
.filter(jrtable_id.eq(tblid))
.order(row_pos.asc())
.select(id)
.load::<i32>(conn);
if ntrids.is_err() {
return Err(ntrids.err().unwrap());
}
let ntrids = ntrids.unwrap();
let a;
let b;
let dir;
let entryid = ntrids[(rowpos-1) as usize];
if rowpos < newrowpos {
a = rowpos + 1;
b = newrowpos;
dir = -1;
}else {
a = newrowpos;
b = rowpos - 1;
dir = 1;
}
for i in a..=b {
let upd = diesel::update(jrentries.find(ntrids[(i-1) as usize]))
.set(row_pos.eq(row_pos + dir))
.execute(conn);
if upd.is_err() {
return upd;
}
}
diesel::update(jrentries.find(entryid))
.set(row_pos.eq(newrowpos))
.execute(conn)
}
pub fn delete_jrentry_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32) -> Result<usize, diesel::result::Error> {
let entryid = jrentries
.filter(jrtable_id.eq(tblid))
.filter(row_pos.eq(rowpos))
.select(id)
.first::<i32>(conn);
if entryid.is_err() {
return Err(entryid.err().unwrap());
}
delete_jrentry(conn, entryid.unwrap())
}
pub fn delete_jrentry(conn: &mut MysqlConnection, entryid: i32) -> Result<usize, diesel::result::Error> {
let rp = jrentries
.find(entryid)
.select(row_pos)
.first::<i32>(conn);
let tblid = jrentries
.find(entryid)
.select(jrtable_id)
.first::<i32>(conn);
if rp.is_err() {
return Err(tblid.err().unwrap());
}
if tblid.is_err() {
return Err(tblid.err().unwrap());
}
let rp = rp.unwrap();
let tblid = tblid.unwrap();
let nr = jrentries
.filter(jrtable_id.eq(tblid))
.execute(conn);
if nr.is_err() {
return nr;
}
move_jrentry(conn, tblid, rp, nr.unwrap() as i32);
diesel::delete(jrentries.find(entryid)).execute(conn)
}
pub fn get_jrentry_id(conn: &mut MysqlConnection, tblid: i32, rowpos: i32) -> Result<i32, diesel::result::Error> {
jrentries
.filter(jrtable_id.eq(tblid))
.filter(row_pos.eq(rowpos))
.select(id)
.first::<i32>(conn)
}
pub fn get_entries_of(conn: &mut MysqlConnection, tblid: i32) -> Result<Vec<Jrentry>, diesel::result::Error> {
jrentries
.filter(jrtable_id.eq(tblid))
.order(row_pos.asc())
.select(Jrentry::as_select())
.load(conn)
}

View File

@ -0,0 +1,131 @@
use crate::models;
use crate::schema;
use schema::jrentries::dsl::{jrentries, id, jrtable_id, row_pos};
use models::{ Jrentry, NewJrentry };
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
pub fn create_jrentry(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
let rowpos = jrentries
.filter(jrtable_id.eq(tblid))
.select(row_pos)
.load::<i32>(conn);
if rowpos.is_err() {
return Err(rowpos.err().unwrap());
}
let rowpos = rowpos.unwrap().len() + 1;
let ntr = NewJrentry { jrtable_id: tblid, row_pos: rowpos as i32 };
diesel::insert_into(crate::schema::jrentries::table)
.values(ntr)
.execute(conn)
}
pub fn move_jrentry(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, newrowpos: i32) -> Result<usize, diesel::result::Error> {
let ntrids = jrentries
.filter(jrtable_id.eq(tblid))
.order(row_pos.asc())
.select(id)
.load::<i32>(conn);
if ntrids.is_err() {
return Err(ntrids.err().unwrap());
}
let ntrids = ntrids.unwrap();
let a;
let b;
let dir;
let entryid = ntrids[(rowpos-1) as usize];
if rowpos < newrowpos {
a = rowpos + 1;
b = newrowpos;
dir = -1;
}else {
a = newrowpos;
b = rowpos - 1;
dir = 1;
}
for i in a..=b {
let upd = diesel::update(jrentries.find(ntrids[(i-1) as usize]))
.set(row_pos.eq(row_pos + dir))
.execute(conn);
if upd.is_err() {
return upd;
}
}
diesel::update(jrentries.find(entryid))
.set(row_pos.eq(newrowpos))
.execute(conn)
}
pub fn delete_jrentry_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32) -> Result<usize, diesel::result::Error> {
let entryid = jrentries
.filter(jrtable_id.eq(tblid))
.filter(row_pos.eq(rowpos))
.select(id)
.first::<i32>(conn);
if entryid.is_err() {
return Err(entryid.err().unwrap());
}
delete_jrentry(conn, entryid.unwrap())
}
pub fn delete_jrentry(conn: &mut MysqlConnection, entryid: i32) -> Result<usize, diesel::result::Error> {
let rp = jrentries
.find(entryid)
.select(row_pos)
.first::<i32>(conn);
let tblid = jrentries
.find(entryid)
.select(jrtable_id)
.first::<i32>(conn);
if rp.is_err() {
return Err(tblid.err().unwrap());
}
if tblid.is_err() {
return Err(tblid.err().unwrap());
}
let rp = rp.unwrap();
let tblid = tblid.unwrap();
let nr = jrentries
.filter(jrtable_id.eq(tblid))
.execute(conn);
if nr.is_err() {
return nr;
}
move_jrentry(conn, tblid, rp, nr.unwrap() as i32);
diesel::delete(jrentries.find(entryid)).execute(conn)
}
pub fn get_jrentry_id(conn: &mut MysqlConnection, tblid: i32, rowpos: i32) -> Result<i32, diesel::result::Error> {
jrentries
.filter(jrtable_id.eq(tblid))
.filter(row_pos.eq(rowpos))
.select(id)
.first::<i32>(conn)
}
pub fn get_entries_of(conn: &mut MysqlConnection, tblid: i32) -> Result<Vec<Jrentry>, diesel::result::Error> {
jrentries
.filter(jrtable_id.eq(tblid))
.select(Jrentry::as_select())
.load(conn)
}

View File

@ -0,0 +1,95 @@
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
use crate::models;
use crate::schema;
use crate::jrcolumns;
use models::{ Jrtable, NewJrtable };
use schema::jrtables::dsl::{ jrtables, id, name, owner_id };
pub fn create_jrtable(conn: &mut MysqlConnection, tblname: &String, field_names: Vec<String>, uid: i32) -> Result<i32, diesel::result::Error> {
let jrtable = NewJrtable { name: tblname.to_string(), owner_id: uid };
let tbl = diesel::insert_into(crate::schema::jrtables::table)
.values(&jrtable)
.execute(conn);
if tbl.is_err() {
return Err(tbl.err().unwrap());
}
let tblid = jrtables
.order(id.desc())
.select(id)
.first::<i32>(conn);
if tblid.is_err() {
return Err(tblid.err().unwrap());
}
let tblid = tblid.unwrap();
let cols = jrcolumns::create_jrcolumns_empty_tbl(conn, tblid, field_names);
if cols.is_err() {
return Err(cols.err().unwrap());
}
Ok(tblid)
}
pub fn rename_jrtable(conn: &mut MysqlConnection, tblid: i32, new_name: &str) -> Result<usize, diesel::result::Error> {
diesel::update(jrtables.find(tblid))
.set(name.eq(new_name))
.execute(conn)
}
pub fn delete_jrtable(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
diesel::delete(jrtables.find(tblid))
.execute(conn)
}
pub fn get_all_tables(conn: &mut MysqlConnection) -> Result<Vec<Jrtable>, diesel::result::Error> {
jrtables
.select(Jrtable::as_select())
.load(conn)
}
pub fn get_tbl(conn: &mut MysqlConnection, tblid: i32) -> Result<Jrtable, diesel::result::Error> {
jrtables
.find(tblid)
.select(Jrtable::as_select())
.first(conn)
}
pub fn get_ncols(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
use schema::jrcolumns::dsl::{ jrcolumns, jrtable_id };
jrcolumns
.filter(jrtable_id.eq(tblid))
.execute(conn)
}
pub fn get_nrows(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
use schema::jrentries::dsl::{jrentries, jrtable_id};
jrentries
.filter(jrtable_id.eq(tblid))
.execute(conn)
}
pub fn get_tblids_uid(conn: &mut MysqlConnection, uid: i32) -> Result<Vec<i32>, diesel::result::Error> {
jrtables
.filter(owner_id.eq(uid))
.select(id)
.load::<i32>(conn)
}
pub fn get_owner_id(conn: &mut MysqlConnection, tblid: i32) -> Result<i32, diesel::result::Error> {
jrtables
.find(tblid)
.select(owner_id)
.first::<i32>(conn)
}
pub fn get_tbl_by_name_uid(conn: &mut MysqlConnection, tblname: &String, uid: i32) -> Result<i32, diesel::result::Error> {
jrtables
.filter(owner_id.eq(uid))
.filter(name.eq(tblname))
.select(id)
.first::<i32>(conn)
}

View File

@ -0,0 +1,95 @@
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
use crate::models;
use crate::schema;
use crate::jrcolumns;
use models::{ Jrtable, NewJrtable };
use schema::jrtables::dsl::{ jrtables, id, name, owner_id };
pub fn create_jrtable(conn: &mut MysqlConnection, tblname: &String, field_names: Vec<String>, uid: i32) -> Result<i32, diesel::result::Error> {
let jrtable = NewJrtable { name: tblname.to_string(), owner_id: uid };
let tbl = diesel::insert_into(crate::schema::jrtables::table)
.values(&jrtable)
.execute(conn);
if tbl.is_err() {
return Err(tbl.err().unwrap());
}
let tblid = jrtables
.order(id.desc())
.select(id)
.first::<i32>(conn);
if tblid.is_err() {
return Err(tblid.err().unwrap());
}
let tblid = tblid.unwrap();
let cols = jrcolumns::create_jrcolumns_empty_tbl(conn, tblid, field_names);
if cols.is_err() {
return Err(cols.err().unwrap());
}
Ok(tblid)
}
pub fn rename_jrtable(conn: &mut MysqlConnection, tblid: i32, new_name: &str) -> Result<usize, diesel::result::Error> {
diesel::update(jrtables.find(tblid))
.set(name.eq(new_name))
.execute(conn)
}
pub fn delete_jrtable(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
diesel::delete(jrtables.find(tblid))
.execute(conn)
}
pub fn get_all_tables(conn: &mut MysqlConnection) -> Result<Vec<Jrtable>, diesel::result::Error> {
jrtables
.select(Jrtable::as_select())
.load(conn)
}
pub fn get_tbl(conn: &mut MysqlConnection, tblid: i32) -> Result<Jrtable, diesel::result::Error> {
jrtables
.find(tblid)
.select(Jrtable::as_select())
.first(conn)
}
pub fn get_ncols(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
use schema::jrcolumns::dsl::{ jrcolumns, jrtable_id };
jrcolumns
.filter(jrtable_id.eq(tblid))
.execute(conn)
}
pub fn get_nrows(conn: &mut MysqlConnection, tblid: i32) -> Result<usize, diesel::result::Error> {
use schema::jrentries::dsl::{jrentries, jrtable_id};
jrentries
.filter(jrtable_id.eq(tblid))
.execute(conn)
}
pub fn get_tblids_uid(conn: &mut MysqlConnection, uid: i32) -> Result<Vec<i32>, diesel::result::Error> {
jrtables
.filter(owner_id.eq(uid))
.select(id)
.load::<i32>(conn)
}
pub fn get_owner_id(conn: &mut MysqlConnection, tblid: i32) -> Result<i32, diesel::result::Error> {
jrtables
.find(tblid)
.select(owner_id)
.first::<i32>(conn)
}
pub fn get_tbl_by_name_uid(conn: &mut MysqlConnection, tblname: &String, uid: i32) -> Result<i32, diesel::result::Error> {
jrtables
.filter(owner_id.eq(uid))
.filter(name.eq(tblname))
.select(id)
.first::<i32>(conn)
}

388
inventur_db/src/lib.rs Normal file
View File

@ -0,0 +1,388 @@
//! Database API using the table style system provided by this crate
mod models;
mod schema;
mod jrtables;
mod jrcolumns;
mod jrentries;
mod jrcells;
mod users;
use dotenvy::dotenv;
use std::env;
use diesel::mysql::MysqlConnection;
use diesel::prelude::*;
use std::hash::{Hash, DefaultHasher};
use std::collections::HashSet;
use diesel::deserialize::FromSql;
use diesel::deserialize;
use diesel::backend::Backend;
use diesel::sql_types::Integer;
#[derive(PartialEq, Clone, Copy, diesel::FromSqlRow)]
#[repr(i32)]
pub enum FIELDTYPE {
TEXT = 0,
NUMBER = 1,
}
impl<DB> FromSql<Integer, DB> for FIELDTYPE
where DB: Backend, i32: FromSql<Integer,DB> {
fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
match i32::from_sql(bytes)? {
0 => Ok(FIELDTYPE::TEXT),
1 => Ok(FIELDTYPE::NUMBER),
x => Err(format!("Unknown field type {}.", x).into()),
}
}
}
/// represents and summarised all relevant data of a table.
/// Standard return type if whole tables should be returned
pub struct Tbl {
/// table id of the represented object
pub tblid: i32,
pub name: String,
pub column_names: Vec<String>,
pub column_types: Vec<FIELDTYPE>,
pub rows: Vec<TRow>,
}
/// Represents a table's row.
/// Internal data structure is abstracted until strings.
#[derive(Hash, Clone, Debug)]
pub struct TRow {
pub row_pos: i32,
pub cells: Vec<String>,
}
impl PartialEq for TRow {
fn eq(&self, other: &Self) -> bool {
let mut hasher = DefaultHasher::new();
self.hash(&mut hasher) == other.hash(&mut hasher)
}
}
impl Eq for TRow {}
/// Identifies a user
/// All fields are unique within the db at any given point.
pub struct User {
/// User's unique id.
pub uid: i32,
pub uname: String,
pub email: String,
}
/// Connect to database.
/// Return value must be passed to most of the crate's functions.
pub fn establish_connection() -> MysqlConnection {
dotenv().ok();
let db_url = env::var("DATABASE_URL").expect("No database url set.");
MysqlConnection::establish(&db_url)
.unwrap_or_else(|_| panic!("Couldn't open database."))
}
/// Fetch one whole table from the database. Identified by it's ID.
/// Needs the id of the requesting user.
/// Returns:
/// A Tbl struct
/// Or:
/// None
/// if the table was not found or
/// if it could not be read or
/// if the requesting user is not the table's owner or
/// if there has been another error
///
pub fn get_table(conn: &mut MysqlConnection, tblid: i32, uid: i32) -> Option<Tbl> {
let tbl = jrtables::get_tbl(conn, tblid);
if tbl.is_err() {
return None;
}
let tbl = tbl.unwrap();
if tbl.owner_id != uid {
return None;
}
let clmns = jrcolumns::get_clmns_of(conn, tblid);
if clmns.is_err() {
return None;
}
let clmns = clmns.unwrap();
let mut clmn_nms = Vec::new();
for clmn in &clmns {
clmn_nms.push(clmn.name.clone());
}
let clmn_nms = clmn_nms;
let mut clmn_ids = Vec::new();
for clmn in &clmns {
clmn_ids.push(clmn.id);
}
let clmn_ids = clmn_ids;
let mut clmn_tps = Vec::new();
for clmn in &clmns {
clmn_tps.push(clmn.column_type);
}
let clmn_tps = clmn_tps;
let rowids = jrentries::get_entries_of(conn, tblid);
if rowids.is_err() {
return None;
}
let rowids = rowids.unwrap();
let mut rows = Vec::new();
for rowid in rowids {
let row = jrcells::get_entry_cells(conn, rowid.id);
if row.is_err() {
return None;
}
let row = row.unwrap();
let mut data = Vec::new();
for cell in row {
data.push(cell.cell_value);
}
let data = data;
rows.push(TRow { row_pos: rowid.row_pos, cells: data });
}
Some(Tbl { tblid: tbl.id, name: tbl.name, column_names: clmn_nms, column_types: clmn_tps,rows: rows })
}
pub fn sort_table(tbl: Tbl, sort_field: usize, sort_dir: u8) -> Tbl {
let mut rows = tbl.rows;
if sort_field == 0 {
rows.sort_unstable_by_key(|a: &TRow| a.row_pos);
if sort_dir == 1 {
rows.reverse();
}
}else {
if tbl.column_types[sort_field-1] == FIELDTYPE::NUMBER {
rows.sort_by_key(|a: &TRow| a.cells[sort_field - 1].trim().parse::<i32>().expect("Number not a number."));
}else {
rows.sort_by_key(|a: &TRow| a.cells[sort_field - 1].clone());
}
if sort_dir == 1 {
rows.reverse();
}
}
let rows = rows;
Tbl { tblid: tbl.tblid, name: tbl.name, column_names: tbl.column_names, column_types: tbl.column_types, rows: rows.clone() }
}
pub fn search_table(tbl: Tbl, search_fields: Vec<i32>, search_value: String) -> Tbl {
let mut rows = tbl.rows;
let mut field_sets = HashSet::new();
for field in search_fields {
for row in &rows {
if row.cells[field as usize].contains(&search_value) {
field_sets.insert(row.clone());
}
}
}
Tbl { tblid: tbl.tblid, name: tbl.name, column_names: tbl.column_names, column_types: tbl.column_types, rows: Vec::from_iter(field_sets) }
}
pub fn get_tblnames(conn: &mut MysqlConnection, tblids: Vec<i32>) -> Option<Vec<String>> {
let mut tblnames = Vec::new();
for tblid in tblids {
let tblname = jrtables::get_tbl(conn, tblid);
if tblname.is_err() {
return None;
}
tblnames.push(tblname.unwrap().name);
}
Some(tblnames)
}
/// Returns a Vec of the ids of a user's table if the user exists, else None.
/// User is identified by its user ID.
pub fn get_user_tblids(conn: &mut MysqlConnection, uid: i32) -> Option<Vec<i32>> {
let tblids = jrtables::get_tblids_uid(conn, uid);
if tblids.is_err() {
return None;
}
Some(tblids.unwrap())
}
/// Change the name of a table.
/// Needs the user ID of the requesting user.
/// Returns Some(true) if the action seems to have been successful and the requesting user is the
/// table's owner.
/// None otherwise.
pub fn rename_table(conn: &mut MysqlConnection, tblid: i32, new_name: String, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid {
return None;
}
let rnm = jrtables::rename_jrtable(conn, tblid, &new_name);
if rnm.is_err() {
return None;
}
Some(true)
}
/// Delete a table.
/// Needs the user ID of the requesting user.
/// Returns Some(true) if the action seems to have been successful and the requesting user is the
/// table's owner.
/// None otherwise.
pub fn delete_table(conn: &mut MysqlConnection, tblid: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid {
return None;
}
let dlt = jrtables::delete_jrtable(conn, tblid);
if dlt.is_err() {
return None;
}
Some(true)
}
/// Create a new table.
/// Needs the user ID of the requesting user.
/// Returns the id of the newly created table if the action seems to have been successful and the requesting user is the
/// table's owner.
/// None otherwise.
pub fn create_table(conn: &mut MysqlConnection, name: String, field_names: Vec<String>, uid: i32) -> Option<i32> {
if jrtables::get_tbl_by_name_uid(conn, &name, uid).is_ok() {
return None;
}
if jrtables::create_jrtable(conn, &name, field_names, uid).is_err() {
return None;
}
let tblid = jrtables::get_tbl_by_name_uid(conn, &name, uid);
if tblid.is_err() {
return None;
}
Some(tblid.unwrap())
}
/// Returns a User struct of a requested user if the combination of username and email are
/// consistent or both do not exist yet, in which case the user is newly created.
pub fn register_or_login(conn: &mut MysqlConnection, uname: String, mail: String) -> Option<User> {
let mut uid = users::get_uid_email(conn, &mail);
if uid.is_err() {
if users::get_uid_uname(conn, &uname).is_ok() || users::create_user(conn, &uname, &mail).is_err() {
return None;
}
uid = users::get_uid_email(conn, &mail);
if uid.is_err() {
return None;
}
}
let uid = uid.unwrap();
let nm = users::get_uname(conn, uid);
if nm.is_err() || nm.unwrap() != uname {
return None;
}
Some(User { uid: uid, uname: uname, email: mail })
}
pub fn delete_user(conn: &mut MysqlConnection, uid: i32) -> Option<bool> {
if users::delete_user(conn, uid).is_err() {
return None;
}
Some(true)
}
pub fn add_row(conn: &mut MysqlConnection, tblid: i32, values: Vec<String>, uid: i32) -> Option<i32> {
let owner = jrtables::get_owner_id(conn, tblid);
let nrows = jrtables::get_nrows(conn, tblid);
if nrows.is_err() || owner.is_err() || owner.unwrap() != uid {
return None;
}
let nrows = nrows.unwrap() as i32;
if jrentries::create_jrentry(conn, tblid).is_err() {
return None;
}
let entryid = jrentries::get_jrentry_id(conn, tblid, nrows+1);
if entryid.is_err() {
return None;
}
let entryid = entryid.unwrap();
let cols = jrcolumns::get_clmns_of(conn, tblid);
if cols.is_err() {
return None;
}
let cols = cols.unwrap();
for (i,col) in cols.iter().enumerate() {
if jrcells::create_jrcell(conn, entryid, col.id, &values[i]).is_err() {
return None;
}
}
Some(entryid)
}
pub fn delete_row(conn: &mut MysqlConnection, tblid: i32, row_pos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid || jrentries::delete_jrentry_relative(conn, tblid, row_pos).is_err() {
return None;
}
Some(true)
}
pub fn move_row(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, newpos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid || jrentries::move_jrentry(conn, tblid, rowpos, newpos).is_err() {
return None;
}
Some(true)
}
pub fn edit_cell(conn: &mut MysqlConnection, tblid: i32, row_pos: i32, column_pos: i32, new_value: String, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcells::change_jrcell_value_relative(conn, tblid, row_pos, column_pos, new_value).is_err()
{
return None;
}
Some(true)
}
pub fn move_column(conn: &mut MysqlConnection, tblid:i32, column_pos: i32, new_column_pos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::move_column_relative(conn, tblid, column_pos, new_column_pos).is_err()
{
return None;
}
Some(true)
}
pub fn add_column(conn: &mut MysqlConnection, tblid: i32, name: String, uid: i32) -> Option<i32> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::create_jrcolumn(conn, tblid, name).is_err()
{
return None;
}
let clmid = jrcolumns::get_last_column_id_of(conn, tblid);
if clmid.is_err() {
return None;
}
Some(clmid.unwrap())
}
pub fn delete_column(conn: &mut MysqlConnection, tblid: i32, column_pos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::delete_column_relative(conn, tblid, column_pos).is_err()
{
return None;
}
Some(true)
}
pub fn rename_column(conn: &mut MysqlConnection, tblid: i32, column_pos: i32, new_name: String, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::rename_column_relative(conn, tblid, column_pos, new_name).is_err()
{
return None;
}
Some(true)
}

314
inventur_db/src/lib.rs~ Normal file
View File

@ -0,0 +1,314 @@
//! Database API using the table style system provided by this crate
mod models;
mod schema;
mod jrtables;
mod jrcolumns;
mod jrentries;
mod jrcells;
mod users;
use dotenvy::dotenv;
use std::env;
use diesel::mysql::MysqlConnection;
use diesel::prelude::*;
/// represents and summarised all relevant data of a table.
/// Standard return type if whole tables should be returned
pub struct Tbl {
/// table id of the represented object
pub tblid: i32,
pub name: String,
pub column_names: Vec<String>,
pub rows: Vec<TRow>,
}
/// Represents a table's row.
/// Internal data structure is abstracted until strings.
pub struct TRow {
pub row_pos: i32,
pub cells: Vec<String>,
}
/// Identifies a user
/// All fields are unique within the db at any given point.
pub struct User {
/// User's unique id.
pub uid: i32,
pub uname: String,
pub email: String,
}
/// Connect to database.
/// Return value must be passed to most of the crate's functions.
pub fn establish_connection() -> MysqlConnection {
dotenv().ok();
let db_url = env::var("DATABASE_URL").expect("No database url set.");
MysqlConnection::establish(&db_url)
.unwrap_or_else(|_| panic!("Couldn't open database."))
}
/// Fetch one whole table from the database. Identified by it's ID.
/// Needs the id of the requesting user.
/// Returns:
/// A Tbl struct
/// Or:
/// None
/// if the table was not found or
/// if it could not be read or
/// if the requesting user is not the table's owner or
/// if there has been another error
///
pub fn get_table(conn: &mut MysqlConnection, tblid: i32, uid: i32) -> Option<Tbl> {
let tbl = jrtables::get_tbl(conn, tblid);
if tbl.is_err() {
return None;
}
let tbl = tbl.unwrap();
if tbl.owner_id != uid {
return None;
}
let clmns = jrcolumns::get_clmns_of(conn, tblid);
if clmns.is_err() {
return None;
}
let clmns = clmns.unwrap();
let mut clmn_nms = Vec::new();
for clmn in &clmns {
clmn_nms.push(clmn.name.clone());
}
let clmn_nms = clmn_nms;
let mut clmn_ids = Vec::new();
for clmn in clmns {
clmn_ids.push(clmn.id);
}
let clmn_ids = clmn_ids;
let rowids = jrentries::get_entries_of(conn, tblid);
if rowids.is_err() {
return None;
}
let rowids = rowids.unwrap();
let mut rows = Vec::new();
for rowid in rowids {
let row = jrcells::get_entry_cells(conn, rowid.id);
if row.is_err() {
return None;
}
let row = row.unwrap();
let mut data = Vec::new();
for cell in row {
data.push(cell.cell_value);
}
let data = data;
rows.push(TRow { row_pos: rowid.row_pos, cells: data });
}
Some(Tbl { tblid: tbl.id, name: tbl.name, column_names: clmn_nms, rows: rows })
}
pub fn get_tblnames(conn: &mut MysqlConnection, tblids: Vec<i32>) -> Option<Vec<String>> {
let mut tblnames = Vec::new();
for tblid in tblids {
let tblname = jrtables::get_tbl(conn, tblid);
if tblname.is_err() {
return None;
}
tblnames.push(tblname.unwrap().name);
}
Some(tblnames)
}
/// Returns a Vec of the ids of a user's table if the user exists, else None.
/// User is identified by its user ID.
pub fn get_user_tblids(conn: &mut MysqlConnection, uid: i32) -> Option<Vec<i32>> {
let tblids = jrtables::get_tblids_uid(conn, uid);
if tblids.is_err() {
return None;
}
Some(tblids.unwrap())
}
/// Change the name of a table.
/// Needs the user ID of the requesting user.
/// Returns Some(true) if the action seems to have been successful and the requesting user is the
/// table's owner.
/// None otherwise.
pub fn rename_table(conn: &mut MysqlConnection, tblid: i32, new_name: String, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid {
return None;
}
let rnm = jrtables::rename_jrtable(conn, tblid, &new_name);
if rnm.is_err() {
return None;
}
Some(true)
}
/// Delete a table.
/// Needs the user ID of the requesting user.
/// Returns Some(true) if the action seems to have been successful and the requesting user is the
/// table's owner.
/// None otherwise.
pub fn delete_table(conn: &mut MysqlConnection, tblid: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid {
return None;
}
let dlt = jrtables::delete_jrtable(conn, tblid);
if dlt.is_err() {
return None;
}
Some(true)
}
/// Create a new table.
/// Needs the user ID of the requesting user.
/// Returns the id of the newly created table if the action seems to have been successful and the requesting user is the
/// table's owner.
/// None otherwise.
pub fn create_table(conn: &mut MysqlConnection, name: String, field_names: Vec<String>, uid: i32) -> Option<i32> {
if jrtables::get_tbl_by_name_uid(conn, &name, uid).is_ok() {
return None;
}
if jrtables::create_jrtable(conn, &name, field_names, uid).is_err() {
return None;
}
let tblid = jrtables::get_tbl_by_name_uid(conn, &name, uid);
if tblid.is_err() {
return None;
}
Some(tblid.unwrap())
}
/// Returns a User struct of a requested user if the combination of username and email are
/// consistent or both do not exist yet, in which case the user is newly created.
pub fn register_or_login(conn: &mut MysqlConnection, uname: String, mail: String) -> Option<User> {
let mut uid = users::get_uid_email(conn, &mail);
if uid.is_err() {
if users::get_uid_uname(conn, &uname).is_ok() || users::create_user(conn, &uname, &mail).is_err() {
return None;
}
uid = users::get_uid_email(conn, &mail);
if uid.is_err() {
return None;
}
}
let uid = uid.unwrap();
let nm = users::get_uname(conn, uid);
if nm.is_err() || nm.unwrap() != uname {
return None;
}
Some(User { uid: uid, uname: uname, email: mail })
}
pub fn delete_user(conn: &mut MysqlConnection, uid: i32) -> Option<bool> {
if users::delete_user(conn, uid).is_err() {
return None;
}
Some(true)
}
pub fn add_row(conn: &mut MysqlConnection, tblid: i32, values: Vec<String>, uid: i32) -> Option<i32> {
let owner = jrtables::get_owner_id(conn, tblid);
let nrows = jrtables::get_nrows(conn, tblid);
if nrows.is_err() || owner.is_err() || owner.unwrap() != uid {
return None;
}
let nrows = nrows.unwrap() as i32;
if jrentries::create_jrentry(conn, tblid).is_err() {
return None;
}
let entryid = jrentries::get_jrentry_id(conn, tblid, nrows+1);
if entryid.is_err() {
return None;
}
let entryid = entryid.unwrap();
let cols = jrcolumns::get_clmns_of(conn, tblid);
if cols.is_err() {
return None;
}
let cols = cols.unwrap();
for (i,col) in cols.iter().enumerate() {
if jrcells::create_jrcell(conn, entryid, col.id, &values[i]).is_err() {
return None;
}
}
Some(entryid)
}
pub fn delete_row(conn: &mut MysqlConnection, tblid: i32, row_pos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid || jrentries::delete_jrentry_relative(conn, tblid, row_pos).is_err() {
return None;
}
Some(true)
}
pub fn move_row(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, newpos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() || owner.unwrap() != uid || jrentries::move_jrentry(conn, tblid, rowpos, newpos).is_err() {
return None;
}
Some(true)
}
pub fn edit_cell(conn: &mut MysqlConnection, tblid: i32, row_pos: i32, column_pos: i32, new_value: String, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcells::change_jrcell_value_relative(conn, tblid, row_pos, column_pos, new_value).is_err()
{
return None;
}
Some(true)
}
pub fn move_column(conn: &mut MysqlConnection, tblid:i32, column_pos: i32, new_column_pos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::move_column_relative(conn, tblid, column_pos, new_column_pos).is_err()
{
return None;
}
Some(true)
}
pub fn add_column(conn: &mut MysqlConnection, tblid: i32, name: String, uid: i32) -> Option<i32> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::create_jrcolumn(conn, tblid, name).is_err()
{
return None;
}
let clmid = jrcolumns::get_last_column_id_of(conn, tblid);
if clmid.is_err() {
return None;
}
Some(clmid.unwrap())
}
pub fn delete_column(conn: &mut MysqlConnection, tblid: i32, column_pos: i32, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::delete_column_relative(conn, tblid, column_pos).is_err()
{
return None;
}
Some(true)
}
pub fn rename_column(conn: &mut MysqlConnection, tblid: i32, column_pos: i32, new_name: String, uid: i32) -> Option<bool> {
let owner = jrtables::get_owner_id(conn, tblid);
if owner.is_err() ||
owner.unwrap() != uid ||
jrcolumns::rename_column_relative(conn, tblid, column_pos, new_name).is_err()
{
return None;
}
Some(true)
}

98
inventur_db/src/models.rs Normal file
View File

@ -0,0 +1,98 @@
use diesel::prelude::*;
use crate::schema::{jrtables, jrcolumns, jrentries, jrcells, users};
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = crate::schema::jrtables)]
#[diesel(belongs_to(User, foreign_key = owner_id))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrtable {
pub id: i32,
pub name: String,
pub owner_id: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrtables)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrtable {
pub name: String,
pub owner_id: i32,
}
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = jrcolumns)]
#[diesel(belongs_to(Jrtable))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrcolumn {
pub id: i32,
pub column_type: crate::FIELDTYPE,
pub name: String,
pub jrtable_id: i32,
pub id_in_table: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrcolumns)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrcolumn {
pub name: String,
pub jrtable_id: i32,
pub id_in_table: i32,
}
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = jrentries)]
#[diesel(belongs_to(Jrtable))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrentry {
pub id: i32,
pub row_pos: i32,
pub jrtable_id: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrentries)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrentry {
pub row_pos: i32,
pub jrtable_id: i32,
}
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = jrcells)]
#[diesel(belongs_to(Jrentry))]
#[diesel(belongs_to(Jrcolumn))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrcell {
pub id: i32,
pub cell_value: String,
pub jrentry_id: i32,
pub jrcolumn_id: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrcells)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrcell {
pub cell_value: String,
pub jrentry_id: i32,
pub jrcolumn_id: i32,
}
#[derive(Queryable, Selectable, Identifiable)]
#[diesel(table_name = users)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct User {
pub id: i32,
pub username: String,
pub email: String,
}
#[derive(Insertable)]
#[diesel(table_name = users)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewUser {
pub username: String,
pub email: String,
}

View File

@ -0,0 +1,97 @@
use diesel::prelude::*;
use crate::schema::{jrtables, jrcolumns, jrentries, jrcells, users};
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = crate::schema::jrtables)]
#[diesel(belongs_to(User, foreign_key = owner_id))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrtable {
pub id: i32,
pub name: String,
pub owner_id: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrtables)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrtable {
pub name: String,
pub owner_id: i32,
}
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = jrcolumns)]
#[diesel(belongs_to(Jrtable))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrcolumn {
pub id: i32,
pub name: String,
pub jrtable_id: i32,
pub id_in_table: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrcolumns)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrcolumn {
pub name: String,
pub jrtable_id: i32,
pub id_in_table: i32,
}
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = jrentries)]
#[diesel(belongs_to(Jrtable))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrentry {
pub id: i32,
pub row_pos: i32,
pub jrtable_id: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrentries)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrentry {
pub row_pos: i32,
pub jrtable_id: i32,
}
#[derive(Queryable, Selectable, Identifiable, Associations)]
#[diesel(table_name = jrcells)]
#[diesel(belongs_to(Jrentry))]
#[diesel(belongs_to(Jrcolumn))]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Jrcell {
pub id: i32,
pub cell_value: String,
pub jrentry_id: i32,
pub jrcolumn_id: i32,
}
#[derive(Insertable)]
#[diesel(table_name = jrcells)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewJrcell {
pub cell_value: String,
pub jrentry_id: i32,
pub jrcolumn_id: i32,
}
#[derive(Queryable, Selectable, Identifiable)]
#[diesel(table_name = users)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct User {
pub id: i32,
pub username: String,
pub email: String,
}
#[derive(Insertable)]
#[diesel(table_name = users)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct NewUser {
pub username: String,
pub email: String,
}

63
inventur_db/src/schema.rs Normal file
View File

@ -0,0 +1,63 @@
// @generated automatically by Diesel CLI.
diesel::table! {
jrcells (id) {
id -> Integer,
#[max_length = 2048]
cell_value -> Varchar,
jrentry_id -> Integer,
jrcolumn_id -> Integer,
}
}
diesel::table! {
jrcolumns (id) {
id -> Integer,
#[max_length = 255]
name -> Varchar,
jrtable_id -> Integer,
id_in_table -> Integer,
column_type -> Integer,
}
}
diesel::table! {
jrentries (id) {
id -> Integer,
row_pos -> Integer,
jrtable_id -> Integer,
}
}
diesel::table! {
jrtables (id) {
id -> Integer,
#[max_length = 255]
name -> Varchar,
owner_id -> Integer,
}
}
diesel::table! {
users (id) {
id -> Integer,
#[max_length = 255]
username -> Varchar,
#[max_length = 512]
email -> Varchar,
}
}
diesel::joinable!(jrcells -> jrcolumns (jrcolumn_id));
diesel::joinable!(jrcells -> jrentries (jrentry_id));
diesel::joinable!(jrcolumns -> jrtables (jrtable_id));
diesel::joinable!(jrentries -> jrtables (jrtable_id));
diesel::joinable!(jrtables -> users (owner_id));
diesel::allow_tables_to_appear_in_same_query!(
jrcells,
jrcolumns,
jrentries,
jrtables,
users,
);

56
inventur_db/src/users.rs Normal file
View File

@ -0,0 +1,56 @@
use crate::models;
use crate::schema;
use schema::users::dsl::{users, id, username, email};
use models::NewUser;
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
pub fn create_user(conn: &mut MysqlConnection, uname: &String, mail: &String) -> Result<usize, diesel::result::Error> {
let user = NewUser { username: uname.to_string(), email: mail.to_string()};
diesel::insert_into(crate::schema::users::table)
.values(&user)
.execute(conn)
}
pub fn delete_user(conn: &mut MysqlConnection, uid: i32) -> Result<usize, diesel::result::Error> {
diesel::delete(users.find(uid))
.execute(conn)
}
pub fn get_uid_email(conn: &mut MysqlConnection, mail: &String) -> Result<i32, diesel::result::Error> {
users
.filter(email.eq(mail))
.select(id)
.first::<i32>(conn)
}
pub fn get_uid_uname(conn: &mut MysqlConnection, uname: &String) -> Result<i32, diesel::result::Error> {
users
.filter(username.eq(uname))
.select(id)
.first::<i32>(conn)
}
pub fn get_uname(conn: &mut MysqlConnection, uid: i32) -> Result<String, diesel::result::Error> {
users
.find(uid)
.select(username)
.first::<String>(conn)
}
pub fn get_email(conn: &mut MysqlConnection, uid: i32) -> Result<String, diesel::result::Error> {
users
.find(uid)
.select(email)
.first::<String>(conn)
}
pub fn get_user_tables(conn: &mut MysqlConnection, uid: i32) -> Result<Vec<i32>, diesel::result::Error> {
use schema::jrtables::dsl::{jrtables, id as tblid, owner_id};
jrtables
.filter(owner_id.eq(uid))
.select(tblid)
.load::<i32>(conn)
}

56
inventur_db/src/users.rs~ Normal file
View File

@ -0,0 +1,56 @@
use crate::models;
use crate::schema;
use schema::users::dsl::{users, id, username, email};
use models::NewUser;
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
pub fn create_user(conn: &mut MysqlConnection, uname: String, mail: String) -> Result<usize, diesel::result::Error> {
let user = NewUser { username: uname, email: mail};
diesel::insert_into(crate::schema::users::table)
.values(&user)
.execute(conn)
}
pub fn delete_user(conn: &mut MysqlConnection, uid: i32) -> Result<usize, diesel::result::Error> {
diesel::delete(users.find(uid))
.execute(conn)
}
pub fn get_uid_email(conn: &mut MysqlConnection, mail: String) -> Result<i32, diesel::result::Error> {
users
.filter(email.eq(mail))
.select(id)
.first::<i32>(conn)
}
pub fn get_uid_uname(conn: &mut MysqlConnection, uname: String) -> Result<i32, diesel::result::Error> {
users
.filter(username.eq(uname))
.select(id)
.first::<i32>(conn)
}
pub fn get_uname(conn: &mut MysqlConnection, uid: i32) -> Result<String, diesel::result::Error> {
users
.find(uid)
.select(username)
.first::<String>(conn)
}
pub fn get_email(conn: &mut MysqlConnection, uid: i32) -> Result<String, diesel::result::Error> {
users
.find(uid)
.select(email)
.first::<String>(conn)
}
pub fn get_user_tables(conn: &mut MysqlConnection, uid: i32) -> Result<Vec<i32>, diesel::result::Error> {
use schema::jrtables::dsl::{jrtables, id as tblid, owner_id};
jrtables
.filter(owner_id.eq(uid))
.select(tblid)
.load::<i32>(conn)
}

View File

@ -1,6 +0,0 @@
-- Your SQL goes here
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(64) NOT NULL,
name VARCHAR(255)
);

12
node_modules/.package-lock.json generated vendored Normal file
View File

@ -0,0 +1,12 @@
{
"name": "inventur",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/papaparse": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
"integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
}
}
}

279
node_modules/papaparse/.eslintrc.js generated vendored Normal file
View File

@ -0,0 +1,279 @@
module.exports = {
"parserOptions": {
"ecmaVersion": 5
},
"env": {
"browser": true,
"worker": true,
"node": true
},
"extends": "eslint:recommended",
"rules": {
"accessor-pairs": "error",
"array-bracket-newline": ["error", "consistent"],
"array-bracket-spacing": [
"error",
"never"
],
"array-callback-return": "error",
"array-element-newline": "off",
"arrow-body-style": "error",
"arrow-parens": "error",
"arrow-spacing": "error",
"block-scoped-var": "error",
"block-spacing": "error",
"brace-style": "off",
"callback-return": "error",
"camelcase": ["error", {"properties": "never"}],
"capitalized-comments": "off",
"class-methods-use-this": "error",
"comma-dangle": "off",
"comma-spacing": "off",
"comma-style": [
"error",
"last"
],
"complexity": "off",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "off",
"curly": "off",
"default-case": "error",
"dot-location": "error",
"dot-notation": "error",
"eol-last": "error",
"eqeqeq": "error",
"for-direction": "error",
"func-call-spacing": "error",
"func-name-matching": "error",
"func-names": [
"error",
"never"
],
"func-style": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"getter-return": "error",
"global-require": "off",
"guard-for-in": "off",
"handle-callback-err": "error",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"implicit-arrow-linebreak": "error",
"indent": [
"error",
"tab"
],
"indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "error",
"keyword-spacing": "off",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "off",
"lines-around-directive": "off",
"lines-between-class-members": "error",
"max-depth": "off",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-comment-style": "off",
"multiline-ternary": [
"error",
"always-multiline"
],
"new-parens": "error",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "error",
"no-array-constructor": "error",
"no-await-in-loop": "error",
"no-bitwise": "error",
"no-buffer-constructor": "error",
"no-caller": "error",
"no-catch-shadow": "off",
"no-cond-assign": [
"error",
"except-parens"
],
"no-confusing-arrow": "error",
"no-console": "off",
"no-continue": "off",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty": ["error", {"allowEmptyCatch": true}],
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "error",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "off",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "off",
"no-plusplus": "off",
"no-process-env": "error",
"no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-spaced-func": "error",
"no-sync": ["error", {"allowAtRootLevel": true}],
"no-tabs": "off",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef-init": "error",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "off",
"no-unneeded-ternary": "error",
"no-unused-expressions": "off",
"no-unused-vars": ["error", {"args": "none"}],
"no-use-before-define": "off",
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-constructor": "error",
"no-useless-rename": "error",
"no-useless-return": "off",
"no-var": "off",
"no-void": "error",
"no-warning-comments": "error",
"no-whitespace-before-property": "error",
"no-with": "error",
"nonblock-statement-body-position": [
"error",
"any"
],
"object-curly-newline": ["error", {"consistent": true}],
"object-curly-spacing": "off",
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": [
"error",
"always"
],
"operator-linebreak": "off",
"padded-blocks": "off",
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-const": "error",
"prefer-destructuring": "off",
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "error",
"prefer-template": "off",
"quote-props": "off",
"quotes": "off",
"radix": [
"error",
"as-needed"
],
"require-await": "error",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": "error",
"semi-spacing": "error",
"semi-style": [
"error",
"last"
],
"sort-imports": "error",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "error",
"space-before-function-paren": [
"error",
"never"
],
"space-in-parens": [
"error",
"never"
],
"space-infix-ops": "error",
"space-unary-ops": [
"error",
{
"nonwords": false,
"words": false
}
],
"spaced-comment": "off",
"strict": "off",
"switch-colon-spacing": "error",
"symbol-description": "error",
"template-curly-spacing": "error",
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "off",
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"yield-star-spacing": "error",
"yoda": "off"
}
};

29
node_modules/papaparse/.github/workflows/node.js.yml generated vendored Normal file
View File

@ -0,0 +1,29 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node.js CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test

27
node_modules/papaparse/Gruntfile.js generated vendored Normal file
View File

@ -0,0 +1,27 @@
module.exports = function(grunt) {
grunt.initConfig({
uglify: {
options: {
compress: {
global_defs: {
'PAPA_BROWSER_CONTEXT': true
},
dead_code: true
},
output: {
comments: 'some',
},
},
min: {
files: {
'papaparse.min.js': ['papaparse.js']
},
},
},
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('build', ['uglify']);
grunt.registerTask('default', ['uglify']);
};

20
node_modules/papaparse/LICENSE generated vendored Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2015 Matthew Holt
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 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.

67
node_modules/papaparse/README.md generated vendored Normal file
View File

@ -0,0 +1,67 @@
Parse CSV with JavaScript
========================================
Papa Parse is the fastest in-browser CSV (or delimited text) parser for JavaScript. It is reliable and correct according to [RFC 4180](https://tools.ietf.org/html/rfc4180), and it comes with these features:
- Easy to use
- Parse CSV files directly (local or over the network)
- Fast mode
- Stream large files (even via HTTP)
- Reverse parsing (converts JSON to CSV)
- Auto-detect delimiter
- Worker threads to keep your web page reactive
- Header row support
- Pause, resume, abort
- Can convert numbers and booleans to their types
- Optional jQuery integration to get files from `<input type="file">` elements
- One of the only parsers that correctly handles line-breaks and quotations
Papa Parse has **no dependencies** - not even jQuery.
Install
-------
papaparse is available on [npm](https://www.npmjs.com/package/papaparse). It
can be installed with the following command:
npm install papaparse
If you don't want to use npm, [papaparse.min.js](https://unpkg.com/papaparse@latest/papaparse.min.js) can be downloaded to your project source.
Homepage & Demo
----------------
- [Homepage](http://papaparse.com)
- [Demo](http://papaparse.com/demo)
To learn how to use Papa Parse:
- [Documentation](http://papaparse.com/docs)
The website is hosted on [Github Pages](https://pages.github.com/). Its content is also included in the docs folder of this repository. If you want to contribute on it just clone the master of this repository and open a pull request.
Papa Parse for Node
--------------------
Papa Parse can parse a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) instead of a [File](https://www.w3.org/TR/FileAPI/) when used in Node.js environments (in addition to plain strings). In this mode, `encoding` must, if specified, be a Node-supported character encoding. The `Papa.LocalChunkSize`, `Papa.RemoteChunkSize` , `download`, `withCredentials` and `worker` config options are unavailable.
Papa Parse can also parse in a node streaming style which makes `.pipe` available. Simply pipe the [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) to the stream returned from `Papa.parse(Papa.NODE_STREAM_INPUT, options)`. The `Papa.LocalChunkSize`, `Papa.RemoteChunkSize` , `download`, `withCredentials`, `worker`, `step`, and `complete` config options are unavailable. To register a callback with the stream to process data, use the `data` event like so: `stream.on('data', callback)` and to signal the end of stream, use the 'end' event like so: `stream.on('end', callback)`.
Get Started
-----------
For usage instructions, see the [homepage](http://papaparse.com) and, for more detail, the [documentation](http://papaparse.com/docs).
Tests
-----
Papa Parse is under test. Download this repository, run `npm install`, then `npm test` to run the tests.
Contributing
------------
To discuss a new feature or ask a question, open an issue. To fix a bug, submit a pull request to be credited with the [contributors](https://github.com/mholt/PapaParse/graphs/contributors)! Remember, a pull request, *with test*, is best. You may also discuss on Twitter with [#PapaParse](https://twitter.com/search?q=%23PapaParse&src=typd&f=realtime) or directly to me, [@mholt6](https://twitter.com/mholt6).
If you contribute a patch, ensure the tests suite is running correctly. We run continuous integration on each pull request and will not accept a patch that breaks the tests.

40
node_modules/papaparse/bower.json generated vendored Normal file
View File

@ -0,0 +1,40 @@
{
"name": "papaparse",
"main": "papaparse.js",
"homepage": "http://papaparse.com",
"authors": [
"Matthew Holt"
],
"description": "Fast and powerful CSV parser for the browser. Converts CSV->JSON and JSON->CSV. Supports web workers and streaming large files.",
"keywords": [
"csv",
"parse",
"parsing",
"parser",
"delimited",
"text",
"data",
"auto-detect",
"comma",
"tab",
"pipe",
"file",
"filereader",
"stream",
"worker",
"workers",
"ajax",
"thread",
"threading",
"multi-threaded"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests",
"player"
]
}

57
node_modules/papaparse/package.json generated vendored Normal file
View File

@ -0,0 +1,57 @@
{
"name": "papaparse",
"version": "5.4.1",
"description": "Fast and powerful CSV parser for the browser that supports web workers and streaming large files. Converts CSV to JSON and JSON to CSV.",
"keywords": [
"csv",
"parser",
"parse",
"parsing",
"delimited",
"text",
"data",
"auto-detect",
"comma",
"tab",
"pipe",
"file",
"filereader",
"stream",
"worker",
"workers",
"thread",
"threading",
"multi-threaded",
"jquery-plugin"
],
"homepage": "http://papaparse.com",
"repository": {
"type": "git",
"url": "https://github.com/mholt/PapaParse.git"
},
"author": {
"name": "Matthew Holt",
"url": "https://twitter.com/mholt6"
},
"license": "MIT",
"main": "papaparse.js",
"browser": "papaparse.min.js",
"devDependencies": {
"chai": "^4.2.0",
"connect": "^3.3.3",
"eslint": "^4.19.1",
"grunt": "^1.0.2",
"grunt-contrib-uglify": "^3.3.0",
"mocha": "^5.2.0",
"mocha-headless-chrome": "^4.0.0",
"open": "7.0.0",
"serve-static": "^1.7.1"
},
"scripts": {
"lint": "eslint --no-ignore papaparse.js Gruntfile.js .eslintrc.js 'tests/**/*.js'",
"test-browser": "node tests/test.js",
"test-mocha-headless-chrome": "node tests/test.js --mocha-headless-chrome",
"test-node": "mocha tests/node-tests.js tests/test-cases.js",
"test": "npm run lint && npm run test-node && npm run test-mocha-headless-chrome"
}
}

1922
node_modules/papaparse/papaparse.js generated vendored Executable file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More