mirror of https://github.com/raftario/filite.git
Initial commit
This commit is contained in:
commit
d5ac4b8b6a
|
@ -0,0 +1,10 @@
|
|||
# Rust build artifacts
|
||||
target/
|
||||
**/*.rs.bk
|
||||
|
||||
# User specific files
|
||||
.env
|
||||
**/*.db
|
||||
|
||||
# JetBrains settings
|
||||
.idea/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "filite"
|
||||
version = "0.1.0"
|
||||
authors = ["Raphaël Thériault <raphael_theriault@outlook.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "1.0.8"
|
||||
chrono = "0.4.9"
|
||||
[dependencies.diesel]
|
||||
version = "1.4.2"
|
||||
features = ["r2d2", "sqlite"]
|
||||
[dependencies.libsqlite3-sys]
|
||||
version = "0.12.0"
|
||||
features = ["bundled"]
|
||||
|
||||
[dev-dependencies]
|
||||
dotenv = "0.14.1"
|
|
@ -0,0 +1,2 @@
|
|||
[print_schema]
|
||||
file = "src/schema.rs"
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE files
|
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE files (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
filepath TEXT NOT NULL,
|
||||
created INTEGER NOT NULL DEFAULT (datetime('now')),
|
||||
updated INTEGER NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE links
|
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE links (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
forward TEXT NOT NULL,
|
||||
created INTEGER NOT NULL DEFAULT (datetime('now')),
|
||||
updated INTEGER NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE texts
|
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE texts (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
contents TEXT NOT NULL,
|
||||
created INTEGER NOT NULL DEFAULT (datetime('now')),
|
||||
updated INTEGER NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
|
@ -0,0 +1,28 @@
|
|||
#[macro_use]
|
||||
extern crate diesel;
|
||||
|
||||
use diesel::r2d2::{self, ConnectionManager};
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
|
||||
pub mod models;
|
||||
pub mod queries;
|
||||
pub mod schema;
|
||||
|
||||
/// SQLite database connection pool
|
||||
pub type Pool = r2d2::Pool<ConnectionManager<SqliteConnection>>;
|
||||
|
||||
/// Functions used for the initial setup
|
||||
pub mod setup {
|
||||
use crate::Pool;
|
||||
|
||||
use diesel::r2d2::{self, ConnectionManager};
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
|
||||
/// Creates a SQLite database connection pool
|
||||
pub fn create_pool(url: &str) -> Pool {
|
||||
let manager = ConnectionManager::<SqliteConnection>::new(url);
|
||||
r2d2::Pool::builder()
|
||||
.build(manager)
|
||||
.expect("Can't create pool.")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
//! Database models
|
||||
|
||||
/// Models from the `files` table
|
||||
pub mod files {
|
||||
use crate::schema::files;
|
||||
|
||||
/// An entry from the `files` table
|
||||
#[derive(Queryable, Identifiable)]
|
||||
pub struct File {
|
||||
pub id: i32,
|
||||
pub filepath: String,
|
||||
pub created: i32,
|
||||
pub updated: i32,
|
||||
}
|
||||
|
||||
/// A new entry to the `files` table
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "files"]
|
||||
pub struct NewFile<'a> {
|
||||
pub id: i32,
|
||||
pub filepath: &'a str,
|
||||
}
|
||||
}
|
||||
|
||||
/// Models from the `links` table
|
||||
pub mod links {
|
||||
use crate::schema::links;
|
||||
|
||||
/// An entry from the `links` table
|
||||
#[derive(Queryable, Identifiable)]
|
||||
pub struct Link {
|
||||
pub id: i32,
|
||||
pub forward: String,
|
||||
pub created: i32,
|
||||
pub updated: i32,
|
||||
}
|
||||
|
||||
/// A new entry to the `links` table
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "links"]
|
||||
pub struct NewLink<'a> {
|
||||
pub id: i32,
|
||||
pub forward: &'a str,
|
||||
}
|
||||
}
|
||||
|
||||
/// Models from the `texts` table
|
||||
pub mod texts {
|
||||
use crate::schema::texts;
|
||||
|
||||
/// An entry from the `texts` table
|
||||
#[derive(Queryable, Identifiable)]
|
||||
pub struct Text {
|
||||
pub id: i32,
|
||||
pub contents: String,
|
||||
pub created: i32,
|
||||
pub updated: i32,
|
||||
}
|
||||
|
||||
/// A new entry to the `texts` table
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "texts"]
|
||||
pub struct NewText<'a> {
|
||||
pub id: i32,
|
||||
pub contents: &'a str,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
//! Helper functions for SQL queries
|
||||
|
||||
// A lot of duplicate code here could be merged by using macros
|
||||
|
||||
/// Queries affecting the `files` table
|
||||
pub mod files {
|
||||
use crate::models::files::*;
|
||||
use crate::schema::files::dsl::*;
|
||||
use crate::schema::files::table;
|
||||
use crate::Pool;
|
||||
|
||||
use actix_web::web::Data;
|
||||
use diesel::prelude::*;
|
||||
use diesel::result::QueryResult;
|
||||
|
||||
/// SELECT a single file entry given its id
|
||||
pub fn find(g_id: i32, pool: Data<Pool>) -> QueryResult<File> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
files.find(g_id).first::<File>(conn)
|
||||
}
|
||||
|
||||
/// INSERT a file entry
|
||||
pub fn insert(p_id: i32, p_filepath: &str, pool: Data<Pool>) -> QueryResult<File> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
let new_file = NewFile {
|
||||
id: p_id,
|
||||
filepath: p_filepath,
|
||||
};
|
||||
diesel::insert_into(table).values(&new_file).execute(conn)?;
|
||||
|
||||
find(p_id, pool)
|
||||
}
|
||||
|
||||
/// UPDATE a file entry
|
||||
pub fn update(
|
||||
p_id: i32,
|
||||
new_id: Option<i32>,
|
||||
new_filepath: Option<&str>,
|
||||
pool: Data<Pool>,
|
||||
) -> QueryResult<File> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
let file = find(p_id, pool)?;
|
||||
let query = diesel::update(&file);
|
||||
let time_update = updated.eq(chrono::Utc::now().timestamp() as i32);
|
||||
match (new_id, new_filepath) {
|
||||
(Some(new_id), Some(new_filepath)) => {
|
||||
query
|
||||
.set((id.eq(new_id), filepath.eq(new_filepath), time_update))
|
||||
.execute(conn)?;
|
||||
}
|
||||
(Some(new_id), None) => {
|
||||
query.set((id.eq(new_id), time_update)).execute(conn)?;
|
||||
}
|
||||
(None, Some(new_filepath)) => {
|
||||
query
|
||||
.set((filepath.eq(new_filepath), time_update))
|
||||
.execute(conn)?;
|
||||
}
|
||||
(None, None) => {
|
||||
return Ok(file);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
/// DELETE a file entry
|
||||
pub fn delete(d_id: i32, pool: Data<Pool>) -> QueryResult<()> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
diesel::delete(files.find(d_id)).execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries affecting the `links` table
|
||||
pub mod links {
|
||||
use crate::models::links::*;
|
||||
use crate::schema::links::dsl::*;
|
||||
use crate::schema::links::table;
|
||||
use crate::Pool;
|
||||
|
||||
use actix_web::web::Data;
|
||||
use diesel::prelude::*;
|
||||
use diesel::result::QueryResult;
|
||||
|
||||
/// SELECT a single link entry given its id
|
||||
pub fn find(g_id: i32, pool: Data<Pool>) -> QueryResult<Link> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
links.find(g_id).first::<Link>(conn)
|
||||
}
|
||||
|
||||
/// INSERT a link entry
|
||||
pub fn insert(p_id: i32, p_forward: &str, pool: Data<Pool>) -> QueryResult<Link> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
let new_link = NewLink {
|
||||
id: p_id,
|
||||
forward: p_forward,
|
||||
};
|
||||
diesel::insert_into(table).values(&new_link).execute(conn)?;
|
||||
|
||||
find(p_id, pool)
|
||||
}
|
||||
|
||||
/// UPDATE a link entry
|
||||
pub fn update(
|
||||
p_id: i32,
|
||||
new_id: Option<i32>,
|
||||
new_forward: Option<&str>,
|
||||
pool: Data<Pool>,
|
||||
) -> QueryResult<Link> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
let link = find(p_id, pool)?;
|
||||
let query = diesel::update(&link);
|
||||
let time_update = updated.eq(chrono::Utc::now().timestamp() as i32);
|
||||
match (new_id, new_forward) {
|
||||
(Some(new_id), Some(new_forward)) => {
|
||||
query
|
||||
.set((id.eq(new_id), forward.eq(new_forward), time_update))
|
||||
.execute(conn)?;
|
||||
}
|
||||
(Some(new_id), None) => {
|
||||
query.set((id.eq(new_id), time_update)).execute(conn)?;
|
||||
}
|
||||
(None, Some(new_forward)) => {
|
||||
query
|
||||
.set((forward.eq(new_forward), time_update))
|
||||
.execute(conn)?;
|
||||
}
|
||||
(None, None) => (),
|
||||
}
|
||||
|
||||
Ok(link)
|
||||
}
|
||||
|
||||
/// DELETE a link entry
|
||||
pub fn delete(d_id: i32, pool: Data<Pool>) -> QueryResult<()> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
diesel::delete(links.find(d_id)).execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries affecting the `texts` table
|
||||
pub mod texts {
|
||||
use crate::models::texts::*;
|
||||
use crate::schema::texts::dsl::*;
|
||||
use crate::schema::texts::table;
|
||||
use crate::Pool;
|
||||
|
||||
use actix_web::web::Data;
|
||||
use diesel::prelude::*;
|
||||
use diesel::result::QueryResult;
|
||||
|
||||
/// SELECT a single text entry given its id
|
||||
pub fn find(g_id: i32, pool: Data<Pool>) -> QueryResult<Text> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
texts.find(g_id).first::<Text>(conn)
|
||||
}
|
||||
|
||||
/// INSERT a text entry
|
||||
pub fn insert(p_id: i32, p_contents: &str, pool: Data<Pool>) -> QueryResult<Text> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
let new_text = NewText {
|
||||
id: p_id,
|
||||
contents: p_contents,
|
||||
};
|
||||
diesel::insert_into(table).values(&new_text).execute(conn)?;
|
||||
|
||||
find(p_id, pool)
|
||||
}
|
||||
|
||||
/// UPDATE a text entry
|
||||
pub fn update(
|
||||
p_id: i32,
|
||||
new_id: Option<i32>,
|
||||
new_contents: Option<&str>,
|
||||
pool: Data<Pool>,
|
||||
) -> QueryResult<Text> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
let text = find(p_id, pool)?;
|
||||
let query = diesel::update(&text);
|
||||
let time_update = updated.eq(chrono::Utc::now().timestamp() as i32);
|
||||
match (new_id, new_contents) {
|
||||
(Some(new_id), Some(new_contents)) => {
|
||||
query
|
||||
.set((id.eq(new_id), contents.eq(new_contents), time_update))
|
||||
.execute(conn)?;
|
||||
}
|
||||
(Some(new_id), None) => {
|
||||
query.set((id.eq(new_id), time_update)).execute(conn)?;
|
||||
}
|
||||
(None, Some(new_contents)) => {
|
||||
query
|
||||
.set((contents.eq(new_contents), time_update))
|
||||
.execute(conn)?;
|
||||
}
|
||||
(None, None) => (),
|
||||
}
|
||||
|
||||
Ok(text)
|
||||
}
|
||||
|
||||
/// DELETE a text entry
|
||||
pub fn delete(d_id: i32, pool: Data<Pool>) -> QueryResult<()> {
|
||||
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||
diesel::delete(texts.find(d_id)).execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
table! {
|
||||
files (id) {
|
||||
id -> Integer,
|
||||
filepath -> Text,
|
||||
created -> Integer,
|
||||
updated -> Integer,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
links (id) {
|
||||
id -> Integer,
|
||||
forward -> Text,
|
||||
created -> Integer,
|
||||
updated -> Integer,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
texts (id) {
|
||||
id -> Integer,
|
||||
contents -> Text,
|
||||
created -> Integer,
|
||||
updated -> Integer,
|
||||
}
|
||||
}
|
||||
|
||||
allow_tables_to_appear_in_same_query!(files, links, texts,);
|
Loading…
Reference in New Issue