Add creation of posts with logging

This commit is contained in:
finga 2021-01-12 17:55:25 +01:00
parent 56544cd0d4
commit 4948195495
13 changed files with 379 additions and 97 deletions

1
simple_text_board/.env Normal file
View file

@ -0,0 +1 @@
DATABASE_URL=simple_text_board.sqlite

View file

@ -270,6 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2de9deab977a153492a1468d1b1c0662c1cf39e5ea87d0c060ecd59ef18d8c"
dependencies = [
"byteorder",
"chrono",
"diesel_derives",
"libsqlite3-sys",
"r2d2",
@ -1163,6 +1164,9 @@ dependencies = [
name = "simple_text_board"
version = "0.1.0"
dependencies = [
"chrono",
"diesel",
"log 0.4.13",
"rocket",
"rocket_contrib",
]

View file

@ -6,8 +6,11 @@ edition = "2018"
[dependencies]
rocket = "0.4"
chrono = "0.4"
diesel = { version = "1.4", features = ["sqlite", "chrono"] }
log = "0.4"
[dependencies.rocket_contrib]
version = "0.4"
default-features = false
features = ["tera_templates"]
features = ["diesel_sqlite_pool", "tera_templates"]

View file

@ -1,3 +1,6 @@
[global.databases]
sqlite = { url = "simple_text_board.sqlite" }
[development]
address = "0.0.0.0"
port = 8000

View file

@ -0,0 +1,5 @@
# For documentation on how to configure this file,
# see diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/schema.rs"

View file

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

View file

@ -0,0 +1,10 @@
CREATE TABLE posts (
id INTEGER NOT NULL PRIMARY KEY,
parent INTEGER,
timestamp DATETIME NOT NULL,
author VARCHAR NOT NULL,
email VARCHAR NOT NULL,
title VARCHAR NOT NULL,
content VARCHAR NOT NULL,
FOREIGN KEY (parent) REFERENCES posts(id)
);

View file

@ -1,9 +1,36 @@
#![feature(proc_macro_hygiene, decl_macro)]
use std::collections::HashMap;
#[macro_use]
extern crate diesel;
use rocket::{get, request::FlashMessage, routes};
use rocket_contrib::templates::Template;
use std::{collections::HashMap, net::SocketAddr};
use chrono::Local;
use diesel::SqliteConnection;
use log::{error, info};
use rocket::{
get, post,
request::{FlashMessage, Form},
response::{Flash, Redirect},
routes, uri, FromForm,
};
use rocket_contrib::{database, templates::Template};
mod models;
mod schema;
use models::NewPost;
#[database("sqlite")]
struct DbCon(SqliteConnection);
#[derive(FromForm)]
struct PostForm {
author: String,
email: String,
title: String,
content: String,
}
#[get("/create")]
fn create_form(flash: Option<FlashMessage>) -> Template {
@ -16,6 +43,36 @@ fn create_form(flash: Option<FlashMessage>) -> Template {
Template::render("create", &context)
}
#[post("/create", data = "<post>")]
fn create_post(
conn: DbCon,
remote_address: SocketAddr,
post: Form<PostForm>,
) -> Result<Redirect, Flash<Redirect>> {
let post = NewPost {
parent: None,
timestamp: Local::now().naive_local(),
author: &post.author.trim(),
email: &post.email.trim(),
title: &post.title.trim(),
content: &post.content.trim(),
};
match post.insert(&conn) {
Ok(_) => {
info!("New post from {}", remote_address);
Ok(Redirect::to(uri!(index)))
}
Err(e) => {
error!("Could not create post from {}: {:?}", remote_address, e);
Err(Flash::error(
Redirect::to(uri!(create_form)),
"Could not create post.".to_string(),
))
}
}
}
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
@ -23,7 +80,8 @@ fn index() -> &'static str {
fn main() {
rocket::ignite()
.mount("/", routes![index, create_form])
.mount("/", routes![index, create_form, create_post])
.attach(DbCon::fairing())
.attach(Template::fairing())
.launch();
}

View file

@ -0,0 +1,20 @@
use crate::schema::posts::{self, dsl::posts as table_posts};
use chrono::NaiveDateTime;
use diesel::{QueryResult, RunQueryDsl};
#[derive(Insertable)]
#[table_name = "posts"]
pub struct NewPost<'a> {
pub parent: Option<&'a i32>,
pub timestamp: NaiveDateTime,
pub author: &'a str,
pub email: &'a str,
pub title: &'a str,
pub content: &'a str,
}
impl NewPost<'_> {
pub fn insert(&self, conn: &diesel::SqliteConnection) -> QueryResult<usize> {
diesel::insert_into(table_posts).values(self).execute(conn)
}
}

View file

@ -0,0 +1,11 @@
table! {
posts (id) {
id -> Integer,
parent -> Nullable<Integer>,
timestamp -> Timestamp,
author -> Text,
email -> Text,
title -> Text,
content -> Text,
}
}

View file

@ -3,9 +3,6 @@
{% block content %}
<h1>simple text board</h1>
<h2>create a post</h2>
{% if flash %}
<p>{{ flash }}</p>
{% endif %}
<form action="/create" method="post" accept-charset="utf-8">
<label for="author">author name</label>
<input type="text" placeholder="author" name="author" required>
@ -17,9 +14,9 @@
<input type="text" placeholder="title" name="title" required>
<label for="content">content</label>
<textarea type="text" placeholder="content" name="content" rows="8" cols="50" required>
</textarea>
<textarea type="text" placeholder="content" name="content" rows="8" cols="50" required></textarea>
<button type="submit">create</button>
{% if flash %}<p>{{ flash }}</p>{% endif %}
</form>
{% endblock content %}