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…
	
	Add table
		
		Reference in a new issue