forked from mirrors/relay
Add ructe
This commit is contained in:
parent
ef13e93140
commit
fbed60248d
8 changed files with 271 additions and 23 deletions
1
.env
1
.env
|
@ -1 +1,2 @@
|
||||||
|
OUT_DIR="compiled_templates"
|
||||||
DATABASE_URL=postgres://ap_actix:ap_actix@localhost:5432/ap_actix
|
DATABASE_URL=postgres://ap_actix:ap_actix@localhost:5432/ap_actix
|
||||||
|
|
57
Cargo.lock
generated
57
Cargo.lock
generated
|
@ -581,6 +581,12 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytecount"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.4"
|
version = "1.3.4"
|
||||||
|
@ -1160,6 +1166,15 @@ dependencies = [
|
||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
@ -1443,6 +1458,17 @@ dependencies = [
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits 0.2.11",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
|
@ -1764,12 +1790,14 @@ dependencies = [
|
||||||
"http-signature-normalization-actix",
|
"http-signature-normalization-actix",
|
||||||
"log",
|
"log",
|
||||||
"lru",
|
"lru",
|
||||||
|
"mime",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
"rand",
|
"rand",
|
||||||
"rsa",
|
"rsa",
|
||||||
"rsa-magic-public-key",
|
"rsa-magic-public-key",
|
||||||
"rsa-pem",
|
"rsa-pem",
|
||||||
|
"ructe",
|
||||||
"serde 1.0.105",
|
"serde 1.0.105",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
@ -1850,6 +1878,35 @@ dependencies = [
|
||||||
"yasna",
|
"yasna",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rsass"
|
||||||
|
version = "0.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53314103d427bab245db7b3d1602faf509d2dd03db85b32421d1748e93bb4475"
|
||||||
|
dependencies = [
|
||||||
|
"bytecount",
|
||||||
|
"lazy_static",
|
||||||
|
"nom",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits 0.2.11",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ructe"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c85620b8046f88a870d93d90fa56904dec76cc79139bfcc22e71e87f0cd2169f"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.11.0",
|
||||||
|
"bytecount",
|
||||||
|
"itertools",
|
||||||
|
"md5",
|
||||||
|
"mime",
|
||||||
|
"nom",
|
||||||
|
"rsass",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-ini"
|
name = "rust-ini"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
|
|
@ -8,6 +8,7 @@ readme = "README.md"
|
||||||
repository = "https://git.asonix.dog/asonix/ap-relay"
|
repository = "https://git.asonix.dog/asonix/ap-relay"
|
||||||
keywords = ["activitypub", "relay"]
|
keywords = ["activitypub", "relay"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
build = "src/build.rs"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ futures = "0.3.4"
|
||||||
http-signature-normalization-actix = { version = "0.3.0-alpha.7", default-features = false, features = ["sha-2"] }
|
http-signature-normalization-actix = { version = "0.3.0-alpha.7", default-features = false, features = ["sha-2"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
lru = "0.4.3"
|
lru = "0.4.3"
|
||||||
|
mime = "0.3.16"
|
||||||
num_cpus = "1.12"
|
num_cpus = "1.12"
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
|
@ -42,5 +44,10 @@ tokio = { version = "0.2.13", features = ["sync"] }
|
||||||
ttl_cache = "0.5.1"
|
ttl_cache = "0.5.1"
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
|
dotenv = "0.15.0"
|
||||||
|
ructe = { version = "0.9.2", features = ["sass", "mime03"] }
|
||||||
|
|
||||||
[profile.dev.package.rsa]
|
[profile.dev.package.rsa]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
82
scss/index.scss
Normal file
82
scss/index.scss
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
body {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
font-family: sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding-bottom: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
body * {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding: 32px 0;
|
||||||
|
background-color: #333;
|
||||||
|
color: #f5f5f5;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin: 32px auto 0;
|
||||||
|
max-width: 700px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 8px;
|
||||||
|
padding-left: 32px;
|
||||||
|
padding-top: 10px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: ' ';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 24px;
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background-color: #333;
|
||||||
|
color: #f5f5f5;
|
||||||
|
position: absolute;
|
||||||
|
padding: 16px 8px;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
a {
|
||||||
|
&,
|
||||||
|
&:focus,
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
color: #ea7fbc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
12
src/build.rs
Normal file
12
src/build.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use ructe::Ructe;
|
||||||
|
|
||||||
|
fn main() -> Result<(), anyhow::Error> {
|
||||||
|
dotenv::dotenv().ok();
|
||||||
|
|
||||||
|
let mut ructe = Ructe::from_env()?;
|
||||||
|
let mut statics = ructe.statics()?;
|
||||||
|
statics.add_sass_file("scss/index.scss")?;
|
||||||
|
ructe.compile_templates("templates")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -64,6 +64,9 @@ pub enum MyError {
|
||||||
#[error("Too many CPUs, {0}")]
|
#[error("Too many CPUs, {0}")]
|
||||||
CpuCount(#[from] std::num::TryFromIntError),
|
CpuCount(#[from] std::num::TryFromIntError),
|
||||||
|
|
||||||
|
#[error("Couldn't flush buffer")]
|
||||||
|
FlushBuffer,
|
||||||
|
|
||||||
#[error("Timed out while waiting on db pool")]
|
#[error("Timed out while waiting on db pool")]
|
||||||
DbTimeout,
|
DbTimeout,
|
||||||
|
|
||||||
|
|
68
src/main.rs
68
src/main.rs
|
@ -1,5 +1,14 @@
|
||||||
use actix_web::{middleware::Logger, web, App, HttpServer, Responder};
|
use actix_web::{
|
||||||
|
http::header::{ContentType, Expires},
|
||||||
|
middleware::Logger,
|
||||||
|
web, App, HttpResponse, HttpServer,
|
||||||
|
};
|
||||||
use bb8_postgres::tokio_postgres;
|
use bb8_postgres::tokio_postgres;
|
||||||
|
use log::error;
|
||||||
|
use std::{
|
||||||
|
io::BufWriter,
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
|
||||||
mod actor;
|
mod actor;
|
||||||
mod apub;
|
mod apub;
|
||||||
|
@ -17,32 +26,42 @@ mod state;
|
||||||
mod verifier;
|
mod verifier;
|
||||||
mod webfinger;
|
mod webfinger;
|
||||||
|
|
||||||
use self::{args::Args, config::Config, db::Db, state::State, webfinger::RelayResolver};
|
use self::{
|
||||||
|
args::Args, config::Config, db::Db, error::MyError, state::State,
|
||||||
async fn index(state: web::Data<State>, config: web::Data<Config>) -> impl Responder {
|
templates::statics::StaticFile, webfinger::RelayResolver,
|
||||||
let mut s = String::new();
|
};
|
||||||
s.push_str(&format!("Welcome to the relay on {}\n", config.hostname()));
|
|
||||||
|
|
||||||
|
async fn index(
|
||||||
|
state: web::Data<State>,
|
||||||
|
config: web::Data<Config>,
|
||||||
|
) -> Result<HttpResponse, MyError> {
|
||||||
let listeners = state.listeners().await;
|
let listeners = state.listeners().await;
|
||||||
if listeners.is_empty() {
|
|
||||||
s.push_str("There are no currently connected servers\n");
|
let mut buf = BufWriter::new(Vec::new());
|
||||||
|
|
||||||
|
templates::index(&mut buf, &listeners, &config)?;
|
||||||
|
let buf = buf.into_inner().map_err(|e| {
|
||||||
|
error!("Error rendering template, {}", e.error());
|
||||||
|
MyError::FlushBuffer
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().content_type("text/html").body(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
static FAR: Duration = Duration::from_secs(60 * 60 * 24);
|
||||||
|
|
||||||
|
async fn static_file(filename: web::Path<String>) -> HttpResponse {
|
||||||
|
if let Some(data) = StaticFile::get(&filename.into_inner()) {
|
||||||
|
let far_expires = SystemTime::now() + FAR;
|
||||||
|
HttpResponse::Ok()
|
||||||
|
.set(Expires(far_expires.into()))
|
||||||
|
.set(ContentType(data.mime.clone()))
|
||||||
|
.body(data.content)
|
||||||
} else {
|
} else {
|
||||||
s.push_str("Here are the currently connected servers:\n");
|
HttpResponse::NotFound()
|
||||||
s.push_str("\n");
|
.reason("No such static file.")
|
||||||
|
.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
for listener in listeners {
|
|
||||||
if let Some(domain) = listener.as_url().domain() {
|
|
||||||
s.push_str(&format!("{}\n", domain));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.push_str("\n");
|
|
||||||
s.push_str(&format!(
|
|
||||||
"The source code for this project can be found at {}\n",
|
|
||||||
config.source_code()
|
|
||||||
));
|
|
||||||
|
|
||||||
s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
|
@ -107,9 +126,12 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
.service(actix_webfinger::scoped::<_, RelayResolver>())
|
.service(actix_webfinger::scoped::<_, RelayResolver>())
|
||||||
.service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))),
|
.service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))),
|
||||||
)
|
)
|
||||||
|
.service(web::resource("/static/{filename}").route(web::get().to(static_file)))
|
||||||
})
|
})
|
||||||
.bind(bind_address)?
|
.bind(bind_address)?
|
||||||
.run()
|
.run()
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
|
||||||
|
|
64
templates/index.rs.html
Normal file
64
templates/index.rs.html
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
@use crate::{config::{Config, UrlKind}, templates::statics::index_css};
|
||||||
|
@use activitystreams::primitives::XsdAnyUri;
|
||||||
|
|
||||||
|
@(listeners: &[XsdAnyUri], config: &Config)
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head lang="en">
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>@config.hostname() | ActivityPub Relay</title>
|
||||||
|
<link rel="stylesheet" href="/static/@index_css.name" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Welcome to @config.software_name() on @config.hostname()</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<section>
|
||||||
|
<h3>Connected Servers:</h3>
|
||||||
|
@if listeners.is_empty() {
|
||||||
|
<p>There are no connected servers at this time.</p>
|
||||||
|
} else {
|
||||||
|
<ul>
|
||||||
|
@for listener in listeners {
|
||||||
|
@if let Some(domain) = listener.as_url().domain() {
|
||||||
|
<li>@domain</li>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h3>Joining</h3>
|
||||||
|
<p>
|
||||||
|
If you are the admin of a server that supports activitypub relays, you can add
|
||||||
|
this relay to your server.
|
||||||
|
</p>
|
||||||
|
<h4>Mastodon</h4>
|
||||||
|
<p>
|
||||||
|
Mastodon admins can add this relay by adding
|
||||||
|
<pre>@config.generate_url(UrlKind::Inbox)</pre> in their relay settings.
|
||||||
|
</p>
|
||||||
|
<h4>Pleroma</h4>
|
||||||
|
<p>
|
||||||
|
Pleroma admins can add this relay by adding
|
||||||
|
<pre>@config.generate_url(UrlKind::Actor)</pre>
|
||||||
|
to their relay settings (I don't actually know how pleroma handles adding
|
||||||
|
relays, is it still a mix command?).
|
||||||
|
</p>
|
||||||
|
<h4>Others</h4>
|
||||||
|
<p>
|
||||||
|
Consult the documentation for your server. It's likely that it follows either
|
||||||
|
Mastodon or Pleroma's relay formatting.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
<p>
|
||||||
|
The source code for this project can be found at
|
||||||
|
<a href="@config.source_code()">@config.source_code()</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue