🚧 one-click server registration
parent
dc53aeed30
commit
a4ec4878ea
|
@ -1545,6 +1545,7 @@ dependencies = [
|
||||||
name = "ptth_relay"
|
name = "ptth_relay"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
"blake3",
|
"blake3",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -1562,6 +1563,7 @@ dependencies = [
|
||||||
"rusty_ulid",
|
"rusty_ulid",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
|
|
@ -11,6 +11,7 @@ repository = "https://github.com/ReactorScram/ptth"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
anyhow = "1.0.38"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
blake3 = "0.3.7"
|
blake3 = "0.3.7"
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
|
@ -27,6 +28,7 @@ rmp-serde = "0.14.4"
|
||||||
rusty_ulid = "0.10.1"
|
rusty_ulid = "0.10.1"
|
||||||
serde = { version = "1.0.117", features = ["derive"] }
|
serde = { version = "1.0.117", features = ["derive"] }
|
||||||
serde_json = "1.0.60"
|
serde_json = "1.0.60"
|
||||||
|
serde_urlencoded = "0.7.0"
|
||||||
thiserror = "1.0.22"
|
thiserror = "1.0.22"
|
||||||
tokio = { version = "1.4.0", features = [] }
|
tokio = { version = "1.4.0", features = [] }
|
||||||
tokio-stream = "0.1.3"
|
tokio-stream = "0.1.3"
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::HashSet,
|
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
@ -30,6 +29,7 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
use chrono::{
|
use chrono::{
|
||||||
DateTime,
|
DateTime,
|
||||||
SecondsFormat,
|
SecondsFormat,
|
||||||
|
@ -77,6 +77,10 @@ pub use config::{
|
||||||
};
|
};
|
||||||
pub use errors::*;
|
pub use errors::*;
|
||||||
pub use relay_state::Relay;
|
pub use relay_state::Relay;
|
||||||
|
use relay_state::{
|
||||||
|
AuditData,
|
||||||
|
AuditEvent,
|
||||||
|
};
|
||||||
|
|
||||||
use relay_state::{
|
use relay_state::{
|
||||||
RejectedServer,
|
RejectedServer,
|
||||||
|
@ -98,6 +102,12 @@ fn error_reply (status: StatusCode, b: &str)
|
||||||
.body (format! ("{}\n", b).into ())
|
.body (format! ("{}\n", b).into ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_user_name (req: &http::request::Parts)
|
||||||
|
-> Option <String>
|
||||||
|
{
|
||||||
|
req.headers.get ("X-Email").map (|x| Some (x.to_str ().ok ()?.to_string ())).flatten ()
|
||||||
|
}
|
||||||
|
|
||||||
/// Clients will come here to start requests, and always park for at least
|
/// Clients will come here to start requests, and always park for at least
|
||||||
/// a short amount of time.
|
/// a short amount of time.
|
||||||
|
|
||||||
|
@ -109,10 +119,6 @@ async fn handle_http_request (
|
||||||
)
|
)
|
||||||
-> Result <Response <Body>, RequestError>
|
-> Result <Response <Body>, RequestError>
|
||||||
{
|
{
|
||||||
use crate::relay_state::{
|
|
||||||
AuditData,
|
|
||||||
AuditEvent,
|
|
||||||
};
|
|
||||||
use RequestError::*;
|
use RequestError::*;
|
||||||
|
|
||||||
let req_method = req.method.clone ();
|
let req_method = req.method.clone ();
|
||||||
|
@ -124,7 +130,7 @@ async fn handle_http_request (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = req.headers.get ("X-Email").map (|x| Some (x.to_str ().ok ()?.to_string ())).flatten ();
|
let user = get_user_name (&req);
|
||||||
|
|
||||||
let req = match http_serde::RequestParts::from_hyper (req.method, uri.clone (), req.headers) {
|
let req = match http_serde::RequestParts::from_hyper (req.method, uri.clone (), req.headers) {
|
||||||
Ok (x) => x,
|
Ok (x) => x,
|
||||||
|
@ -522,6 +528,45 @@ async fn handle_gen_scraper_key (_state: Arc <Relay>)
|
||||||
.body (Body::from (body))
|
.body (Body::from (body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_register_server (req: Request <Body>, state: Arc <Relay>)
|
||||||
|
-> Result <(), anyhow::Error>
|
||||||
|
{
|
||||||
|
let (parts, body) = req.into_parts ();
|
||||||
|
let user = get_user_name (&parts);
|
||||||
|
|
||||||
|
let form_data = read_body_limited (body, 1_024).await?;
|
||||||
|
let reg: relay_state::Registration = serde_urlencoded::from_bytes (&form_data)?;
|
||||||
|
|
||||||
|
state.audit_log.push (AuditEvent::new (AuditData::RegisterServer {
|
||||||
|
user,
|
||||||
|
reg: reg.clone (),
|
||||||
|
})).await;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut me_config = state.me_config.write ().await;
|
||||||
|
|
||||||
|
//me_config.servers.
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok (())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_body_limited (mut body: Body, limit: usize) -> anyhow::Result <Vec <u8>>
|
||||||
|
{
|
||||||
|
let mut buffer = vec! [];
|
||||||
|
while let Some (chunk) = body.next ().await {
|
||||||
|
let chunk = chunk?;
|
||||||
|
|
||||||
|
if buffer.len () + chunk.len () > limit {
|
||||||
|
bail! ("Body was bigger than limit");
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.extend_from_slice (&chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok (buffer)
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument (level = "trace", skip (req, state, handlebars))]
|
#[instrument (level = "trace", skip (req, state, handlebars))]
|
||||||
async fn handle_all (
|
async fn handle_all (
|
||||||
req: Request <Body>,
|
req: Request <Body>,
|
||||||
|
@ -589,6 +634,15 @@ async fn handle_all (
|
||||||
},
|
},
|
||||||
ErrorMethodNotAllowed => error_reply (StatusCode::METHOD_NOT_ALLOWED, "Method not allowed. Are you POST-ing to a GET-only url, or vice versa?")?,
|
ErrorMethodNotAllowed => error_reply (StatusCode::METHOD_NOT_ALLOWED, "Method not allowed. Are you POST-ing to a GET-only url, or vice versa?")?,
|
||||||
ErrorRoutingFailed => error_reply (StatusCode::OK, "URL routing failed")?,
|
ErrorRoutingFailed => error_reply (StatusCode::OK, "URL routing failed")?,
|
||||||
|
RegisterServer => {
|
||||||
|
match handle_register_server (req, state).await {
|
||||||
|
Ok (_) => Response::builder ()
|
||||||
|
.status (StatusCode::TEMPORARY_REDIRECT)
|
||||||
|
.header ("location", "unregistered_servers")
|
||||||
|
.body (Body::from ("Success. Redirecting..."))?,
|
||||||
|
Err (e) => error_reply (StatusCode::BAD_REQUEST, &format! ("{:?}", e))?,
|
||||||
|
}
|
||||||
|
}
|
||||||
Root => {
|
Root => {
|
||||||
let s = handlebars.render ("root", &())?;
|
let s = handlebars.render ("root", &())?;
|
||||||
ok_reply (s)?
|
ok_reply (s)?
|
||||||
|
@ -675,11 +729,6 @@ pub async fn run_relay (
|
||||||
)
|
)
|
||||||
-> Result <(), RelayError>
|
-> Result <(), RelayError>
|
||||||
{
|
{
|
||||||
use crate::relay_state::{
|
|
||||||
AuditData,
|
|
||||||
AuditEvent,
|
|
||||||
};
|
|
||||||
|
|
||||||
let handlebars = Arc::new (load_templates (asset_root)?);
|
let handlebars = Arc::new (load_templates (asset_root)?);
|
||||||
|
|
||||||
if let Some (x) = git_version::read ().await {
|
if let Some (x) = git_version::read ().await {
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
|
use serde::Deserialize;
|
||||||
use tokio::sync::{
|
use tokio::sync::{
|
||||||
Mutex,
|
Mutex,
|
||||||
RwLock,
|
RwLock,
|
||||||
|
@ -116,6 +117,10 @@ pub struct AuditEvent {
|
||||||
|
|
||||||
#[derive (Clone, Debug)]
|
#[derive (Clone, Debug)]
|
||||||
pub enum AuditData {
|
pub enum AuditData {
|
||||||
|
RegisterServer {
|
||||||
|
user: Option <String>,
|
||||||
|
reg: Registration,
|
||||||
|
},
|
||||||
RelayStart,
|
RelayStart,
|
||||||
WebClientGet {
|
WebClientGet {
|
||||||
user: Option <String>,
|
user: Option <String>,
|
||||||
|
@ -125,6 +130,12 @@ pub enum AuditData {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive (Clone, Debug, Deserialize)]
|
||||||
|
pub struct Registration {
|
||||||
|
name: String,
|
||||||
|
tripcode: String,
|
||||||
|
}
|
||||||
|
|
||||||
impl AuditEvent {
|
impl AuditEvent {
|
||||||
pub fn new (data: AuditData) -> Self {
|
pub fn new (data: AuditData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub enum Route <'a> {
|
||||||
ErrorCantPost,
|
ErrorCantPost,
|
||||||
ErrorMethodNotAllowed,
|
ErrorMethodNotAllowed,
|
||||||
ErrorRoutingFailed,
|
ErrorRoutingFailed,
|
||||||
|
RegisterServer,
|
||||||
Root,
|
Root,
|
||||||
Scraper {
|
Scraper {
|
||||||
rest: &'a str,
|
rest: &'a str,
|
||||||
|
@ -45,6 +46,9 @@ pub fn route_url <'a> (method: &Method, path: &'a str) -> Route <'a> {
|
||||||
else if path == "/frontend/debug/toggle" {
|
else if path == "/frontend/debug/toggle" {
|
||||||
Route::DebugToggle
|
Route::DebugToggle
|
||||||
}
|
}
|
||||||
|
else if path == "/frontend/register" {
|
||||||
|
Route::RegisterServer
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Route::ErrorCantPost
|
Route::ErrorCantPost
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ AIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAA" rel="icon" type="image/x-icon" />
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
.padded {
|
.padded {
|
||||||
|
display: block;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
.submit {
|
.submit {
|
||||||
|
@ -61,11 +62,13 @@ AIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAA" rel="icon" type="image/x-icon" />
|
||||||
<td><span class="padded">{{this.name}}</span></td>
|
<td><span class="padded">{{this.name}}</span></td>
|
||||||
<td>
|
<td>
|
||||||
<span class="padded">{{this.tripcode}}</span>
|
<span class="padded">{{this.tripcode}}</span>
|
||||||
<form>
|
<!--
|
||||||
|
<form action="register" method="post">
|
||||||
<input type="hidden" name="name" value="{{this.name}}">
|
<input type="hidden" name="name" value="{{this.name}}">
|
||||||
<input type="hidden" name="tripcode" value="{{this.tripcode}}">
|
<input type="hidden" name="tripcode" value="{{this.tripcode}}">
|
||||||
<input class="submit" type="submit" value="Register">
|
<input class="submit" type="submit" value="Register">
|
||||||
</form>
|
</form>
|
||||||
|
-->
|
||||||
</td>
|
</td>
|
||||||
<td><span class="padded">{{this.last_seen}}</span></td>
|
<td><span class="padded">{{this.last_seen}}</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
Loading…
Reference in New Issue