⭐ new: add code for scraper keys to expire and have limited durations
							parent
							
								
									bf8e483d16
								
							
						
					
					
						commit
						0eb1e7e38f
					
				| 
						 | 
					@ -187,6 +187,7 @@ dependencies = [
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "num-integer",
 | 
					 "num-integer",
 | 
				
			||||||
 "num-traits",
 | 
					 "num-traits",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 "time",
 | 
					 "time",
 | 
				
			||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 "winapi 0.3.9",
 | 
					 "winapi 0.3.9",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ license = "AGPL-3.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
base64 = "0.12.3"
 | 
					base64 = "0.12.3"
 | 
				
			||||||
blake3 = "0.3.7"
 | 
					blake3 = "0.3.7"
 | 
				
			||||||
chrono = "0.4.19"
 | 
					chrono = {version = "0.4.19", features = ["serde"]}
 | 
				
			||||||
dashmap = "3.11.10"
 | 
					dashmap = "3.11.10"
 | 
				
			||||||
futures = "0.3.7"
 | 
					futures = "0.3.7"
 | 
				
			||||||
handlebars = "3.5.1"
 | 
					handlebars = "3.5.1"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,78 +3,20 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
	collections::HashMap,
 | 
						collections::HashMap,
 | 
				
			||||||
	convert::{TryFrom, TryInto},
 | 
						convert::{TryFrom},
 | 
				
			||||||
	fmt,
 | 
					 | 
				
			||||||
	iter::FromIterator,
 | 
						iter::FromIterator,
 | 
				
			||||||
	ops::Deref,
 | 
					 | 
				
			||||||
	path::Path,
 | 
						path::Path,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use serde::{
 | 
					 | 
				
			||||||
	Deserialize,
 | 
					 | 
				
			||||||
	Deserializer,
 | 
					 | 
				
			||||||
	de::{
 | 
					 | 
				
			||||||
		self,
 | 
					 | 
				
			||||||
		Visitor,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::errors::ConfigError;
 | 
					use crate::errors::ConfigError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct BlakeHashWrapper (blake3::Hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl BlakeHashWrapper {
 | 
					 | 
				
			||||||
	pub fn from_key (bytes: &[u8]) -> Self {
 | 
					 | 
				
			||||||
		Self (blake3::hash (bytes))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	pub fn encode_base64 (&self) -> String {
 | 
					 | 
				
			||||||
		base64::encode (self.as_bytes ())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Deref for BlakeHashWrapper {
 | 
					 | 
				
			||||||
	type Target = blake3::Hash;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	fn deref (&self) -> &<Self as Deref>::Target {
 | 
					 | 
				
			||||||
		&self.0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct BlakeHashVisitor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl <'de> Visitor <'de> for BlakeHashVisitor {
 | 
					 | 
				
			||||||
	type Value = blake3::Hash;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	fn expecting (&self, formatter: &mut fmt::Formatter) -> fmt::Result {
 | 
					 | 
				
			||||||
		formatter.write_str ("a 32-byte blake3 hash, encoded as base64")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	fn visit_str <E: de::Error> (self, value: &str) 
 | 
					 | 
				
			||||||
	-> Result <Self::Value, E>
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		let bytes: Vec <u8> = base64::decode (value).map_err (|_| E::custom (format! ("str is not base64: {}", value)))?;
 | 
					 | 
				
			||||||
		let bytes: [u8; 32] = (&bytes [..]).try_into ().map_err (|_| E::custom (format! ("decode base64 is not 32 bytes long: {}", value)))?;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		let tripcode = blake3::Hash::from (bytes);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		Ok (tripcode)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl <'de> Deserialize <'de> for BlakeHashWrapper {
 | 
					 | 
				
			||||||
	fn deserialize <D: Deserializer <'de>> (deserializer: D) -> Result <Self, D::Error> {
 | 
					 | 
				
			||||||
		Ok (BlakeHashWrapper (deserializer.deserialize_str (BlakeHashVisitor)?))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Stuff we need to load from the config file and use to
 | 
					// Stuff we need to load from the config file and use to
 | 
				
			||||||
// set up the HTTP server
 | 
					// set up the HTTP server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod file {
 | 
					pub mod file {
 | 
				
			||||||
	use serde::Deserialize;
 | 
						use serde::Deserialize;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	use super::*;
 | 
						use crate::key_validity::*;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	#[derive (Deserialize)]
 | 
						#[derive (Deserialize)]
 | 
				
			||||||
	pub struct Server {
 | 
						pub struct Server {
 | 
				
			||||||
| 
						 | 
					@ -84,16 +26,21 @@ pub mod file {
 | 
				
			||||||
		pub display_name: Option <String>,
 | 
							pub display_name: Option <String>,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						#[derive (Deserialize)]
 | 
				
			||||||
 | 
						pub struct DevMode {
 | 
				
			||||||
 | 
							pub scraper_key: Option <ScraperKey <Valid7Days>>,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	// Stuff that's identical between the file and the runtime structures
 | 
						// Stuff that's identical between the file and the runtime structures
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[derive (Default, Deserialize)]
 | 
						#[derive (Default, Deserialize)]
 | 
				
			||||||
	pub struct Isomorphic {
 | 
						pub struct Isomorphic {
 | 
				
			||||||
		#[serde (default)]
 | 
					 | 
				
			||||||
		pub enable_dev_mode:     bool,
 | 
					 | 
				
			||||||
		#[serde (default)]
 | 
							#[serde (default)]
 | 
				
			||||||
		pub enable_scraper_auth: bool,
 | 
							pub enable_scraper_auth: bool,
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		pub dev_scraper_key: Option <BlakeHashWrapper>,
 | 
							// If any of these fields are used, we are in dev mode and have to 
 | 
				
			||||||
 | 
							// show extra warnings, since some auth may be weakened
 | 
				
			||||||
 | 
							pub dev_mode: Option <DevMode>,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	#[derive (Deserialize)]
 | 
						#[derive (Deserialize)]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,222 @@
 | 
				
			||||||
 | 
					use std::{
 | 
				
			||||||
 | 
						convert::TryInto,
 | 
				
			||||||
 | 
						fmt,
 | 
				
			||||||
 | 
						ops::Deref,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use chrono::{DateTime, Duration, Utc};
 | 
				
			||||||
 | 
					use serde::{
 | 
				
			||||||
 | 
						de::{
 | 
				
			||||||
 | 
							self,
 | 
				
			||||||
 | 
							Visitor,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						Deserialize, 
 | 
				
			||||||
 | 
						Deserializer,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct BlakeHashWrapper (blake3::Hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl BlakeHashWrapper {
 | 
				
			||||||
 | 
						pub fn from_key (bytes: &[u8]) -> Self {
 | 
				
			||||||
 | 
							Self (blake3::hash (bytes))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						pub fn encode_base64 (&self) -> String {
 | 
				
			||||||
 | 
							base64::encode (self.as_bytes ())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Deref for BlakeHashWrapper {
 | 
				
			||||||
 | 
						type Target = blake3::Hash;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						fn deref (&self) -> &<Self as Deref>::Target {
 | 
				
			||||||
 | 
							&self.0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct BlakeHashVisitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl <'de> Visitor <'de> for BlakeHashVisitor {
 | 
				
			||||||
 | 
						type Value = blake3::Hash;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						fn expecting (&self, formatter: &mut fmt::Formatter) -> fmt::Result {
 | 
				
			||||||
 | 
							formatter.write_str ("a 32-byte blake3 hash, encoded as base64")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						fn visit_str <E: de::Error> (self, value: &str) 
 | 
				
			||||||
 | 
						-> Result <Self::Value, E>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							let bytes: Vec <u8> = base64::decode (value).map_err (|_| E::custom (format! ("str is not base64: {}", value)))?;
 | 
				
			||||||
 | 
							let bytes: [u8; 32] = (&bytes [..]).try_into ().map_err (|_| E::custom (format! ("decode base64 is not 32 bytes long: {}", value)))?;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let tripcode = blake3::Hash::from (bytes);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							Ok (tripcode)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl <'de> Deserialize <'de> for BlakeHashWrapper {
 | 
				
			||||||
 | 
						fn deserialize <D: Deserializer <'de>> (deserializer: D) -> Result <Self, D::Error> {
 | 
				
			||||||
 | 
							Ok (BlakeHashWrapper (deserializer.deserialize_str (BlakeHashVisitor)?))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Valid7Days;
 | 
				
			||||||
 | 
					//pub struct Valid30Days;
 | 
				
			||||||
 | 
					//pub struct Valid90Days;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait MaxValidDuration {
 | 
				
			||||||
 | 
						fn dur () -> Duration;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl MaxValidDuration for Valid7Days {
 | 
				
			||||||
 | 
						fn dur () -> Duration {
 | 
				
			||||||
 | 
							Duration::days (7)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive (Deserialize)]
 | 
				
			||||||
 | 
					pub struct ScraperKey <V: MaxValidDuration> {
 | 
				
			||||||
 | 
						pub not_before: DateTime <Utc>,
 | 
				
			||||||
 | 
						pub not_after: DateTime <Utc>,
 | 
				
			||||||
 | 
						pub hash: BlakeHashWrapper,
 | 
				
			||||||
 | 
						_phantom: std::marker::PhantomData <V>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive (Copy, Clone, Debug, PartialEq)]
 | 
				
			||||||
 | 
					pub enum KeyValidity {
 | 
				
			||||||
 | 
						Valid,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						WrongKey,
 | 
				
			||||||
 | 
						ClockIsBehind,
 | 
				
			||||||
 | 
						Expired,
 | 
				
			||||||
 | 
						DurationTooLong (Duration),
 | 
				
			||||||
 | 
						DurationNegative,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl <V: MaxValidDuration> ScraperKey <V> {
 | 
				
			||||||
 | 
						pub fn is_valid (&self, now: DateTime <Utc>, input: &[u8]) -> KeyValidity {
 | 
				
			||||||
 | 
							use KeyValidity::*;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// I put this first because I think the constant-time check should run
 | 
				
			||||||
 | 
							// before anything else. But I'm not a crypto expert, so it's just
 | 
				
			||||||
 | 
							// guesswork.
 | 
				
			||||||
 | 
							if blake3::hash (input) != *self.hash {
 | 
				
			||||||
 | 
								return WrongKey;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if self.not_after < self.not_before {
 | 
				
			||||||
 | 
								return DurationNegative;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let max_dur = V::dur ();
 | 
				
			||||||
 | 
							let actual_dur = self.not_after - self.not_before;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if actual_dur > max_dur {
 | 
				
			||||||
 | 
								return DurationTooLong (max_dur);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if now >= self.not_after {
 | 
				
			||||||
 | 
								return Expired;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if now < self.not_before {
 | 
				
			||||||
 | 
								return ClockIsBehind;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return Valid;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg (test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
						use chrono::{Utc};
 | 
				
			||||||
 | 
						use super::*;
 | 
				
			||||||
 | 
						use KeyValidity::*;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						#[test]
 | 
				
			||||||
 | 
						fn duration_negative () {
 | 
				
			||||||
 | 
							let zero_time = Utc::now ();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let key = ScraperKey::<Valid7Days> {
 | 
				
			||||||
 | 
								not_before: zero_time + Duration::days (1 + 2),
 | 
				
			||||||
 | 
								not_after: zero_time + Duration::days (1),
 | 
				
			||||||
 | 
								hash: BlakeHashWrapper::from_key ("bad_password".as_bytes ()),
 | 
				
			||||||
 | 
								_phantom: Default::default (),
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let err = DurationNegative;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for (input, expected) in &[
 | 
				
			||||||
 | 
								(zero_time + Duration::days (0), err),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (2), err),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (100), err),
 | 
				
			||||||
 | 
							] {
 | 
				
			||||||
 | 
								assert_eq! (key.is_valid (*input, "bad_password".as_bytes ()), *expected);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						#[test]
 | 
				
			||||||
 | 
						fn key_valid_too_long () {
 | 
				
			||||||
 | 
							let zero_time = Utc::now ();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let key = ScraperKey::<Valid7Days> {
 | 
				
			||||||
 | 
								not_before: zero_time + Duration::days (1),
 | 
				
			||||||
 | 
								not_after: zero_time + Duration::days (1 + 8),
 | 
				
			||||||
 | 
								hash: BlakeHashWrapper::from_key ("bad_password".as_bytes ()),
 | 
				
			||||||
 | 
								_phantom: Default::default (),
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let err = DurationTooLong (Duration::days (7));
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for (input, expected) in &[
 | 
				
			||||||
 | 
								(zero_time + Duration::days (0), err),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (2), err),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (100), err),
 | 
				
			||||||
 | 
							] {
 | 
				
			||||||
 | 
								assert_eq! (key.is_valid (*input, "bad_password".as_bytes ()), *expected);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						#[test]
 | 
				
			||||||
 | 
						fn normal_key () {
 | 
				
			||||||
 | 
							let zero_time = Utc::now ();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let key = ScraperKey::<Valid7Days> {
 | 
				
			||||||
 | 
								not_before: zero_time + Duration::days (1),
 | 
				
			||||||
 | 
								not_after: zero_time + Duration::days (1 + 7),
 | 
				
			||||||
 | 
								hash: BlakeHashWrapper::from_key ("bad_password".as_bytes ()),
 | 
				
			||||||
 | 
								_phantom: Default::default (),
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for (input, expected) in &[
 | 
				
			||||||
 | 
								(zero_time + Duration::days (0), ClockIsBehind),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (2), Valid),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (1 + 7), Expired),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (100), Expired),
 | 
				
			||||||
 | 
							] {
 | 
				
			||||||
 | 
								assert_eq! (key.is_valid (*input, "bad_password".as_bytes ()), *expected);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						#[test]
 | 
				
			||||||
 | 
						fn wrong_key () {
 | 
				
			||||||
 | 
							let zero_time = Utc::now ();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let key = ScraperKey::<Valid7Days> {
 | 
				
			||||||
 | 
								not_before: zero_time + Duration::days (1),
 | 
				
			||||||
 | 
								not_after: zero_time + Duration::days (1 + 7),
 | 
				
			||||||
 | 
								hash: BlakeHashWrapper::from_key ("bad_password".as_bytes ()),
 | 
				
			||||||
 | 
								_phantom: Default::default (),
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for (input, expected) in &[
 | 
				
			||||||
 | 
								(zero_time + Duration::days (0), WrongKey),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (2), WrongKey),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (1 + 7), WrongKey),
 | 
				
			||||||
 | 
								(zero_time + Duration::days (100), WrongKey),
 | 
				
			||||||
 | 
							] {
 | 
				
			||||||
 | 
								assert_eq! (key.is_valid (*input, "badder_password".as_bytes ()), *expected);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -62,6 +62,8 @@ use ptth_core::{
 | 
				
			||||||
pub mod config;
 | 
					pub mod config;
 | 
				
			||||||
pub mod errors;
 | 
					pub mod errors;
 | 
				
			||||||
pub mod git_version;
 | 
					pub mod git_version;
 | 
				
			||||||
 | 
					pub mod key_validity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod server_endpoint;
 | 
					mod server_endpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use config::Config;
 | 
					pub use config::Config;
 | 
				
			||||||
| 
						 | 
					@ -495,10 +497,9 @@ async fn reload_config (
 | 
				
			||||||
	(*config) = new_config;
 | 
						(*config) = new_config;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	debug! ("Loaded {} server configs", config.servers.len ());
 | 
						debug! ("Loaded {} server configs", config.servers.len ());
 | 
				
			||||||
	debug! ("enable_dev_mode: {}", config.iso.enable_dev_mode);
 | 
					 | 
				
			||||||
	debug! ("enable_scraper_auth: {}", config.iso.enable_scraper_auth);
 | 
						debug! ("enable_scraper_auth: {}", config.iso.enable_scraper_auth);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if config.iso.enable_dev_mode {
 | 
						if config.iso.dev_mode.is_some () {
 | 
				
			||||||
		error! ("Dev mode is enabled! This might turn off some security features. If you see this in production, escalate it to someone!");
 | 
							error! ("Dev mode is enabled! This might turn off some security features. If you see this in production, escalate it to someone!");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,8 +33,6 @@ stronger is ready.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (X) Add feature flags to ptth_relay.toml for dev mode and scrapers
 | 
					- (X) Add feature flags to ptth_relay.toml for dev mode and scrapers
 | 
				
			||||||
- (X) Make sure Docker release CAN build
 | 
					- (X) Make sure Docker release CAN build
 | 
				
			||||||
- ( ) Add failing test to block releases
 | 
					 | 
				
			||||||
- ( ) Make sure `cargo test` fails and Docker release can NOT build
 | 
					 | 
				
			||||||
- ( ) Add hash of 1 scraper key to ptth_relay.toml, with 1 week expiration
 | 
					- ( ) Add hash of 1 scraper key to ptth_relay.toml, with 1 week expiration
 | 
				
			||||||
- ( ) (POC) Test with curl
 | 
					- ( ) (POC) Test with curl
 | 
				
			||||||
- ( ) Manually create SQLite DB for scraper keys, add 1 hash
 | 
					- ( ) Manually create SQLite DB for scraper keys, add 1 hash
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ fn end_to_end () {
 | 
				
			||||||
	use reqwest::Client;
 | 
						use reqwest::Client;
 | 
				
			||||||
	use tracing::{debug, info};
 | 
						use tracing::{debug, info};
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	use ptth_relay::config::BlakeHashWrapper;
 | 
						use ptth_relay::key_validity::BlakeHashWrapper;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Prefer this form for tests, since all tests share one process
 | 
						// Prefer this form for tests, since all tests share one process
 | 
				
			||||||
	// and we don't care if another test already installed a subscriber.
 | 
						// and we don't care if another test already installed a subscriber.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue