added qrcode on the tags
This commit is contained in:
parent
dd26eed497
commit
761e1daf23
10 changed files with 163 additions and 5 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -3,10 +3,26 @@
|
|||
This will try to keep history of all changes and document impacts in deployment / hosting.
|
||||
All versions before v1.1.0 are ignored as the tool was only ready-ish at v1.1.0
|
||||
|
||||
## [next]
|
||||
## v2.0.0
|
||||
|
||||
breaking change: configuration changes
|
||||
|
||||
- added*: qrcode generation of tags
|
||||
- added: admin prod deployment instructions
|
||||
|
||||
the qrcode generation of tags introduces a new required configuration key, `default.public_url`.
|
||||
This should contain the canonical base URL of your instance (e.g. `https://dolltags.pet/`).
|
||||
|
||||
Example below.
|
||||
|
||||
```toml
|
||||
[default]
|
||||
secret_key=...
|
||||
public_url="https://dolltags.pet/"
|
||||
|
||||
[...]
|
||||
```
|
||||
|
||||
## v1.3.0 - 2025-02-07
|
||||
|
||||
- added: social tags; sharing in a social network should give a small preview of the base details
|
||||
|
|
99
Cargo.lock
generated
99
Cargo.lock
generated
|
@ -305,6 +305,12 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.10.0"
|
||||
|
@ -472,6 +478,15 @@ version = "2.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.14"
|
||||
|
@ -631,6 +646,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"clap",
|
||||
"orion",
|
||||
"qrcode-generator",
|
||||
"rand",
|
||||
"regex",
|
||||
"rocket",
|
||||
|
@ -704,6 +720,15 @@ version = "2.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "fdeflate"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
|
||||
dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.9"
|
||||
|
@ -736,6 +761,16 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.11.1"
|
||||
|
@ -1054,6 +1089,15 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html-escape"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
|
||||
dependencies = [
|
||||
"utf8-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.12"
|
||||
|
@ -1310,6 +1354,18 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
"num-traits",
|
||||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.7.1"
|
||||
|
@ -1539,6 +1595,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1932,6 +1989,19 @@ version = "0.3.31"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.6.2"
|
||||
|
@ -1981,6 +2051,23 @@ dependencies = [
|
|||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qrcode-generator"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf0051849b5465059b75f59d388c7318aad6554701b74ecf02afc2573b0306c"
|
||||
dependencies = [
|
||||
"html-escape",
|
||||
"image",
|
||||
"qrcodegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qrcodegen"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
|
@ -2434,6 +2521,12 @@ dependencies = [
|
|||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.1"
|
||||
|
@ -3256,6 +3349,12 @@ version = "1.0.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
|
|
|
@ -22,3 +22,4 @@ anyhow = "1.0"
|
|||
orion = "0.17"
|
||||
uuid = { version = "1.11", features = ["serde"] }
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
qrcode-generator = "5"
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
[default]
|
||||
secret_key = "8STDFCStGMYGoOq8RJf3JJXsg4p6wZVAph50R3Fbq6U="
|
||||
public_url = "http://localhost:8000/"
|
||||
|
||||
[default.databases.dolltags]
|
||||
url = "postgres://postgres:woofwoof@localhost/dolltags"
|
||||
|
|
7
src/config.rs
Normal file
7
src/config.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use rocket::serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Config {
|
||||
pub public_url: String,
|
||||
}
|
|
@ -6,6 +6,7 @@ use std::path::PathBuf;
|
|||
|
||||
use auth::session;
|
||||
use cli::check_cli_invocation;
|
||||
use config::Config;
|
||||
use db::migrate::run_migrations;
|
||||
use db::schema::DollTags;
|
||||
use rocket::fairing::AdHoc;
|
||||
|
@ -16,6 +17,7 @@ use routes::{account, admin, error_handlers, form, public};
|
|||
|
||||
pub mod auth;
|
||||
pub mod cli;
|
||||
pub mod config;
|
||||
pub mod db;
|
||||
pub mod ids;
|
||||
pub mod pages;
|
||||
|
@ -49,6 +51,7 @@ fn rocket() -> _ {
|
|||
rocket::build()
|
||||
.attach(pages::init_templates())
|
||||
.attach(DollTags::init())
|
||||
.attach(AdHoc::config::<Config>())
|
||||
.attach(AdHoc::try_on_ignite("SQLx migrations", run_migrations))
|
||||
.attach(AdHoc::on_liftoff("CLI invocation hack", |rocket| {
|
||||
Box::pin(async move { check_cli_invocation(rocket).await })
|
||||
|
@ -66,6 +69,7 @@ fn rocket() -> _ {
|
|||
"/account",
|
||||
routes![
|
||||
account::index,
|
||||
account::qr_profile,
|
||||
account::show_settings,
|
||||
account::change_settings,
|
||||
account::change_password,
|
||||
|
|
|
@ -5,12 +5,12 @@ use rocket::{
|
|||
outcome::try_outcome,
|
||||
request::{FromRequest, Outcome},
|
||||
serde::Serialize,
|
||||
Request,
|
||||
Request, State,
|
||||
};
|
||||
use rocket_dyn_templates::{tera::try_get_value, Template};
|
||||
use serde_json::{to_value, Value};
|
||||
|
||||
use crate::{auth::session::Session, db::schema::User, ids};
|
||||
use crate::{auth::session::Session, config::Config, db::schema::User, ids};
|
||||
|
||||
pub fn init_templates() -> impl Fairing {
|
||||
Template::custom(|engines| {
|
||||
|
@ -36,6 +36,8 @@ pub struct CommonTemplateState {
|
|||
pub is_admin: bool,
|
||||
/// feature flag - disables the UI for it since it's not implemeted yet.
|
||||
pub forgot_password_implemented: bool,
|
||||
/// the website's public base URL (used for canonical URLs)
|
||||
pub public_url: String,
|
||||
}
|
||||
|
||||
impl CommonTemplateState {
|
||||
|
@ -55,11 +57,13 @@ impl<'r> FromRequest<'r> for CommonTemplateState {
|
|||
|
||||
async fn from_request(request: &'r Request<'_>) -> Outcome<CommonTemplateState, ()> {
|
||||
let session_state = try_outcome!(request.guard::<Session>().await);
|
||||
let config_state = try_outcome!(request.guard::<&State<Config>>().await);
|
||||
|
||||
Outcome::Success(CommonTemplateState {
|
||||
logged_in: session_state.0.is_some(),
|
||||
is_admin: false,
|
||||
forgot_password_implemented: false,
|
||||
public_url: config_state.public_url.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
use std::net::IpAddr;
|
||||
|
||||
use qrcode_generator::QrCodeEcc;
|
||||
use rocket::{
|
||||
form::{self, Contextual, Error, Form},
|
||||
http::CookieJar,
|
||||
http::{uri::Absolute, CookieJar},
|
||||
response::Redirect,
|
||||
serde::{json::Json, Serialize},
|
||||
tokio::task,
|
||||
State,
|
||||
};
|
||||
use rocket_dyn_templates::{context, Template};
|
||||
use sqlx::Acquire;
|
||||
|
||||
use crate::{
|
||||
auth::{pw, session},
|
||||
config::Config,
|
||||
db::{
|
||||
doll,
|
||||
schema::{DollProfile, DollTagsDb, User},
|
||||
|
@ -39,6 +42,15 @@ pub async fn index(mut db: DollTagsDb, user: User, meta: CommonTemplateState) ->
|
|||
.into())
|
||||
}
|
||||
|
||||
#[get("/qr-png/<id>")]
|
||||
pub fn qr_profile(id: &str, _user: User, config: &State<Config>) -> PageResult {
|
||||
let public_uri = Absolute::parse(&config.public_url)?;
|
||||
let built_uri = uri!(public_uri, crate::routes::public::short_url(id));
|
||||
let image = qrcode_generator::to_png_to_vec(built_uri.to_string(), QrCodeEcc::Low, 400)?;
|
||||
|
||||
Ok(image.into())
|
||||
}
|
||||
|
||||
#[get("/settings")]
|
||||
pub fn show_settings(user: User, meta: CommonTemplateState) -> Template {
|
||||
Template::render(
|
||||
|
|
|
@ -10,6 +10,8 @@ pub async fn not_found() -> Template {
|
|||
pub enum PageResponse {
|
||||
Page(Template),
|
||||
Redirect(Redirect),
|
||||
#[response(content_type = "image/png")]
|
||||
Image(Vec<u8>),
|
||||
}
|
||||
|
||||
impl From<Template> for PageResponse {
|
||||
|
@ -24,6 +26,12 @@ impl From<Redirect> for PageResponse {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for PageResponse {
|
||||
fn from(value: Vec<u8>) -> Self {
|
||||
PageResponse::Image(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Responder)]
|
||||
#[response(status = 500)]
|
||||
pub struct Fail(Template);
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
<a href="/account/edit_tag/{{profile.id}}">Edit</a>
|
||||
<a href="/account/delete/{{profile.id}}">Delete</a>
|
||||
</div>
|
||||
<details>
|
||||
<summary>show the QR code</summary>
|
||||
|
||||
<img loading="lazy" src="/account/qr-png/{{profile.id}}" alt="A QrCode containing a direct link to the profile" />
|
||||
</details>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
|
@ -52,4 +57,4 @@
|
|||
</ul>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock main %}
|
||||
{% endblock main %}
|
||||
|
|
Loading…
Add table
Reference in a new issue