Upgrade Diesel 1.x to 2.x and move the db to sqlite
parent
031abd96ce
commit
df669e8b78
|
@ -12,4 +12,9 @@ proyectos
|
||||||
Rocket.toml
|
Rocket.toml
|
||||||
|
|
||||||
# Certificates
|
# Certificates
|
||||||
*.pem
|
*.pem
|
||||||
|
|
||||||
|
# Sqlite database
|
||||||
|
*.db
|
||||||
|
*.sqlite
|
||||||
|
*.sqlite3
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { version = "0.5.0", features = ["secrets"] }
|
rocket = { version = "0.5.0", features = ["secrets"] }
|
||||||
rocket_dyn_templates = { version = "0.1.0", features = ["tera"] }
|
rocket_dyn_templates = { version = "0.1.0", features = ["tera"] }
|
||||||
diesel = { version = "1.0.0", features = ["postgres", "chrono"] }
|
diesel = { version = "2.0.0", features = ["sqlite", "chrono", "returning_clauses_for_sqlite_3_35"] }
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
chrono = { version = "0.4.9", features = ["serde"] }
|
chrono = { version = "0.4.9", features = ["serde"] }
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
-- This file was automatically created by Diesel to setup helper functions
|
|
||||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
|
||||||
-- changes will be added to existing projects as new migrations.
|
|
||||||
|
|
||||||
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
|
||||||
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
|
|
@ -1,36 +0,0 @@
|
||||||
-- This file was automatically created by Diesel to setup helper functions
|
|
||||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
|
||||||
-- changes will be added to existing projects as new migrations.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Sets up a trigger for the given table to automatically set a column called
|
|
||||||
-- `updated_at` whenever the row is modified (unless `updated_at` was included
|
|
||||||
-- in the modified columns)
|
|
||||||
--
|
|
||||||
-- # Example
|
|
||||||
--
|
|
||||||
-- ```sql
|
|
||||||
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
|
|
||||||
--
|
|
||||||
-- SELECT diesel_manage_updated_at('users');
|
|
||||||
-- ```
|
|
||||||
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
|
|
||||||
BEGIN
|
|
||||||
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
|
||||||
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
|
|
||||||
BEGIN
|
|
||||||
IF (
|
|
||||||
NEW IS DISTINCT FROM OLD AND
|
|
||||||
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
|
|
||||||
) THEN
|
|
||||||
NEW.updated_at := current_timestamp;
|
|
||||||
END IF;
|
|
||||||
RETURN NEW;
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
|
@ -1 +0,0 @@
|
||||||
DROP TABLE posts
|
|
|
@ -1,10 +0,0 @@
|
||||||
CREATE TABLE posts (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
title VARCHAR NOT NULL,
|
|
||||||
content TEXT NOT NULL,
|
|
||||||
published BOOLEAN NOT NULL DEFAULT 'f',
|
|
||||||
views integer NOT NULL DEFAULT 0,
|
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
-- This file should undo anything in `up.sql`
|
|
@ -0,0 +1,9 @@
|
||||||
|
CREATE TABLE posts (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
published BOOLEAN NOT NULL DEFAULT 0,
|
||||||
|
views INTEGER NOT NULL DEFAULT 0,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
18
src/admin.rs
18
src/admin.rs
|
@ -50,7 +50,7 @@ fn login(cookies: &CookieJar<'_>, login: Form<Login>) -> Redirect {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/panel")]
|
#[get("/panel")]
|
||||||
fn panel(cookies: &CookieJar<'_>) -> Result<Template, Redirect> {
|
fn panel(cookies: &CookieJar<'_>) -> Result<Template, Box<Redirect>> {
|
||||||
let password = env::var("admin_pass").expect("admin_pass not setted");
|
let password = env::var("admin_pass").expect("admin_pass not setted");
|
||||||
|
|
||||||
match cookies.get_private("user") {
|
match cookies.get_private("user") {
|
||||||
|
@ -62,15 +62,15 @@ fn panel(cookies: &CookieJar<'_>) -> Result<Template, Redirect> {
|
||||||
|
|
||||||
Ok(Template::render("admin/panel", context))
|
Ok(Template::render("admin/panel", context))
|
||||||
} else {
|
} else {
|
||||||
Err(Redirect::to("/admin"))
|
Err(Box::new(Redirect::to("/admin")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Err(Redirect::to("/admin")),
|
None => Err(Box::new(Redirect::to("/admin"))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/add_post")]
|
#[get("/add_post")]
|
||||||
fn add_post(cookies: &CookieJar<'_>) -> Result<Template, Redirect> {
|
fn add_post(cookies: &CookieJar<'_>) -> Result<Template, Box<Redirect>> {
|
||||||
let password = env::var("admin_pass").expect("admin_pass not setted");
|
let password = env::var("admin_pass").expect("admin_pass not setted");
|
||||||
|
|
||||||
match cookies.get_private("user") {
|
match cookies.get_private("user") {
|
||||||
|
@ -80,10 +80,10 @@ fn add_post(cookies: &CookieJar<'_>) -> Result<Template, Redirect> {
|
||||||
|
|
||||||
Ok(Template::render("admin/add_post", context))
|
Ok(Template::render("admin/add_post", context))
|
||||||
} else {
|
} else {
|
||||||
Err(Redirect::to("/admin"))
|
Err(Box::new(Redirect::to("/admin")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Err(Redirect::to("/admin")),
|
None => Err(Box::new(Redirect::to("/admin"))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ fn write_add_post(cookies: &CookieJar<'_>, post: Form<NewPost>) -> Redirect {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/edit_post/<id>")]
|
#[get("/edit_post/<id>")]
|
||||||
fn edit_post(cookies: &CookieJar<'_>, id: i32) -> Result<Template, Redirect> {
|
fn edit_post(cookies: &CookieJar<'_>, id: i32) -> Result<Template, Box<Redirect>> {
|
||||||
let password = env::var("admin_pass").expect("admin_pass not setted");
|
let password = env::var("admin_pass").expect("admin_pass not setted");
|
||||||
|
|
||||||
match cookies.get_private("user") {
|
match cookies.get_private("user") {
|
||||||
|
@ -119,10 +119,10 @@ fn edit_post(cookies: &CookieJar<'_>, id: i32) -> Result<Template, Redirect> {
|
||||||
|
|
||||||
Ok(Template::render("admin/edit_post", context))
|
Ok(Template::render("admin/edit_post", context))
|
||||||
} else {
|
} else {
|
||||||
Err(Redirect::to("/admin"))
|
Err(Box::new(Redirect::to("/admin")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Err(Redirect::to("/admin")),
|
None => Err(Box::new(Redirect::to("/admin"))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
use chrono::prelude::Utc;
|
use chrono::prelude::Utc;
|
||||||
use diesel::pg::PgConnection;
|
use diesel::sqlite::SqliteConnection;
|
||||||
use diesel::result::Error;
|
use diesel::result::Error;
|
||||||
use diesel::Connection;
|
use diesel::Connection;
|
||||||
use diesel::ExpressionMethods;
|
use diesel::ExpressionMethods;
|
||||||
use diesel::QueryDsl;
|
use diesel::QueryDsl;
|
||||||
use diesel::RunQueryDsl;
|
use diesel::RunQueryDsl;
|
||||||
|
use diesel::SelectableHelper;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
fn establish_connection() -> PgConnection {
|
fn establish_connection() -> SqliteConnection {
|
||||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL not setted");
|
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL not setted");
|
||||||
|
|
||||||
PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
|
SqliteConnection::establish(&database_url).unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod posts {
|
pub mod posts {
|
||||||
|
@ -23,24 +24,24 @@ pub mod posts {
|
||||||
pub fn get_posts(page: Option<u64>) -> (Vec<Post>, i64) {
|
pub fn get_posts(page: Option<u64>) -> (Vec<Post>, i64) {
|
||||||
use crate::schema::posts::dsl::*;
|
use crate::schema::posts::dsl::*;
|
||||||
|
|
||||||
let connection = establish_connection();
|
let connection = &mut establish_connection();
|
||||||
let visible_posts = posts.order(created_at.desc());
|
let visible_posts = posts.order(created_at.desc());
|
||||||
let visible_posts = match page {
|
let visible_posts = match page {
|
||||||
Some(number_page) => visible_posts
|
Some(number_page) => visible_posts
|
||||||
.filter(published.eq(true))
|
.filter(published.eq(true))
|
||||||
.limit(MAX_POSTS_PER_PAGE as i64)
|
.limit(MAX_POSTS_PER_PAGE as i64)
|
||||||
.offset((MAX_POSTS_PER_PAGE * (number_page - 1)) as i64)
|
.offset((MAX_POSTS_PER_PAGE * (number_page - 1)) as i64)
|
||||||
.load::<Post>(&connection)
|
.load::<Post>(connection)
|
||||||
.expect("Error loading posts"),
|
.expect("Error loading posts"),
|
||||||
None => visible_posts
|
None => visible_posts
|
||||||
.load::<Post>(&connection)
|
.load::<Post>(connection)
|
||||||
.expect("Error loading posts"),
|
.expect("Error loading posts"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let number_of_posts: i64 = posts
|
let number_of_posts: i64 = posts
|
||||||
.filter(published.eq(true))
|
.filter(published.eq(true))
|
||||||
.count()
|
.count()
|
||||||
.get_result(&connection)
|
.get_result(connection)
|
||||||
.expect("Error counting the posts");
|
.expect("Error counting the posts");
|
||||||
|
|
||||||
(visible_posts, number_of_posts)
|
(visible_posts, number_of_posts)
|
||||||
|
@ -49,24 +50,25 @@ pub mod posts {
|
||||||
pub fn get_post(id_number: i32) -> Result<Post, Error> {
|
pub fn get_post(id_number: i32) -> Result<Post, Error> {
|
||||||
use crate::schema::posts::dsl::*;
|
use crate::schema::posts::dsl::*;
|
||||||
|
|
||||||
let connection = establish_connection();
|
let connection = &mut establish_connection();
|
||||||
let post = posts.find(id_number).first(&connection);
|
|
||||||
|
posts.find(id_number).first(connection)
|
||||||
|
|
||||||
post
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_post(new_post: &NewPost) -> Result<Post, Error> {
|
pub fn add_post(new_post: &NewPost) -> Result<Post, Error> {
|
||||||
use crate::schema::posts;
|
use crate::schema::posts;
|
||||||
|
|
||||||
let connection = establish_connection();
|
let connection = &mut establish_connection();
|
||||||
diesel::insert_into(posts::table)
|
diesel::insert_into(posts::table)
|
||||||
.values(new_post)
|
.values(new_post)
|
||||||
.get_result(&connection)
|
.returning(Post::as_returning())
|
||||||
|
.get_result(connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit_post(updated_id: i32, new_post: &NewPost) -> Result<Post, Error> {
|
pub fn edit_post(updated_id: i32, new_post: &NewPost) -> Result<Post, Error> {
|
||||||
use crate::schema::posts::dsl::*;
|
use crate::schema::posts::dsl::*;
|
||||||
let connection = establish_connection();
|
let connection = &mut establish_connection();
|
||||||
|
|
||||||
let date = Utc::now().naive_utc();
|
let date = Utc::now().naive_utc();
|
||||||
|
|
||||||
|
@ -77,16 +79,17 @@ pub mod posts {
|
||||||
published.eq(&new_post.published),
|
published.eq(&new_post.published),
|
||||||
updated_at.eq(&date),
|
updated_at.eq(&date),
|
||||||
))
|
))
|
||||||
.get_result(&connection)
|
.returning(Post::as_returning())
|
||||||
|
.get_result(connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_visit(post_id: i32) {
|
pub fn add_visit(post_id: i32) {
|
||||||
use crate::schema::posts::dsl::*;
|
use crate::schema::posts::dsl::*;
|
||||||
|
|
||||||
let connection = establish_connection();
|
let connection = &mut establish_connection();
|
||||||
diesel::update(posts.filter(id.eq(post_id)))
|
diesel::update(posts.filter(id.eq(post_id)))
|
||||||
.set(views.eq(views + 1))
|
.set(views.eq(views + 1))
|
||||||
.execute(&connection)
|
.execute(connection)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
mod schema;
|
mod schema;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate diesel;
|
extern crate diesel;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -22,7 +21,7 @@ use std::vec::Vec;
|
||||||
|
|
||||||
static BOTS: OnceCell<Bots> = OnceCell::const_new();
|
static BOTS: OnceCell<Bots> = OnceCell::const_new();
|
||||||
|
|
||||||
async fn is_bot(ua: &String) -> bool {
|
async fn is_bot(ua: &str) -> bool {
|
||||||
let bots = BOTS.get_or_init(|| async { Bots::default() }).await;
|
let bots = BOTS.get_or_init(|| async { Bots::default() }).await;
|
||||||
bots.is_bot(ua)
|
bots.is_bot(ua)
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ pub fn ascii_table(raw_table: String) -> String {
|
||||||
let index_subrow = index / row.len();
|
let index_subrow = index / row.len();
|
||||||
let index_col = index % row.len();
|
let index_col = index % row.len();
|
||||||
let text = if let Some(col) = row.get(index_col) {
|
let text = if let Some(col) = row.get(index_col) {
|
||||||
if let Some(&ref text) = col.get(index_subrow) {
|
if let Some(text) = col.get(index_subrow) {
|
||||||
text
|
text
|
||||||
} else {
|
} else {
|
||||||
&String::from("")
|
&String::from("")
|
||||||
|
|
|
@ -3,7 +3,9 @@ use serde::Serialize;
|
||||||
|
|
||||||
use super::schema::posts;
|
use super::schema::posts;
|
||||||
|
|
||||||
#[derive(Queryable, Serialize)]
|
#[derive(Queryable, Selectable, Serialize)]
|
||||||
|
#[diesel(table_name = posts)]
|
||||||
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||||
pub struct Post {
|
pub struct Post {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -15,7 +17,7 @@ pub struct Post {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromForm, Insertable, Debug)]
|
#[derive(FromForm, Insertable, Debug)]
|
||||||
#[table_name = "posts"]
|
#[diesel(table_name = posts)]
|
||||||
pub struct NewPost {
|
pub struct NewPost {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
posts (id) {
|
posts (id) {
|
||||||
id -> Int4,
|
id -> Integer,
|
||||||
title -> Varchar,
|
title -> Text,
|
||||||
content -> Text,
|
content -> Text,
|
||||||
published -> Bool,
|
published -> Bool,
|
||||||
views -> Int4,
|
views -> Integer,
|
||||||
created_at -> Timestamp,
|
created_at -> Timestamp,
|
||||||
updated_at -> Timestamp,
|
updated_at -> Timestamp,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue