Compare commits

..

No commits in common. "40b9a90bf9780bc1267b9930339c33871241d9fe" and "243bc6397be63ed17e0fccd97b2c78e9af4308cb" have entirely different histories.

13 changed files with 166 additions and 307 deletions

View file

@ -5,7 +5,7 @@ ENV RUSTFLAGS='-C target-feature=-crt-static'
WORKDIR /app
COPY ./site .
RUN apk add --no-cache musl-dev sqlite-dev
RUN cargo install --path . -j $(nproc)
RUN cargo install --path .
FROM alpine:latest

View file

@ -2,31 +2,31 @@
Pure rust. Built with actix, diesel, tera, serde and sqlite3.
## Run instructions using docker
## Build instructions using docker
1. Clone the repository
```bash
git clone https://github.com/mtrx1337/crablog
git clone https://github.com/leonardlorenz/crablog
cd crablog/site
```
2. Install diesel and create a database
```bash
cargo install diesel_cli --no-default-features --features "sqlite"
cargo install diesel_cli
diesel setup --database-url ../content/db.sqlite3
diesel migration run --database-url ../content/db.sqlite3
```
3. Set up your configuration file (see below)
4. Pull the image (or build from source) and run the docker container
4. Build and run the docker container (Will compile from source and thus take a while)
```bash
docker-compose up -d
```
## Configuration environment file
All configuration options are defined in crablog.env, an example configuration is provided.
When not using Docker you may have to add crablog.env to your startup script or define the variables there.
All configuration options are defined in .env, to be created in the same directory as this readme.
An example configuration:
`crablog.env`
```
USERNAME=yourusername
EMAIL=me@mydomain.tld
@ -44,17 +44,13 @@ ROOT_PATH=/path/to/template/directory/and/sqliteDB
## Routes
| Route | Description |
| ------------ | -------------------------------------------------- |
| `/` | shows the last 5 posts |
| `/id/<id>` | shows a single post by id |
| `/all` | shows all posts |
| `/submit` | set your submit token and create posts |
| `/edit/<id>` | edit, delete or hide posts |
| `/about` | information about this blog, social media accounts |
- / site welcome
- /blog shows the last 5 posts
- /blog/id/<id> shows a single post by id
- /blog/all shows all posts
- /blog/submit set your submit token and create posts
- /blog/edit/<id> edit, delete or hide posts
**API Routes**
| Route | Description |
| ---------------- | ------------------------- |
| `api/blog/posts` | returns all posts as json |
- /api/blog/posts returns all posts as json

View file

@ -13,16 +13,13 @@
</head>
<body>
<h1><a href="/" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<p style="text-align: right">
<a href="/about">About</a>
<a href="/">Last 5 posts</a>
</p>
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<p style="text-align: right"><a href="/">Home</a> <a href="/blog">Last 5 posts</a></p>
<ul>
{% for post in posts %}
<article>
<div>
<a href="/id/{{ post.id }}" class="post-link">[link]</a>
<a href="/blog/id/{{ post.id }}" class="post-link">[link]</a>
</div>
<div class="post-content">
<h2 class="post-title">{{ post.title }}</h2>

View file

@ -13,16 +13,12 @@
</head>
<body>
<h1><a href="/" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<p style="text-align: right">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/all">All Posts</a>
</p>
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<p style="text-align: right"><a href="/">Home</a> <a href="/blog">Last 5 Posts</a> <a href="/blog/all">All Posts</a></p>
<ul>
<article>
<div>
<a href="/id/{{ post.id }}" class="post-link">[link]</a>
<a href="/blog/id/{{ post.id }}" class="post-link">[link]</a>
</div>
<div class="post-content">
<h2 class="post-title">{{ post.title }}</h2>

View file

@ -13,15 +13,13 @@
</head>
<body>
<h1><a href="/" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<p style="text-align: right">
<a href="/about">About</a>
<a href="/all">All Posts</a></p>
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<p style="text-align: right"><a href="/">Home</a> <a href="/blog/all">All Posts</a></p>
<ul>
{% for post in posts %}
<article>
<div>
<a href="/id/{{ post.id }}" class="post-link">[link]</a>
<a href="/blog/id/{{ post.id }}" class="post-link">[link]</a>
</div>
<div class="post-content">
<h2 class="post-title">{{ post.title }}</h2>

View file

@ -11,11 +11,11 @@
<link rel="shortcut icon" type="image/jpg" href="/static/favicon.ico"/>
</head>
<body>
<h1><a href="/" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<h1><a href="/blog" class="post-link" style="text-decoration:none;color:black;">{{ username }}' blog</a></h1>
<h2>Edit posts</h2>
<ul style="list-style: none;">
{% for post in posts %}
<li><a href="/edit/{{ post.id }}">{{ post.title }}</a></li>
<li><a href="/blog/edit/{{ post.id }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
</body>

View file

@ -13,11 +13,9 @@
<body>
<h1>Hi, I'm {{ username }}</h1>
<p style="text-align: right">
<a href="/">Back to the blog</a>
</p>
<p>
This is my blog. If you have questions or input for me please send me an E-Mail to {{ email }}
I have a <a href="/blog">blog.</a><br>
If you have questions or input for me please send me an E-Mail to {{ email }}
</p>
<br>
<p>

View file

@ -1,9 +1,6 @@
USERNAME=yourusername
EMAIL=me@mydomain.tld
SUBMIT_TOKEN=mysupersecretpw
BIND_PORT=8000
SUBMIT_TOKEN=Submit!123 # token needed for submitting
GITHUB_ACCOUNT=usernam3
TWITTER_ACCOUNT=usernam3
MASTODON_ACCOUNT=usernam3@mastodon.social
REDDIT_ACCOUNT=usernam3
DISCORD_ACCOUNT=usernam3
USERNAME=
EMAIL=
TWITTER_ACCOUNT=
GITHUB_ACCOUNT=

View file

@ -1,8 +1,7 @@
version: "3.0"
version: "3.8"
services:
crablog:
build: .
image: mtrx1337/crablog
ports:
- 8000:8000
hostname: crablog

179
site/Cargo.lock generated
View file

@ -57,9 +57,9 @@ dependencies = [
[[package]]
name = "actix-http"
version = "2.2.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "452299e87817ae5673910e53c243484ca38be3828db819b6011736fc6982e874"
checksum = "404df68c297f73b8d36c9c9056404913d25905a8f80127b0e5fe147c9c4b9f02"
dependencies = [
"actix-codec",
"actix-connect",
@ -92,7 +92,7 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project 1.0.1",
"rand 0.7.3",
"rand",
"regex",
"serde",
"serde_json",
@ -109,7 +109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2"
dependencies = [
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -233,9 +233,9 @@ dependencies = [
[[package]]
name = "actix-web"
version = "3.3.2"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e641d4a172e7faa0862241a20ff4f1f5ab0ab7c279f00c2d4587b77483477b86"
checksum = "88344b7a5ef27e5e09e73565379f69273dd3e2d29e82afc381b84d170d0a5631"
dependencies = [
"actix-codec",
"actix-http",
@ -278,7 +278,7 @@ checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -313,7 +313,7 @@ checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -335,9 +335,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "awc"
version = "2.0.3"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b381e490e7b0cfc37ebc54079b0413d8093ef43d14a4e4747083f7fa47a9e691"
checksum = "425980a1e58e5030a3e4b065a3d577c8f0e16142ea9d81f30614eae810c98577"
dependencies = [
"actix-codec",
"actix-http",
@ -351,7 +351,7 @@ dependencies = [
"log",
"mime",
"percent-encoding",
"rand 0.7.3",
"rand",
"serde",
"serde_json",
"serde_urlencoded",
@ -572,12 +572,12 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
[[package]]
name = "crablog"
version = "0.3.1"
version = "0.2.3"
dependencies = [
"actix-files",
"actix-web",
"chrono",
"diesel 1.4.6",
"diesel 1.4.5",
"diesel_codegen",
"env_logger",
"once_cell",
@ -616,7 +616,7 @@ checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -636,9 +636,9 @@ dependencies = [
[[package]]
name = "diesel"
version = "1.4.6"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542"
checksum = "3e2de9deab977a153492a1468d1b1c0662c1cf39e5ea87d0c060ecd59ef18d8c"
dependencies = [
"byteorder",
"chrono",
@ -667,7 +667,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -694,6 +694,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "dtoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
[[package]]
name = "either"
version = "1.6.1"
@ -718,14 +724,14 @@ dependencies = [
"heck",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
name = "env_logger"
version = "0.8.3"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e"
dependencies = [
"atty",
"humantime",
@ -829,7 +835,7 @@ dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -906,17 +912,6 @@ dependencies = [
"wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
]
[[package]]
name = "gimli"
version = "0.23.0"
@ -938,9 +933,9 @@ dependencies = [
[[package]]
name = "globwalk"
version = "0.8.1"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
checksum = "178270263374052c40502e9f607134947de75302c1348d1a0e31db67c1691446"
dependencies = [
"bitflags",
"ignore",
@ -1327,9 +1322,9 @@ checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
[[package]]
name = "once_cell"
version = "1.7.2"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "opaque-debug"
@ -1413,7 +1408,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -1453,7 +1448,7 @@ checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -1464,7 +1459,7 @@ checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -1505,9 +1500,9 @@ checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
[[package]]
name = "proc-macro2"
version = "1.0.26"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid 0.2.1",
]
@ -1539,23 +1534,11 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom 0.1.15",
"getrandom",
"libc",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc 0.2.0",
]
[[package]]
name = "rand"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
"libc",
"rand_chacha 0.3.0",
"rand_core 0.6.2",
"rand_hc 0.3.0",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
@ -1565,17 +1548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core 0.5.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [
"ppv-lite86",
"rand_core 0.6.2",
"rand_core",
]
[[package]]
@ -1584,16 +1557,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom 0.1.15",
]
[[package]]
name = "rand_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
dependencies = [
"getrandom 0.2.2",
"getrandom",
]
[[package]]
@ -1602,16 +1566,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_hc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [
"rand_core 0.6.2",
"rand_core",
]
[[package]]
@ -1701,22 +1656,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.125"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.125"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -1732,14 +1687,14 @@ dependencies = [
[[package]]
name = "serde_urlencoded"
version = "0.7.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
dependencies = [
"form_urlencoded",
"dtoa",
"itoa",
"ryu",
"serde",
"url",
]
[[package]]
@ -1848,7 +1803,7 @@ dependencies = [
"quote 1.0.7",
"serde",
"serde_derive",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -1864,7 +1819,7 @@ dependencies = [
"serde_derive",
"serde_json",
"sha1",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -1886,9 +1841,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.71"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
dependencies = [
"proc-macro2",
"quote 1.0.7",
@ -1906,9 +1861,9 @@ dependencies = [
[[package]]
name = "tera"
version = "1.8.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b64b021b8d3ab1f59ceae9e6cd1c26c8e7ce0322a9ebfff6c0e22b3b66938935"
checksum = "1381c83828bedd5ce4e59473110afa5381ffe523406d9ade4b77c9f7be70ff9a"
dependencies = [
"chrono",
"chrono-tz",
@ -1918,7 +1873,7 @@ dependencies = [
"percent-encoding",
"pest",
"pest_derive",
"rand 0.8.3",
"rand",
"regex",
"serde",
"serde_json",
@ -1952,7 +1907,7 @@ checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -2019,7 +1974,7 @@ dependencies = [
"proc-macro2",
"quote 1.0.7",
"standback",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -2115,7 +2070,7 @@ dependencies = [
"idna",
"lazy_static",
"log",
"rand 0.7.3",
"rand",
"smallvec",
"thiserror",
"tokio",
@ -2263,9 +2218,9 @@ dependencies = [
[[package]]
name = "uuid"
version = "0.8.2"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
dependencies = [
"serde",
"sha1",
@ -2290,7 +2245,7 @@ dependencies = [
"nom",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
]
[[package]]
@ -2365,7 +2320,7 @@ dependencies = [
"log",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
"wasm-bindgen-shared",
]
@ -2387,7 +2342,7 @@ checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.71",
"syn 1.0.48",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]

View file

@ -1,6 +1,6 @@
[package]
name = "crablog"
version = "0.3.1"
version = "0.2.3"
authors = ["Leonard Lorenz <dev@leonardlorenz.de>"]
edition = "2018"
@ -8,20 +8,20 @@ edition = "2018"
[dependencies]
chrono = { version = "*", features = ["serde"] }
actix-web = "3.3.2"
actix-web = "3.2.0"
actix-files = "0.4.0"
serde = { version = "1.0.125", features = ["derive"] }
serde_json = "*"
serde_derive = "*"
serde = { version = "1.0.117", features = ["derive"] }
serde_json = "1.0.59"
serde_derive = "1.0.117"
diesel = { version = "1.4.6", default-features = false, features = ["sqlite", "chrono"] }
diesel = { version = "1.4.5", default-features = false, features = ["sqlite", "chrono"] }
diesel_codegen = { version = "0.16.1", default-features = false }
uuid = { version = "0.8.2", features = ["serde", "v5"] }
uuid = { version = "0.8.1", features = ["serde", "v5"] }
tera = "1.8.0"
tera = "1.5.0"
once_cell = "1.7.2"
once_cell = "1.5.2"
env_logger = "0.8.3"
env_logger = "0.8.2"

View file

@ -9,89 +9,50 @@ extern crate serde_derive;
extern crate tera;
use actix_files as fs;
use actix_web::{middleware::Logger, App, HttpServer};
use actix_web::{App, HttpServer, middleware::Logger};
use env_logger::Env;
use once_cell::sync::Lazy;
use std::{collections::HashMap, env, sync::RwLock};
use tera::Tera;
use std::{env, sync::RwLock, collections::HashMap};
use once_cell::sync::Lazy;
pub static CONFIG_MAP: Lazy<RwLock<HashMap<String, String>>> = Lazy::new(|| {
let mut config: HashMap<String, String> = HashMap::new();
let required_env_vars = [
"SUBMIT_TOKEN",
"ROOT_PATH",
"USERNAME",
"EMAIL",
"BIND_PORT",
];
let optional_env_vars = [
"GITHUB_ACCOUNT",
"TWITTER_ACCOUNT",
"MASTODON_ACCOUNT",
"DISCORD_ACCOUNT",
"REDDIT_ACCOUNT",
];
// Test if variable is set. If not, panic.
let mut insert_required_env = |env: &str| {
let env_string = String::from(env);
config.insert(
env_string.clone(), // env var name
env::var(env_string).expect(format!("`{}` variable not set.", env).as_str()), // env var content
)
};
for var in required_env_vars.iter() {
insert_required_env(var);
config.insert(String::from("SUBMIT_TOKEN"), env::var("SUBMIT_TOKEN").expect("SUBMIT_TOKEN variable not set."));
config.insert(String::from("ROOT_PATH"), env::var("ROOT_PATH").expect("ROOT_PATH variable not set."));
config.insert(String::from("USERNAME"), env::var("USERNAME").expect("USERNAME variable not set."));
config.insert(String::from("EMAIL"), env::var("EMAIL").expect("EMAIL variable not set."));
config.insert(String::from("BIND_PORT"), env::var("BIND_PORT").expect("BIND_PORT variable not set."));
if let Ok(acc) = env::var("GITHUB_ACCOUNT") {
config.insert(String::from("GITHUB_ACCOUNT"), acc.clone());
}
// Test if variable is set. If it is insert into config.
let mut insert_optional_env = |env: &str| {
if let Ok(var_content) = env::var(String::from(env)) {
config.insert(String::from(env), var_content.clone());
if let Ok(acc) = env::var("TWITTER_ACCOUNT") {
config.insert(String::from("TWITTER_ACCOUNT"), acc.clone());
}
};
for var in optional_env_vars.iter() {
insert_optional_env(var);
if let Ok(acc) = env::var("MASTODON_ACCOUNT") {
config.insert(String::from("MASTODON_ACCOUNT"), acc.clone());
}
if let Ok(acc) = env::var("DISCORD_ACCOUNT") {
config.insert(String::from("DISCORD_ACCOUNT"), acc.clone());
}
if let Ok(acc) = env::var("REDDIT_ACCOUNT") {
config.insert(String::from("REDDIT_ACCOUNT"), acc.clone());
}
// Print some info about the current configuration
println!("Submit token = `{}`", config.get("SUBMIT_TOKEN").unwrap());
println!(
"Current working directory = `{}`",
env::current_dir().unwrap().to_str().unwrap()
);
println!("Root path = `{}`", config.get("ROOT_PATH").unwrap());
println!(
"Template path = `{}/templates/*`",
config.get("ROOT_PATH").unwrap()
);
println!("Launching on 0.0.0.0:{}", config.get("BIND_PORT").unwrap());
RwLock::new(config)
});
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
let mut tera = Tera::new(
format!(
"{}{}",
CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(),
"/templates/*"
)
.as_str(),
)
.unwrap();
let mut tera = Tera::new(format!("{}{}", CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(), "/templates/*").as_str()).unwrap();
tera.autoescape_on(vec![".sql"]);
env_logger::Builder::from_env(Env::default().default_filter_or("info"));
App::new()
.data(tera)
.service(routes::about)
.service(routes::root)
.service(routes::blog)
.service(routes::blog_all)
.service(routes::blog_by_id)
@ -103,20 +64,10 @@ async fn main() -> std::io::Result<()> {
.service(api::blog_edit_post)
.service(api::blog_hide_post)
.service(api::blog_delete_post)
.service(fs::Files::new(
"/static",
format!(
"{}{}",
CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(),
"/static"
),
))
.service(fs::Files::new("/static", format!("{}{}", CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(), "/static")))
.wrap(Logger::new("%a %r %t"))
})
.bind(format!(
"0.0.0.0:{}",
CONFIG_MAP.read().unwrap().get("BIND_PORT").unwrap()
))?
.bind(format!("0.0.0.0:{}", CONFIG_MAP.read().unwrap().get("BIND_PORT").unwrap()))?
.run()
.await
}

View file

@ -1,8 +1,8 @@
use crate::db;
use super::CONFIG_MAP;
use actix_web::{error, get, http::StatusCode, web, Error, HttpResponse};
use actix_web::{get, http::StatusCode, web, HttpResponse, Error, error};
use tera::Context;
use super::CONFIG_MAP;
/// tests if the post id is a valid i32 integer bigger than zero
/// assert(!(id_valid("2147483648").0))
@ -33,13 +33,10 @@ pub fn replace_br_tags(x: &str) -> String {
x.replace("<br>", "\n")
}
#[get("/about")]
async fn about(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
#[get("/")]
async fn root(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let mut context = Context::new();
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
context.insert("email", CONFIG_MAP.read().unwrap().get("EMAIL").unwrap());
if let Some(acc) = CONFIG_MAP.read().unwrap().get("GITHUB_ACCOUNT") {
context.insert("github_account", acc);
@ -57,113 +54,89 @@ async fn about(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
context.insert("reddit_account", acc);
}
let result = tmpl
.render("about.html", &context)
let result = tmpl.render("index.html", &context)
.map_err(|e| error::ErrorInternalServerError(format!("Template error\n{}", e)))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/")]
#[get("/blog")]
async fn blog(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let posts = db::get_last_five_posts();
let mut context = Context::new();
context.insert("posts", &posts);
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
let result = tmpl
.render("blog.html", &context)
let result = tmpl.render("blog.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/all")]
#[get("/blog/all")]
async fn blog_all(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let posts = db::get_all_posts();
let mut context = Context::new();
context.insert("posts", &posts);
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
let result = tmpl
.render("blog-all-posts.html", &context)
let result = tmpl.render("blog-all-posts.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/id/{post_id}")]
async fn blog_by_id(
tmpl: web::Data<tera::Tera>,
web::Path(post_id): web::Path<std::string::String>,
) -> Result<HttpResponse, Error> {
#[get("/blog/id/{post_id}")]
async fn blog_by_id(tmpl: web::Data<tera::Tera>, web::Path(post_id): web::Path<std::string::String>) -> Result<HttpResponse, Error> {
let (valid, id) = id_valid(post_id);
if valid {
let post = db::get_post_by_id(id as i32);
if !post.published {
return Ok(HttpResponse::new(StatusCode::UNAUTHORIZED));
return Ok(HttpResponse::new(StatusCode::UNAUTHORIZED))
}
let mut context = Context::new();
context.insert("post", &post);
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
let result = tmpl
.render("blog-by-id.html", &context)
let result = tmpl.render("blog-by-id.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
return Ok(HttpResponse::Ok().content_type("text/html").body(result));
return Ok(HttpResponse::Ok().content_type("text/html").body(result))
} else {
return Ok(HttpResponse::new(StatusCode::NOT_FOUND));
return Ok(HttpResponse::new(StatusCode::NOT_FOUND))
}
}
#[get("/submit")]
#[get("/blog/submit")]
async fn blog_submit(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let mut context = Context::new();
context.insert("title", "");
context.insert("body", "");
let result = tmpl
.render("submit.html", &context)
let result = tmpl.render("submit.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
return Ok(HttpResponse::Ok().content_type("text/html").body(result));
return Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/edit")]
#[get("/blog/edit")]
async fn blog_edit(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let mut context = Context::new();
context.insert("posts", &db::get_all_posts());
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
let result = tmpl
.render("edit.html", &context)
let result = tmpl.render("edit.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/edit/{post_id}")]
async fn blog_edit_by_id(
tmpl: web::Data<tera::Tera>,
web::Path(post_id): web::Path<std::string::String>,
) -> Result<HttpResponse, Error> {
#[get("/blog/edit/{post_id}")]
async fn blog_edit_by_id(tmpl: web::Data<tera::Tera>, web::Path(post_id): web::Path<std::string::String>) -> Result<HttpResponse, Error> {
let (valid, id) = id_valid(post_id);
if valid {
let mut post = db::get_post_by_id(id as i32);
@ -176,8 +149,7 @@ async fn blog_edit_by_id(
context.insert("body", &post.body);
context.insert("id", &id);
let result = tmpl
.render("edit-form.html", &context)
let result = tmpl.render("edit-form.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))