2020-12-18 18:27:11 +01:00
|
|
|
#+OPTIONS: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
|
|
|
|
#+OPTIONS: author:t broken-links:nil c:nil creator:nil
|
|
|
|
#+OPTIONS: d:(not "LOGBOOK") date:t e:t email:nil f:t inline:t num:t
|
|
|
|
#+OPTIONS: p:nil pri:nil prop:nil stat:t tags:t tasks:t tex:t
|
|
|
|
#+OPTIONS: timestamp:t title:t toc:t todo:t |:t
|
2020-12-21 14:09:32 +01:00
|
|
|
#+TITLE: Rust, Rocket and Diesel
|
|
|
|
#+SUBTITLE: Web apps with rust
|
|
|
|
#+DESCRIPTION: An introduction to Rust, Rocket and Diesel.
|
2020-12-18 18:27:11 +01:00
|
|
|
#+KEYWORDS: rust rocket diesel
|
2020-12-21 11:04:02 +01:00
|
|
|
#+AUTHOR: \href{mailto:rocket-presentation@onders.org}{finga}
|
2020-12-18 18:27:11 +01:00
|
|
|
#+EMAIL: rocket-presentation@onders.org
|
|
|
|
#+LANGUAGE: en
|
|
|
|
#+SELECT_TAGS: export
|
|
|
|
#+EXCLUDE_TAGS: noexport
|
|
|
|
#+CREATOR: Emacs 26.1 (Org mode 9.1.9)
|
|
|
|
|
|
|
|
#+OPTIONS: H:2
|
|
|
|
#+LATEX_CLASS: beamer
|
|
|
|
#+LATEX_CLASS_OPTIONS: [aspectration=1610]
|
2020-12-21 11:04:02 +01:00
|
|
|
# #+LATEX_HEADER: \hypersetup{colorlinks=true,linkcolor=gray}
|
|
|
|
#+LATEX_HEADER: \hypersetup{colorlinks=true,linkcolor=black,urlcolor=gray}
|
2020-12-18 18:27:11 +01:00
|
|
|
#+COLUMNS: %45ITEM %10BEAMER_env(Env) %10BEAMER_act(Act) %4BEAMER_col(Col) %8BEAMER_opt(Opt)
|
|
|
|
#+BEAMER_THEME: Frankfurt
|
|
|
|
#+BEAMER_COLOR_THEME: seagull
|
|
|
|
#+BEAMER_FONT_THEME:
|
|
|
|
#+BEAMER_INNER_THEME:
|
|
|
|
#+BEAMER_OUTER_THEME:
|
|
|
|
#+BEAMER_HEADER: \institute[INST]{\href{https://cccsbg.at}{cccsbg}}
|
|
|
|
|
|
|
|
* Rust
|
|
|
|
|
|
|
|
** What is Rust?
|
2020-12-21 11:04:02 +01:00
|
|
|
#+BEGIN_CENTER
|
|
|
|
#+LaTeX:\includegraphics[width = 0.65\textwidth]{img/Bruine_roest_op_tarwe_(Puccinia_recondita_f.sp._tritici_on_Triticum_aestivum).jpg}
|
|
|
|
#+END_CENTER
|
|
|
|
|
2020-12-21 14:09:32 +01:00
|
|
|
*** Rust, the language
|
2021-01-11 22:44:15 +01:00
|
|
|
- About 10 years young (2010)
|
2020-12-21 11:04:02 +01:00
|
|
|
- Memory safe without gcing, optional ref counting
|
|
|
|
- Ownership, lifetimes, traits
|
|
|
|
- Variables are immutable by default and can be shadowed
|
|
|
|
- Performance of idiomatic Rust is comparable to the performance
|
|
|
|
of idiomatic cpp
|
|
|
|
|
2020-12-21 15:11:43 +01:00
|
|
|
** Where to get further information?
|
2020-12-21 11:04:02 +01:00
|
|
|
|
2020-12-21 14:09:32 +01:00
|
|
|
*** Docs...
|
2021-01-11 22:44:15 +01:00
|
|
|
- [[https://doc.rust-lang.org/book/][The rust book]] (~$ rustup docs --book~)
|
|
|
|
- [[https://doc.rust-lang.org/rust-by-example/][Rust by example]] (~$ rustup docs --rust-by-example~)
|
|
|
|
- [[https://doc.rust-lang.org/std/][The Rust Standard Library]] (~$ rustup docs --std~)
|
|
|
|
- Use '~$ rustup help docs~' to get an overview
|
2020-12-21 11:04:02 +01:00
|
|
|
- [[https://cheats.rs][cheats.rs]]
|
2021-01-11 22:44:15 +01:00
|
|
|
- [[https://programming-idioms.org/cheatsheet/Rust][programming-idioms.org]]
|
2020-12-21 11:04:02 +01:00
|
|
|
- [[https://cargo.io][cargo.io]]/[[https://lib.rs][lib.rs]]
|
|
|
|
|
2020-12-21 14:09:32 +01:00
|
|
|
*** Chat (Discord)
|
|
|
|
- [[https://discord.gg/rust-lang][The Rust Programming Language]]
|
|
|
|
- [[https://discord.com/invite/tcbkpyQ][The Rust Programming Language Community Server]]
|
|
|
|
|
2020-12-21 11:04:02 +01:00
|
|
|
** What are we going to use?
|
|
|
|
|
|
|
|
*** Definitely
|
2020-12-21 15:11:43 +01:00
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
- [[https://rocket.rs][rocket]]
|
|
|
|
- [[https://diesel.rs][diesel]]
|
2021-01-11 22:44:15 +01:00
|
|
|
- log/env_logger
|
2020-12-21 11:04:02 +01:00
|
|
|
|
|
|
|
*** Maybe
|
2020-12-21 15:11:43 +01:00
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
- anyhow
|
|
|
|
- lettre
|
|
|
|
- sha3
|
|
|
|
- serde
|
|
|
|
- chrono
|
2020-12-21 11:04:02 +01:00
|
|
|
|
|
|
|
** How to install
|
|
|
|
|
|
|
|
*** Install Rust
|
|
|
|
#+BEGIN_SRC sh
|
|
|
|
$ curl --proto '=https' --tlsv1.2 -sSf \
|
|
|
|
https://sh.rustup.rs | sh
|
|
|
|
#+END_SRC
|
|
|
|
|
2020-12-21 14:09:32 +01:00
|
|
|
*** Install nightly Rust (needed for Rocket)
|
2020-12-21 11:04:02 +01:00
|
|
|
#+BEGIN_SRC sh
|
|
|
|
$ rustup toolchain install nightly
|
|
|
|
#+END_SRC
|
|
|
|
|
2020-12-21 14:09:32 +01:00
|
|
|
*** Install rustfmt (code formatter)
|
2020-12-21 11:04:02 +01:00
|
|
|
#+BEGIN_SRC sh
|
|
|
|
$ rustup component add rustfmt
|
|
|
|
#+END_SRC
|
|
|
|
|
2020-12-21 14:09:32 +01:00
|
|
|
*** Install clippy (linter and static code analysis)
|
2020-12-21 11:04:02 +01:00
|
|
|
#+BEGIN_SRC sh
|
|
|
|
$ rustup component add clippy
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
* Rocket
|
|
|
|
|
|
|
|
** What is Rocket?
|
2020-12-21 14:09:32 +01:00
|
|
|
#+BEGIN_QUOTE
|
|
|
|
Rocket is a web framework for Rust that makes it simple to write
|
|
|
|
fast, secure web applications without sacrificing flexibility,
|
|
|
|
usability, or type safety.
|
|
|
|
#+END_QUOTE
|
|
|
|
|
|
|
|
*** Features
|
|
|
|
|
|
|
|
**** Col left
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:END:
|
|
|
|
- Type Safe
|
|
|
|
- Extensible
|
|
|
|
- Templating
|
|
|
|
- Cookies
|
|
|
|
|
|
|
|
**** Col right
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:END:
|
|
|
|
- Streams
|
|
|
|
- Testing (Unit tests)
|
|
|
|
- Typed URIs
|
|
|
|
|
2020-12-21 15:11:43 +01:00
|
|
|
** Where to get further information?
|
2020-12-21 14:09:32 +01:00
|
|
|
|
|
|
|
*** Docs...
|
2020-12-21 15:11:43 +01:00
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
- [[https://rocket.rs][rocket.rs]]
|
2020-12-21 14:09:32 +01:00
|
|
|
- [[https://rocket.rs/v0.4/guide/][Rocket Guide]]
|
|
|
|
- [[https://api.rocket.rs/v0.4/rocket/][Rocket API docs]]
|
|
|
|
- [[https://github.com/SergioBenitez/Rocket/tree/v0.4/examples][Examples]]
|
|
|
|
|
|
|
|
*** Chat
|
2020-12-21 15:11:43 +01:00
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
2020-12-21 14:09:32 +01:00
|
|
|
- Matrix: [[https://chat.mozilla.org/#/room/%23rocket:mozilla.org][#rocket:mozilla.org]]
|
|
|
|
- IRC on Freenode: [[https://kiwiirc.com/client/chat.freenode.net/#rocket][#rocket]]
|
2020-12-21 11:04:02 +01:00
|
|
|
|
|
|
|
* Diesel
|
|
|
|
|
|
|
|
** What is an ORM?
|
2020-12-21 15:11:43 +01:00
|
|
|
Object-relational-mapping is a programming technique for converting
|
|
|
|
data between incompatible type systems using the paradigms of your
|
|
|
|
programming language.
|
|
|
|
|
|
|
|
*** Pros
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
- Models are DRY (don't repeat yourself)
|
|
|
|
- Cleaner separation
|
|
|
|
- Prepared and sanitised queries
|
|
|
|
- Changes are versioned
|
|
|
|
|
|
|
|
*** Cons
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
- Debugging can get more complicated (performance)
|
|
|
|
- No need to learn SQL
|
|
|
|
|
|
|
|
** Prerequisites ~diesel_cli~
|
|
|
|
|
|
|
|
*** Setup Diesel for default DBMS
|
|
|
|
#+BEGIN_SRC sh
|
|
|
|
$ sudo apt install libpq-dev libsqlite3-dev \
|
|
|
|
default-libmysqlclient-dev
|
|
|
|
$ cargo install diesel_cli
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
*** Setup Diesel for SQLite only
|
|
|
|
#+BEGIN_SRC sh
|
|
|
|
$ sudo apt install libsqlite3-dev
|
|
|
|
$ cargo install diesel_cli -no-default-features \
|
|
|
|
--features sqlite
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
** How does that look in Rust
|
|
|
|
|
|
|
|
*** Define a struct
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.50
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
#+BEGIN_SRC rust
|
|
|
|
#[derive(Queryable)]
|
|
|
|
pub struct NewComment<'a> {
|
|
|
|
name: &'a str,
|
|
|
|
email: &'a str,
|
|
|
|
comment: &'a str,
|
|
|
|
}
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
*** Insert something
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
#+BEGIN_SRC rust
|
|
|
|
let user = NewUser {
|
|
|
|
name: "foo",
|
|
|
|
email: "foo@bar.baz",
|
|
|
|
comment: "A comment",
|
|
|
|
};
|
|
|
|
|
|
|
|
insert_into(comments)
|
|
|
|
.values(&user)
|
|
|
|
.execute(conn);
|
|
|
|
#+END_SRC
|
2020-12-21 11:04:02 +01:00
|
|
|
|
2020-12-21 15:11:43 +01:00
|
|
|
** Where to get further information?
|
|
|
|
|
|
|
|
*** Docs...
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
- [[https://diesel.rs][diesel.rs]]
|
|
|
|
- [[https://diesel.rs/guides/][Diesel Guides]]
|
|
|
|
- [[https://docs.diesel.rs/master/diesel/index.html][Diesel API docs]]
|
|
|
|
- [[https://github.com/diesel-rs/diesel/tree/master/examples][Examples]] (minimalistic)
|
|
|
|
|
|
|
|
*** Support
|
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
|
|
|
- [[https://gitter.im/diesel-rs/diesel][Gitter]]
|
|
|
|
- [[https://discourse.diesel.rs/][Discourse Forum]]
|
2020-12-21 11:04:02 +01:00
|
|
|
|
|
|
|
* Lets code something
|
|
|
|
|
2020-12-21 15:11:43 +01:00
|
|
|
** Lets create a small web app
|
2021-01-11 22:44:15 +01:00
|
|
|
A mini text board where everybody can post and reply.
|
|
|
|
|
|
|
|
*** Caution
|
|
|
|
HTML is not disabled!
|
|
|
|
|
|
|
|
** Let us start
|
|
|
|
#+BEGIN_CENTER
|
|
|
|
#+LaTeX:\includegraphics[width = 0.7\textwidth]{img/challenge-accepted-lets-code-it.jpg}
|
|
|
|
#+END_CENTER
|
2020-12-21 15:11:43 +01:00
|
|
|
|
2021-01-11 22:48:48 +01:00
|
|
|
*** Steps to reproduce :noexport:
|
|
|
|
|
|
|
|
**** Create new crate
|
2021-01-12 17:55:25 +01:00
|
|
|
#+BEGIN_SRC sh
|
|
|
|
cargo init simple_text_board
|
|
|
|
cd simple_text_board
|
|
|
|
rustup override set nightly
|
|
|
|
cargo r
|
|
|
|
#+END_SRC
|
2021-01-11 22:48:48 +01:00
|
|
|
|
2021-01-11 23:10:26 +01:00
|
|
|
**** Setup Rocket
|
2021-01-12 17:55:25 +01:00
|
|
|
***** Add Rocket to ~Cargo.toml~
|
|
|
|
#+BEGIN_SRC toml
|
|
|
|
[dependencies]
|
|
|
|
rocket = "0.4"
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Add ~Rocket.toml~
|
|
|
|
#+BEGIN_SRC toml
|
|
|
|
[development]
|
|
|
|
address = "0.0.0.0"
|
|
|
|
port = 8000
|
|
|
|
workers = 2
|
|
|
|
keep_alive = 5
|
|
|
|
log = "normal"
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Modify ~src/main.rs~ for Rockets "~Hello, world!~" program
|
|
|
|
#+BEGIN_SRC rust
|
|
|
|
#![feature(proc_macro_hygiene, decl_macro)]
|
|
|
|
|
|
|
|
#[macro_use] extern crate rocket;
|
|
|
|
|
|
|
|
#[get("/")]
|
|
|
|
fn index() -> &'static str {
|
|
|
|
"Hello, world!"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
rocket::ignite().mount("/", routes![index]).launch();
|
|
|
|
}
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
**** Create first templates
|
|
|
|
***** Create the base template at ~templates/base.html.tera~
|
|
|
|
#+BEGIN_SRC html
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta charset="utf-8" />
|
|
|
|
<meta name="viewport" content="width=device-width" />
|
|
|
|
<title>simple text board</title>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<ul>
|
|
|
|
<li><a href="/">home</a></li>
|
|
|
|
<li><a href="/create">create post</a></li>
|
|
|
|
</ul>
|
|
|
|
{% block content %} {% endblock %}
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Create the create template at ~templates/create.html.tera~
|
|
|
|
#+BEGIN_SRC html
|
|
|
|
{% extends "base" %}
|
|
|
|
|
|
|
|
{% block content %}
|
|
|
|
<h1>simple text board</h1>
|
|
|
|
<h2>create a post</h2>
|
|
|
|
<form action="/create" method="post" accept-charset="utf-8">
|
|
|
|
<label for="author">author name</label>
|
|
|
|
<input type="text" placeholder="author" name="author" required>
|
|
|
|
|
|
|
|
<label for="email">email</label>
|
|
|
|
<input type="text" placeholder="email" name="email">
|
|
|
|
|
|
|
|
<label for="title">title</label>
|
|
|
|
<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>
|
|
|
|
|
|
|
|
<button type="submit">create</button>
|
|
|
|
{% if flash %}<p>{{ flash }}</p>{% endif %}
|
|
|
|
</form>
|
|
|
|
{% endblock content %}
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Create the ~create_form~ function and add it to routing
|
|
|
|
#+BEGIN_SRC rust
|
|
|
|
#![feature(proc_macro_hygiene, decl_macro)]
|
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
use rocket::{get, request::FlashMessage, routes};
|
|
|
|
use rocket_contrib::templates::Template;
|
|
|
|
|
|
|
|
#[get("/create")]
|
|
|
|
fn create_form(flash: Option<FlashMessage>) -> Template {
|
|
|
|
let mut context = HashMap::new();
|
|
|
|
|
|
|
|
if let Some(ref msg) = flash {
|
|
|
|
context.insert("flash", msg.msg());
|
|
|
|
}
|
|
|
|
|
|
|
|
Template::render("create", &context)
|
|
|
|
}
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
rocket::ignite()
|
|
|
|
.mount("/", routes![index, create_form])
|
|
|
|
.attach(Template::fairing())
|
|
|
|
.launch();
|
|
|
|
}
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
**** Setup Database and posts
|
|
|
|
***** Create the ~.env~ file
|
|
|
|
#+BEGIN_SRC sh
|
|
|
|
DATABASE_URL=simple_text_board.sqlite
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Add diesel to the dependencies and to ~rocket_contrib~ in ~Cargo.toml~
|
|
|
|
#+BEGIN_SRC toml
|
|
|
|
...
|
|
|
|
chrono = "0.4"
|
|
|
|
diesel = { version = "1.4", features = ["sqlite", "chrono"] }
|
|
|
|
log = "0.4"
|
|
|
|
...
|
|
|
|
[dependencies.rocket_contrib]
|
|
|
|
...
|
|
|
|
features = ["diesel_sqlite_pool", "tera_templates"]
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Configure database for Rocket in ~Rocket.toml~
|
|
|
|
#+BEGIN_SRC toml
|
|
|
|
[global.databases]
|
|
|
|
sqlite = { url = "simple_text_board.sqlite" }
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Create the first table schema
|
|
|
|
#+BEGIN_SRC sh
|
|
|
|
diesel setup
|
|
|
|
diesel migration generate create_posts
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** How to create the table
|
|
|
|
#+BEGIN_SRC sql
|
|
|
|
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)
|
|
|
|
);
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** How to destroy it
|
|
|
|
#+BEGIN_SRC sql
|
|
|
|
DROP TABLE posts;
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Applay and test rollback
|
|
|
|
#+BEGIN_SRC sh
|
|
|
|
diesel migration run
|
|
|
|
diesel migration redo
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Create data model in ~src/models.rs~
|
|
|
|
#+BEGIN_SRC rust
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#+END_SRC
|
|
|
|
|
|
|
|
***** Add create post functionality to ~src/main.rs~
|
|
|
|
#+BEGIN_SRC rust
|
|
|
|
#![feature(proc_macro_hygiene, decl_macro)]
|
|
|
|
|
|
|
|
#[macro_use]
|
|
|
|
extern crate diesel;
|
|
|
|
|
|
|
|
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)]
|
|
|
|
pub struct PostForm {
|
|
|
|
author: String,
|
|
|
|
email: String,
|
|
|
|
title: String,
|
|
|
|
content: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
#[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(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
rocket::ignite()
|
|
|
|
.mount("/", routes![index, create_form, create_post])
|
|
|
|
.attach(DbCon::fairing())
|
|
|
|
.attach(Template::fairing())
|
|
|
|
.launch();
|
|
|
|
}
|
|
|
|
#+END_SRC
|
2021-01-11 23:10:26 +01:00
|
|
|
|
2020-12-21 11:04:02 +01:00
|
|
|
* Conclusion
|
|
|
|
|
|
|
|
** What did we do?
|
2021-01-11 22:44:15 +01:00
|
|
|
- Setup Rust and Diesel
|
|
|
|
- Create a project with Rocket and Diesel prerequisites
|
|
|
|
- Handle a SQLite DB with Diesel
|
|
|
|
- Create Tera templates
|
2020-12-21 11:04:02 +01:00
|
|
|
|
|
|
|
** What did you hopefully learn!
|
|
|
|
|
2020-12-21 14:09:32 +01:00
|
|
|
** Two small projects
|
|
|
|
|
|
|
|
*** [[https://git.onders.org/finga/ldap0r][ldap0r]]
|
2020-12-21 15:11:43 +01:00
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
2020-12-21 14:09:32 +01:00
|
|
|
- LDAP password reset tool
|
|
|
|
- ($\sim$ 300 SloC)
|
|
|
|
- First release
|
|
|
|
- Tests
|
|
|
|
|
|
|
|
*** [[https://git.onders.org/finga/filerly][filerly]]
|
2020-12-21 15:11:43 +01:00
|
|
|
:PROPERTIES:
|
|
|
|
:BEAMER_col: 0.45
|
|
|
|
:BEAMER_env: block
|
|
|
|
:END:
|
2020-12-21 14:09:32 +01:00
|
|
|
- File sharing a la NextCloud
|
2021-01-11 22:44:15 +01:00
|
|
|
- Not yet ready, work in progress...
|
2020-12-21 11:04:02 +01:00
|
|
|
|
|
|
|
** The End
|
|
|
|
#+BEGIN_CENTER
|
|
|
|
#+LaTeX:\includegraphics[width = 0.3\textwidth]{img/goodbye.jpg}
|
|
|
|
|
|
|
|
\Huge
|
|
|
|
Thanks for your attention!!1!
|
|
|
|
|
|
|
|
This is the end..
|
|
|
|
#+END_CENTER
|