Add commandline blocking and whitelisting
This commit is contained in:
		
							parent
							
								
									3c5154d449
								
							
						
					
					
						commit
						eefff20941
					
				
					 14 changed files with 723 additions and 283 deletions
				
			
		
							
								
								
									
										1
									
								
								.env
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								.env
									
										
									
									
									
								
							|  | @ -1,2 +1 @@ | |||
| DATABASE_URL=postgres://ap_actix:ap_actix@localhost:5432/ap_actix | ||||
| HOSTNAME=localhost:8080 | ||||
|  |  | |||
							
								
								
									
										294
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										294
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -9,7 +9,7 @@ dependencies = [ | |||
|  "activitystreams-derive", | ||||
|  "chrono", | ||||
|  "mime", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_json", | ||||
|  "thiserror", | ||||
|  "url", | ||||
|  | @ -127,7 +127,7 @@ dependencies = [ | |||
|  "pin-project", | ||||
|  "rand", | ||||
|  "regex", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_json", | ||||
|  "serde_urlencoded", | ||||
|  "sha-1", | ||||
|  | @ -155,7 +155,7 @@ dependencies = [ | |||
|  "http", | ||||
|  "log", | ||||
|  "regex", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -298,7 +298,7 @@ dependencies = [ | |||
|  "pin-project", | ||||
|  "regex", | ||||
|  "rustls", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_json", | ||||
|  "serde_urlencoded", | ||||
|  "time 0.2.9", | ||||
|  | @ -324,7 +324,7 @@ checksum = "120ce509b4ad2a0dedfbaebc1c1fb2b5e7bb34430a851c3eb264a704135e30a7" | |||
| dependencies = [ | ||||
|  "actix-http", | ||||
|  "actix-web", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_derive", | ||||
|  "thiserror", | ||||
| ] | ||||
|  | @ -364,6 +364,15 @@ dependencies = [ | |||
|  "memchr", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ansi_term" | ||||
| version = "0.11.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" | ||||
| dependencies = [ | ||||
|  "winapi 0.3.8", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anyhow" | ||||
| version = "1.0.27" | ||||
|  | @ -382,6 +391,7 @@ dependencies = [ | |||
|  "anyhow", | ||||
|  "base64 0.12.0", | ||||
|  "bb8-postgres", | ||||
|  "config", | ||||
|  "dotenv", | ||||
|  "futures", | ||||
|  "http-signature-normalization-actix", | ||||
|  | @ -393,9 +403,10 @@ dependencies = [ | |||
|  "rsa", | ||||
|  "rsa-magic-public-key", | ||||
|  "rsa-pem", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_json", | ||||
|  "sha2", | ||||
|  "structopt", | ||||
|  "thiserror", | ||||
|  "tokio", | ||||
|  "ttl_cache", | ||||
|  | @ -408,6 +419,15 @@ version = "0.4.5" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "arrayvec" | ||||
| version = "0.4.12" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" | ||||
| dependencies = [ | ||||
|  "nodrop", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "async-trait" | ||||
| version = "0.1.24" | ||||
|  | @ -461,7 +481,7 @@ dependencies = [ | |||
|  "percent-encoding", | ||||
|  "rand", | ||||
|  "rustls", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_json", | ||||
|  "serde_urlencoded", | ||||
| ] | ||||
|  | @ -635,10 +655,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" | ||||
| dependencies = [ | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.11", | ||||
|  "time 0.1.42", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "clap" | ||||
| version = "2.33.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" | ||||
| dependencies = [ | ||||
|  "ansi_term", | ||||
|  "atty", | ||||
|  "bitflags", | ||||
|  "strsim", | ||||
|  "textwrap", | ||||
|  "unicode-width", | ||||
|  "vec_map", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cloudabi" | ||||
| version = "0.0.3" | ||||
|  | @ -648,6 +683,22 @@ dependencies = [ | |||
|  "bitflags", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "config" | ||||
| version = "0.10.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
|  "nom", | ||||
|  "rust-ini", | ||||
|  "serde 1.0.105", | ||||
|  "serde-hjson", | ||||
|  "serde_json", | ||||
|  "toml", | ||||
|  "yaml-rust", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "const-random" | ||||
| version = "0.1.8" | ||||
|  | @ -1183,6 +1234,19 @@ dependencies = [ | |||
|  "spin", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lexical-core" | ||||
| version = "0.6.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890" | ||||
| dependencies = [ | ||||
|  "arrayvec", | ||||
|  "cfg-if", | ||||
|  "rustc_version", | ||||
|  "ryu", | ||||
|  "static_assertions", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "libc" | ||||
| version = "0.2.68" | ||||
|  | @ -1195,6 +1259,16 @@ version = "0.2.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "linked-hash-map" | ||||
| version = "0.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" | ||||
| dependencies = [ | ||||
|  "serde 0.8.23", | ||||
|  "serde_test", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "linked-hash-map" | ||||
| version = "0.5.2" | ||||
|  | @ -1234,7 +1308,7 @@ version = "0.1.2" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" | ||||
| dependencies = [ | ||||
|  "linked-hash-map", | ||||
|  "linked-hash-map 0.5.2", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1335,6 +1409,23 @@ dependencies = [ | |||
|  "winapi 0.3.8", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "nodrop" | ||||
| version = "0.1.14" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "nom" | ||||
| version = "5.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" | ||||
| dependencies = [ | ||||
|  "lexical-core", | ||||
|  "memchr", | ||||
|  "version_check", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "num-bigint" | ||||
| version = "0.2.6" | ||||
|  | @ -1343,7 +1434,7 @@ checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" | |||
| dependencies = [ | ||||
|  "autocfg 1.0.0", | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.11", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1358,9 +1449,9 @@ dependencies = [ | |||
|  "libm", | ||||
|  "num-integer", | ||||
|  "num-iter", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.11", | ||||
|  "rand", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "smallvec", | ||||
|  "zeroize", | ||||
| ] | ||||
|  | @ -1372,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" | ||||
| dependencies = [ | ||||
|  "autocfg 1.0.0", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.11", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1383,7 +1474,16 @@ checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" | |||
| dependencies = [ | ||||
|  "autocfg 1.0.0", | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.11", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "num-traits" | ||||
| version = "0.1.43" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" | ||||
| dependencies = [ | ||||
|  "num-traits 0.2.11", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1547,6 +1647,32 @@ dependencies = [ | |||
|  "log", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-error" | ||||
| version = "0.4.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" | ||||
| dependencies = [ | ||||
|  "proc-macro-error-attr", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "version_check", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-error-attr" | ||||
| version = "0.4.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn-mid", | ||||
|  "version_check", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-hack" | ||||
| version = "0.5.12" | ||||
|  | @ -1690,7 +1816,7 @@ dependencies = [ | |||
|  "num-bigint-dig", | ||||
|  "num-integer", | ||||
|  "num-iter", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.11", | ||||
|  "rand", | ||||
|  "subtle 2.2.2", | ||||
|  "zeroize", | ||||
|  | @ -1716,13 +1842,19 @@ dependencies = [ | |||
|  "log", | ||||
|  "num-bigint", | ||||
|  "num-bigint-dig", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.11", | ||||
|  "pem", | ||||
|  "rsa", | ||||
|  "thiserror", | ||||
|  "yasna", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rust-ini" | ||||
| version = "0.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rustc-demangle" | ||||
| version = "0.1.16" | ||||
|  | @ -1799,6 +1931,12 @@ version = "0.7.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "0.8.23" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.105" | ||||
|  | @ -1808,6 +1946,19 @@ dependencies = [ | |||
|  "serde_derive", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde-hjson" | ||||
| version = "0.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
|  "linked-hash-map 0.3.0", | ||||
|  "num-traits 0.1.43", | ||||
|  "regex", | ||||
|  "serde 0.8.23", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_derive" | ||||
| version = "1.0.105" | ||||
|  | @ -1827,7 +1978,16 @@ checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" | |||
| dependencies = [ | ||||
|  "itoa", | ||||
|  "ryu", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_test" | ||||
| version = "0.8.23" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" | ||||
| dependencies = [ | ||||
|  "serde 0.8.23", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1838,7 +1998,7 @@ checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" | |||
| dependencies = [ | ||||
|  "dtoa", | ||||
|  "itoa", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "url", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1924,6 +2084,12 @@ version = "0.2.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4edf667ea8f60afc06d6aeec079d20d5800351109addec1faea678a8663da4e1" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "static_assertions" | ||||
| version = "0.3.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "stdweb" | ||||
| version = "0.4.20" | ||||
|  | @ -1946,7 +2112,7 @@ checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" | |||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_derive", | ||||
|  "syn", | ||||
| ] | ||||
|  | @ -1960,7 +2126,7 @@ dependencies = [ | |||
|  "base-x", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "serde", | ||||
|  "serde 1.0.105", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "sha1", | ||||
|  | @ -1983,6 +2149,36 @@ dependencies = [ | |||
|  "unicode-normalization", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "strsim" | ||||
| version = "0.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "structopt" | ||||
| version = "0.3.12" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d" | ||||
| dependencies = [ | ||||
|  "clap", | ||||
|  "lazy_static", | ||||
|  "structopt-derive", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "structopt-derive" | ||||
| version = "0.4.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430" | ||||
| dependencies = [ | ||||
|  "heck", | ||||
|  "proc-macro-error", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "subtle" | ||||
| version = "1.0.0" | ||||
|  | @ -2006,6 +2202,17 @@ dependencies = [ | |||
|  "unicode-xid", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "syn-mid" | ||||
| version = "0.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "synstructure" | ||||
| version = "0.12.3" | ||||
|  | @ -2027,6 +2234,15 @@ dependencies = [ | |||
|  "winapi-util", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "textwrap" | ||||
| version = "0.11.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" | ||||
| dependencies = [ | ||||
|  "unicode-width", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "thiserror" | ||||
| version = "1.0.11" | ||||
|  | @ -2196,6 +2412,15 @@ dependencies = [ | |||
|  "tokio", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "toml" | ||||
| version = "0.5.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" | ||||
| dependencies = [ | ||||
|  "serde 1.0.105", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "trust-dns-proto" | ||||
| version = "0.19.3" | ||||
|  | @ -2242,7 +2467,7 @@ version = "0.5.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4189890526f0168710b6ee65ceaedf1460c48a14318ceec933cb26baa492096a" | ||||
| dependencies = [ | ||||
|  "linked-hash-map", | ||||
|  "linked-hash-map 0.5.2", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2275,6 +2500,12 @@ version = "1.6.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "unicode-width" | ||||
| version = "0.1.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "unicode-xid" | ||||
| version = "0.2.0" | ||||
|  | @ -2307,6 +2538,18 @@ dependencies = [ | |||
|  "rand", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "vec_map" | ||||
| version = "0.8.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "version_check" | ||||
| version = "0.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasi" | ||||
| version = "0.9.0+wasi-snapshot-preview1" | ||||
|  | @ -2464,6 +2707,15 @@ dependencies = [ | |||
|  "winapi-build", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "yaml-rust" | ||||
| version = "0.4.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" | ||||
| dependencies = [ | ||||
|  "linked-hash-map 0.5.2", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "yasna" | ||||
| version = "0.3.1" | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ actix-webfinger = "0.3.0-alpha.3" | |||
| activitystreams = "0.5.0-alpha.11" | ||||
| base64 = "0.12" | ||||
| bb8-postgres = "0.4.0" | ||||
| config = "0.10.1" | ||||
| dotenv = "0.15.0" | ||||
| futures = "0.3.4" | ||||
| http-signature-normalization-actix = { version = "0.3.0-alpha.5", default-features = false, features = ["sha-2"] } | ||||
|  | @ -29,6 +30,7 @@ rsa-pem = { version = "0.1.0", git = "https://git.asonix.dog/Aardwolf/rsa-pem" } | |||
| serde = { version = "1.0", features = ["derive"] } | ||||
| serde_json = "1.0" | ||||
| sha2 = "0.8" | ||||
| structopt = "0.3.12" | ||||
| thiserror = "1.0" | ||||
| tokio = { version = "0.2.13", features = ["sync"] } | ||||
| ttl_cache = "0.5.1" | ||||
|  |  | |||
							
								
								
									
										48
									
								
								src/actor.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/actor.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| use crate::{ | ||||
|     apub::PublicKey, | ||||
|     config::{Config, UrlKind}, | ||||
|     error::MyError, | ||||
|     responses::ok, | ||||
|     state::State, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     actor::Application, context, endpoint::EndpointProperties, ext::Extensible, | ||||
|     object::properties::ObjectProperties, security, | ||||
| }; | ||||
| use actix_web::{web, Responder}; | ||||
| use rsa_pem::KeyExt; | ||||
| 
 | ||||
| pub async fn route( | ||||
|     state: web::Data<State>, | ||||
|     config: web::Data<Config>, | ||||
| ) -> Result<impl Responder, MyError> { | ||||
|     let mut application = Application::full(); | ||||
|     let mut endpoint = EndpointProperties::default(); | ||||
| 
 | ||||
|     endpoint.set_shared_inbox(config.generate_url(UrlKind::Inbox))?; | ||||
| 
 | ||||
|     let props: &mut ObjectProperties = application.as_mut(); | ||||
|     props | ||||
|         .set_id(config.generate_url(UrlKind::Actor))? | ||||
|         .set_summary_xsd_string("AodeRelay bot")? | ||||
|         .set_name_xsd_string("AodeRelay")? | ||||
|         .set_url_xsd_any_uri(config.generate_url(UrlKind::Actor))? | ||||
|         .set_many_context_xsd_any_uris(vec![context(), security()])?; | ||||
| 
 | ||||
|     application | ||||
|         .extension | ||||
|         .set_preferred_username("relay")? | ||||
|         .set_followers(config.generate_url(UrlKind::Followers))? | ||||
|         .set_following(config.generate_url(UrlKind::Following))? | ||||
|         .set_inbox(config.generate_url(UrlKind::Inbox))? | ||||
|         .set_outbox(config.generate_url(UrlKind::Outbox))? | ||||
|         .set_endpoints(endpoint)?; | ||||
| 
 | ||||
|     let public_key = PublicKey { | ||||
|         id: config.generate_url(UrlKind::MainKey).parse()?, | ||||
|         owner: config.generate_url(UrlKind::Actor).parse()?, | ||||
|         public_key_pem: state.public_key.to_pem_pkcs8()?, | ||||
|     }; | ||||
| 
 | ||||
|     Ok(ok(application.extend(public_key.to_ext()))) | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/args.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/args.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| use structopt::StructOpt; | ||||
| 
 | ||||
| #[derive(Debug, StructOpt)] | ||||
| #[structopt(name = "relay", about = "An activitypub relay")] | ||||
| pub struct Args { | ||||
|     #[structopt(short, help = "A list of domains that should be blocked")] | ||||
|     blocks: Vec<String>, | ||||
| 
 | ||||
|     #[structopt(short, help = "A list of domains that should be whitelisted")] | ||||
|     whitelists: Vec<String>, | ||||
| 
 | ||||
|     #[structopt(short, help = "Undo whitelisting or blocking these domains")] | ||||
|     undo: bool, | ||||
| } | ||||
| 
 | ||||
| impl Args { | ||||
|     pub fn new() -> Self { | ||||
|         Self::from_args() | ||||
|     } | ||||
| 
 | ||||
|     pub fn blocks(&self) -> &[String] { | ||||
|         &self.blocks | ||||
|     } | ||||
| 
 | ||||
|     pub fn whitelists(&self) -> &[String] { | ||||
|         &self.whitelists | ||||
|     } | ||||
| 
 | ||||
|     pub fn undo(&self) -> bool { | ||||
|         self.undo | ||||
|     } | ||||
| } | ||||
							
								
								
									
										111
									
								
								src/config.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/config.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | |||
| use crate::{error::MyError, requests::Requests, verifier::MyVerify}; | ||||
| use config::Environment; | ||||
| use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature}; | ||||
| use sha2::{Digest, Sha256}; | ||||
| use std::net::IpAddr; | ||||
| use uuid::Uuid; | ||||
| 
 | ||||
| #[derive(Clone, Debug, serde::Deserialize)] | ||||
| pub struct Config { | ||||
|     hostname: String, | ||||
|     addr: IpAddr, | ||||
|     port: u16, | ||||
|     debug: bool, | ||||
|     whitelist_mode: bool, | ||||
|     validate_signatures: bool, | ||||
|     https: bool, | ||||
|     database_url: String, | ||||
| } | ||||
| 
 | ||||
| pub enum UrlKind { | ||||
|     Activity, | ||||
|     Actor, | ||||
|     Followers, | ||||
|     Following, | ||||
|     Inbox, | ||||
|     MainKey, | ||||
|     NodeInfo, | ||||
|     Outbox, | ||||
| } | ||||
| 
 | ||||
| impl Config { | ||||
|     pub fn build() -> Result<Self, MyError> { | ||||
|         let mut config = config::Config::new(); | ||||
|         config | ||||
|             .set_default("hostname", "localhost:8080")? | ||||
|             .set_default("addr", "127.0.0.1")? | ||||
|             .set_default("port", 8080)? | ||||
|             .set_default("debug", true)? | ||||
|             .set_default("whitelist_mode", false)? | ||||
|             .set_default("validate_signatures", false)? | ||||
|             .set_default("https", false)? | ||||
|             .merge(Environment::new())?; | ||||
| 
 | ||||
|         Ok(config.try_into()?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn digest_middleware(&self) -> VerifyDigest<Sha256> { | ||||
|         if self.validate_signatures { | ||||
|             VerifyDigest::new(Sha256::new()) | ||||
|         } else { | ||||
|             VerifyDigest::new(Sha256::new()).optional() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn signature_middleware(&self, requests: Requests) -> VerifySignature<MyVerify> { | ||||
|         if self.validate_signatures { | ||||
|             VerifySignature::new(MyVerify(requests), Default::default()) | ||||
|         } else { | ||||
|             VerifySignature::new(MyVerify(requests), Default::default()).optional() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn bind_address(&self) -> (IpAddr, u16) { | ||||
|         (self.addr, self.port) | ||||
|     } | ||||
| 
 | ||||
|     pub fn debug(&self) -> bool { | ||||
|         self.debug | ||||
|     } | ||||
| 
 | ||||
|     pub fn whitelist_mode(&self) -> bool { | ||||
|         self.whitelist_mode | ||||
|     } | ||||
| 
 | ||||
|     pub fn database_url(&self) -> &str { | ||||
|         &self.database_url | ||||
|     } | ||||
| 
 | ||||
|     pub fn hostname(&self) -> &str { | ||||
|         &self.hostname | ||||
|     } | ||||
| 
 | ||||
|     pub fn generate_resource(&self) -> String { | ||||
|         format!("relay@{}", self.hostname) | ||||
|     } | ||||
| 
 | ||||
|     pub fn software_name(&self) -> String { | ||||
|         "AodeRelay".to_owned() | ||||
|     } | ||||
| 
 | ||||
|     pub fn software_version(&self) -> String { | ||||
|         "v0.1.0-master".to_owned() | ||||
|     } | ||||
| 
 | ||||
|     pub fn generate_url(&self, kind: UrlKind) -> String { | ||||
|         let scheme = if self.https { "https" } else { "http" }; | ||||
| 
 | ||||
|         match kind { | ||||
|             UrlKind::Activity => { | ||||
|                 format!("{}://{}/activity/{}", scheme, self.hostname, Uuid::new_v4()) | ||||
|             } | ||||
|             UrlKind::Actor => format!("{}://{}/actor", scheme, self.hostname), | ||||
|             UrlKind::Followers => format!("{}://{}/followers", scheme, self.hostname), | ||||
|             UrlKind::Following => format!("{}://{}/following", scheme, self.hostname), | ||||
|             UrlKind::Inbox => format!("{}://{}/inbox", scheme, self.hostname), | ||||
|             UrlKind::MainKey => format!("{}://{}/actor#main-key", scheme, self.hostname), | ||||
|             UrlKind::NodeInfo => format!("{}://{}/nodeinfo/2.0", scheme, self.hostname), | ||||
|             UrlKind::Outbox => format!("{}://{}/outbox", scheme, self.hostname), | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										114
									
								
								src/db.rs
									
										
									
									
									
								
							
							
						
						
									
										114
									
								
								src/db.rs
									
										
									
									
									
								
							|  | @ -2,7 +2,11 @@ use crate::error::MyError; | |||
| use activitystreams::primitives::XsdAnyUri; | ||||
| use bb8_postgres::{ | ||||
|     bb8, | ||||
|     tokio_postgres::{row::Row, Client, Config, NoTls}, | ||||
|     tokio_postgres::{ | ||||
|         error::{Error, SqlState}, | ||||
|         row::Row, | ||||
|         Client, Config, NoTls, | ||||
|     }, | ||||
|     PostgresConnectionManager, | ||||
| }; | ||||
| use log::{info, warn}; | ||||
|  | @ -43,6 +47,48 @@ impl Db { | |||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn add_blocks(&self, domains: &[String]) -> Result<(), MyError> { | ||||
|         let conn = self.pool.get().await?; | ||||
|         for domain in domains { | ||||
|             match add_block(&conn, domain.as_str()).await { | ||||
|                 Err(e) if e.code() != Some(&SqlState::UNIQUE_VIOLATION) => { | ||||
|                     Err(e)?; | ||||
|                 } | ||||
|                 _ => (), | ||||
|             }; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn remove_blocks(&self, domains: &[String]) -> Result<(), MyError> { | ||||
|         let conn = self.pool.get().await?; | ||||
|         for domain in domains { | ||||
|             remove_block(&conn, domain.as_str()).await? | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn add_whitelists(&self, domains: &[String]) -> Result<(), MyError> { | ||||
|         let conn = self.pool.get().await?; | ||||
|         for domain in domains { | ||||
|             match add_whitelist(&conn, domain.as_str()).await { | ||||
|                 Err(e) if e.code() != Some(&SqlState::UNIQUE_VIOLATION) => { | ||||
|                     Err(e)?; | ||||
|                 } | ||||
|                 _ => (), | ||||
|             }; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn remove_whitelists(&self, domains: &[String]) -> Result<(), MyError> { | ||||
|         let conn = self.pool.get().await?; | ||||
|         for domain in domains { | ||||
|             remove_whitelist(&conn, domain.as_str()).await? | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn hydrate_blocks(&self) -> Result<HashSet<String>, MyError> { | ||||
|         let conn = self.pool.get().await?; | ||||
| 
 | ||||
|  | @ -74,7 +120,7 @@ impl Db { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| pub async fn listen(client: &Client) -> Result<(), MyError> { | ||||
| pub async fn listen(client: &Client) -> Result<(), Error> { | ||||
|     info!("LISTEN new_blocks;"); | ||||
|     info!("LISTEN new_whitelists;"); | ||||
|     info!("LISTEN new_listeners;"); | ||||
|  | @ -117,49 +163,67 @@ async fn update_private_key(client: &Client, key: &RSAPrivateKey) -> Result<(), | |||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn add_block(client: &Client, block: &XsdAnyUri) -> Result<(), MyError> { | ||||
|     let host = if let Some(host) = block.as_url().host() { | ||||
|         host | ||||
|     } else { | ||||
|         return Err(MyError::Host(block.to_string())); | ||||
|     }; | ||||
| 
 | ||||
| async fn add_block(client: &Client, domain: &str) -> Result<(), Error> { | ||||
|     info!( | ||||
|         "INSERT INTO blocks (domain_name, created_at) VALUES ($1::TEXT, 'now'); [{}]", | ||||
|         host.to_string() | ||||
|         domain, | ||||
|     ); | ||||
|     client | ||||
|         .execute( | ||||
|             "INSERT INTO blocks (domain_name, created_at) VALUES ($1::TEXT, 'now');", | ||||
|             &[&host.to_string()], | ||||
|             &[&domain], | ||||
|         ) | ||||
|         .await?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn add_whitelist(client: &Client, whitelist: &XsdAnyUri) -> Result<(), MyError> { | ||||
|     let host = if let Some(host) = whitelist.as_url().host() { | ||||
|         host | ||||
|     } else { | ||||
|         return Err(MyError::Host(whitelist.to_string())); | ||||
|     }; | ||||
| async fn remove_block(client: &Client, domain: &str) -> Result<(), Error> { | ||||
|     info!( | ||||
|         "DELETE FROM blocks WHERE domain_name = $1::TEXT; [{}]", | ||||
|         domain, | ||||
|     ); | ||||
|     client | ||||
|         .execute( | ||||
|             "DELETE FROM blocks WHERE domain_name = $1::TEXT;", | ||||
|             &[&domain], | ||||
|         ) | ||||
|         .await?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn add_whitelist(client: &Client, domain: &str) -> Result<(), Error> { | ||||
|     info!( | ||||
|         "INSERT INTO whitelists (domain_name, created_at) VALUES ($1::TEXT, 'now'); [{}]", | ||||
|         host.to_string() | ||||
|         domain, | ||||
|     ); | ||||
|     client | ||||
|         .execute( | ||||
|             "INSERT INTO whitelists (domain_name, created_at) VALUES ($1::TEXT, 'now');", | ||||
|             &[&host.to_string()], | ||||
|             &[&domain], | ||||
|         ) | ||||
|         .await?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn remove_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), MyError> { | ||||
| async fn remove_whitelist(client: &Client, domain: &str) -> Result<(), Error> { | ||||
|     info!( | ||||
|         "DELETE FROM whitelists WHERE domain_name = $1::TEXT; [{}]", | ||||
|         domain, | ||||
|     ); | ||||
|     client | ||||
|         .execute( | ||||
|             "DELETE FROM whitelists WHERE domain_name = $1::TEXT;", | ||||
|             &[&domain], | ||||
|         ) | ||||
|         .await?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn remove_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), Error> { | ||||
|     info!( | ||||
|         "DELETE FROM listeners WHERE actor_id = {};", | ||||
|         listener.as_str() | ||||
|  | @ -174,7 +238,7 @@ async fn remove_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), My | |||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn add_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), MyError> { | ||||
| async fn add_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), Error> { | ||||
|     info!( | ||||
|         "INSERT INTO listeners (actor_id, created_at) VALUES ($1::TEXT, 'now'); [{}]", | ||||
|         listener.as_str(), | ||||
|  | @ -189,14 +253,14 @@ async fn add_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), MyErr | |||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn hydrate_blocks(client: &Client) -> Result<HashSet<String>, MyError> { | ||||
| async fn hydrate_blocks(client: &Client) -> Result<HashSet<String>, Error> { | ||||
|     info!("SELECT domain_name FROM blocks"); | ||||
|     let rows = client.query("SELECT domain_name FROM blocks", &[]).await?; | ||||
| 
 | ||||
|     parse_rows(rows) | ||||
| } | ||||
| 
 | ||||
| async fn hydrate_whitelists(client: &Client) -> Result<HashSet<String>, MyError> { | ||||
| async fn hydrate_whitelists(client: &Client) -> Result<HashSet<String>, Error> { | ||||
|     info!("SELECT domain_name FROM whitelists"); | ||||
|     let rows = client | ||||
|         .query("SELECT domain_name FROM whitelists", &[]) | ||||
|  | @ -205,14 +269,14 @@ async fn hydrate_whitelists(client: &Client) -> Result<HashSet<String>, MyError> | |||
|     parse_rows(rows) | ||||
| } | ||||
| 
 | ||||
| async fn hydrate_listeners(client: &Client) -> Result<HashSet<XsdAnyUri>, MyError> { | ||||
| async fn hydrate_listeners(client: &Client) -> Result<HashSet<XsdAnyUri>, Error> { | ||||
|     info!("SELECT actor_id FROM listeners"); | ||||
|     let rows = client.query("SELECT actor_id FROM listeners", &[]).await?; | ||||
| 
 | ||||
|     parse_rows(rows) | ||||
| } | ||||
| 
 | ||||
| fn parse_rows<T, E>(rows: Vec<Row>) -> Result<HashSet<T>, MyError> | ||||
| fn parse_rows<T, E>(rows: Vec<Row>) -> Result<HashSet<T>, Error> | ||||
| where | ||||
|     T: std::str::FromStr<Err = E> + Eq + std::hash::Hash, | ||||
|     E: std::fmt::Display, | ||||
|  |  | |||
							
								
								
									
										29
									
								
								src/error.rs
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								src/error.rs
									
										
									
									
									
								
							|  | @ -1,11 +1,18 @@ | |||
| use activitystreams::primitives::XsdAnyUriError; | ||||
| use actix_web::{error::ResponseError, http::StatusCode, HttpResponse}; | ||||
| use actix_web::{ | ||||
|     error::{BlockingError, ResponseError}, | ||||
|     http::StatusCode, | ||||
|     HttpResponse, | ||||
| }; | ||||
| use log::error; | ||||
| use rsa_pem::KeyError; | ||||
| use std::{convert::Infallible, io::Error}; | ||||
| use std::{convert::Infallible, fmt::Debug, io::Error}; | ||||
| 
 | ||||
| #[derive(Debug, thiserror::Error)] | ||||
| pub enum MyError { | ||||
|     #[error("Error in configuration, {0}")] | ||||
|     Config(#[from] config::ConfigError), | ||||
| 
 | ||||
|     #[error("Error in db, {0}")] | ||||
|     DbError(#[from] bb8_postgres::tokio_postgres::error::Error), | ||||
| 
 | ||||
|  | @ -51,9 +58,6 @@ pub enum MyError { | |||
|     #[error("Wrong ActivityPub kind, {0}")] | ||||
|     Kind(String), | ||||
| 
 | ||||
|     #[error("No host present in URI, {0}")] | ||||
|     Host(String), | ||||
| 
 | ||||
|     #[error("Too many CPUs, {0}")] | ||||
|     CpuCount(#[from] std::num::TryFromIntError), | ||||
| 
 | ||||
|  | @ -77,6 +81,9 @@ pub enum MyError { | |||
| 
 | ||||
|     #[error("URI is missing domain field")] | ||||
|     Domain, | ||||
| 
 | ||||
|     #[error("Blocking operation was canceled")] | ||||
|     Canceled, | ||||
| } | ||||
| 
 | ||||
| impl ResponseError for MyError { | ||||
|  | @ -102,6 +109,18 @@ impl ResponseError for MyError { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> From<BlockingError<T>> for MyError | ||||
| where | ||||
|     T: Into<MyError> + Debug, | ||||
| { | ||||
|     fn from(e: BlockingError<T>) -> Self { | ||||
|         match e { | ||||
|             BlockingError::Error(e) => e.into(), | ||||
|             BlockingError::Canceled => MyError::Canceled, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> From<bb8_postgres::bb8::RunError<T>> for MyError | ||||
| where | ||||
|     T: Into<MyError>, | ||||
|  |  | |||
							
								
								
									
										50
									
								
								src/inbox.rs
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								src/inbox.rs
									
										
									
									
									
								
							|  | @ -1,10 +1,11 @@ | |||
| use crate::{ | ||||
|     accepted, | ||||
|     apub::{AcceptedActors, AcceptedObjects, ValidTypes}, | ||||
|     config::{Config, UrlKind}, | ||||
|     db::Db, | ||||
|     error::MyError, | ||||
|     requests::Requests, | ||||
|     state::{State, UrlKind}, | ||||
|     responses::accepted, | ||||
|     state::State, | ||||
| }; | ||||
| use activitystreams::{ | ||||
|     activity::{Accept, Announce, Follow, Undo}, | ||||
|  | @ -22,6 +23,7 @@ use std::convert::TryInto; | |||
| pub async fn inbox( | ||||
|     db: web::Data<Db>, | ||||
|     state: web::Data<State>, | ||||
|     config: web::Data<Config>, | ||||
|     client: web::Data<Requests>, | ||||
|     input: web::Json<AcceptedObjects>, | ||||
|     verified: SignatureVerified, | ||||
|  | @ -58,19 +60,20 @@ pub async fn inbox( | |||
| 
 | ||||
|     match input.kind { | ||||
|         ValidTypes::Announce | ValidTypes::Create => { | ||||
|             handle_announce(&state, &client, input, actor).await | ||||
|             handle_announce(&state, &config, &client, input, actor).await | ||||
|         } | ||||
|         ValidTypes::Follow => handle_follow(&db, &state, &client, input, actor, is_listener).await, | ||||
|         ValidTypes::Follow => handle_follow(&db, &config, &client, input, actor, is_listener).await, | ||||
|         ValidTypes::Delete | ValidTypes::Update => { | ||||
|             handle_forward(&state, &client, input, actor).await | ||||
|         } | ||||
|         ValidTypes::Undo => handle_undo(&db, &state, &client, input, actor).await, | ||||
|         ValidTypes::Undo => handle_undo(&db, &state, &config, &client, input, actor).await, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| async fn handle_undo( | ||||
|     db: &Db, | ||||
|     state: &State, | ||||
|     config: &Config, | ||||
|     client: &Requests, | ||||
|     input: AcceptedObjects, | ||||
|     actor: AcceptedActors, | ||||
|  | @ -88,7 +91,7 @@ async fn handle_undo( | |||
|         return handle_forward(state, client, input, actor).await; | ||||
|     } | ||||
| 
 | ||||
|     let my_id: XsdAnyUri = state.generate_url(UrlKind::Actor).parse()?; | ||||
|     let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor).parse()?; | ||||
| 
 | ||||
|     if !input.object.child_object_is(&my_id) && !input.object.child_object_is(&public()) { | ||||
|         return Err(MyError::WrongActor(input.object.id().to_string())); | ||||
|  | @ -97,7 +100,7 @@ async fn handle_undo( | |||
|     let inbox = actor.inbox().to_owned(); | ||||
|     db.remove_listener(inbox).await?; | ||||
| 
 | ||||
|     let undo = generate_undo_follow(state, &actor.id, &my_id)?; | ||||
|     let undo = generate_undo_follow(config, &actor.id, &my_id)?; | ||||
| 
 | ||||
|     let client2 = client.clone(); | ||||
|     let inbox = actor.inbox().clone(); | ||||
|  | @ -125,6 +128,7 @@ async fn handle_forward( | |||
| 
 | ||||
| async fn handle_announce( | ||||
|     state: &State, | ||||
|     config: &Config, | ||||
|     client: &Requests, | ||||
|     input: AcceptedObjects, | ||||
|     actor: AcceptedActors, | ||||
|  | @ -135,9 +139,9 @@ async fn handle_announce( | |||
|         return Err(MyError::Duplicate); | ||||
|     } | ||||
| 
 | ||||
|     let activity_id: XsdAnyUri = state.generate_url(UrlKind::Activity).parse()?; | ||||
|     let activity_id: XsdAnyUri = config.generate_url(UrlKind::Activity).parse()?; | ||||
| 
 | ||||
|     let announce = generate_announce(state, &activity_id, object_id)?; | ||||
|     let announce = generate_announce(config, &activity_id, object_id)?; | ||||
|     let inboxes = get_inboxes(state, &actor, &object_id).await?; | ||||
|     client.deliver_many(inboxes, announce.clone()); | ||||
| 
 | ||||
|  | @ -148,13 +152,13 @@ async fn handle_announce( | |||
| 
 | ||||
| async fn handle_follow( | ||||
|     db: &Db, | ||||
|     state: &State, | ||||
|     config: &Config, | ||||
|     client: &Requests, | ||||
|     input: AcceptedObjects, | ||||
|     actor: AcceptedActors, | ||||
|     is_listener: bool, | ||||
| ) -> Result<HttpResponse, MyError> { | ||||
|     let my_id: XsdAnyUri = state.generate_url(UrlKind::Actor).parse()?; | ||||
|     let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor).parse()?; | ||||
| 
 | ||||
|     if !input.object.is(&my_id) && !input.object.is(&public()) { | ||||
|         return Err(MyError::WrongActor(input.object.id().to_string())); | ||||
|  | @ -166,7 +170,7 @@ async fn handle_follow( | |||
| 
 | ||||
|         // if following relay directly, not just following 'public', followback
 | ||||
|         if input.object.is(&my_id) { | ||||
|             let follow = generate_follow(state, &actor.id, &my_id)?; | ||||
|             let follow = generate_follow(config, &actor.id, &my_id)?; | ||||
|             let client2 = client.clone(); | ||||
|             let inbox = actor.inbox().clone(); | ||||
|             let follow2 = follow.clone(); | ||||
|  | @ -176,7 +180,7 @@ async fn handle_follow( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let accept = generate_accept_follow(state, &actor.id, &input.id, &my_id)?; | ||||
|     let accept = generate_accept_follow(config, &actor.id, &input.id, &my_id)?; | ||||
| 
 | ||||
|     let client2 = client.clone(); | ||||
|     let inbox = actor.inbox().clone(); | ||||
|  | @ -190,7 +194,7 @@ async fn handle_follow( | |||
| 
 | ||||
| // Generate a type that says "I want to stop following you"
 | ||||
| fn generate_undo_follow( | ||||
|     state: &State, | ||||
|     config: &Config, | ||||
|     actor_id: &XsdAnyUri, | ||||
|     my_id: &XsdAnyUri, | ||||
| ) -> Result<Undo, MyError> { | ||||
|  | @ -203,7 +207,7 @@ fn generate_undo_follow( | |||
| 
 | ||||
|             follow | ||||
|                 .object_props | ||||
|                 .set_id(state.generate_url(UrlKind::Activity))?; | ||||
|                 .set_id(config.generate_url(UrlKind::Activity))?; | ||||
|             follow | ||||
|                 .follow_props | ||||
|                 .set_actor_xsd_any_uri(actor_id.clone())? | ||||
|  | @ -212,12 +216,12 @@ fn generate_undo_follow( | |||
|             follow | ||||
|         })?; | ||||
| 
 | ||||
|     prepare_activity(undo, state.generate_url(UrlKind::Actor), actor_id.clone()) | ||||
|     prepare_activity(undo, config.generate_url(UrlKind::Actor), actor_id.clone()) | ||||
| } | ||||
| 
 | ||||
| // Generate a type that says "Look at this object"
 | ||||
| fn generate_announce( | ||||
|     state: &State, | ||||
|     config: &Config, | ||||
|     activity_id: &XsdAnyUri, | ||||
|     object_id: &XsdAnyUri, | ||||
| ) -> Result<Announce, MyError> { | ||||
|  | @ -226,18 +230,18 @@ fn generate_announce( | |||
|     announce | ||||
|         .announce_props | ||||
|         .set_object_xsd_any_uri(object_id.clone())? | ||||
|         .set_actor_xsd_any_uri(state.generate_url(UrlKind::Actor))?; | ||||
|         .set_actor_xsd_any_uri(config.generate_url(UrlKind::Actor))?; | ||||
| 
 | ||||
|     prepare_activity( | ||||
|         announce, | ||||
|         activity_id.clone(), | ||||
|         state.generate_url(UrlKind::Followers), | ||||
|         config.generate_url(UrlKind::Followers), | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| // Generate a type that says "I want to follow you"
 | ||||
| fn generate_follow( | ||||
|     state: &State, | ||||
|     config: &Config, | ||||
|     actor_id: &XsdAnyUri, | ||||
|     my_id: &XsdAnyUri, | ||||
| ) -> Result<Follow, MyError> { | ||||
|  | @ -250,14 +254,14 @@ fn generate_follow( | |||
| 
 | ||||
|     prepare_activity( | ||||
|         follow, | ||||
|         state.generate_url(UrlKind::Activity), | ||||
|         config.generate_url(UrlKind::Activity), | ||||
|         actor_id.clone(), | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| // Generate a type that says "I accept your follow request"
 | ||||
| fn generate_accept_follow( | ||||
|     state: &State, | ||||
|     config: &Config, | ||||
|     actor_id: &XsdAnyUri, | ||||
|     input_id: &XsdAnyUri, | ||||
|     my_id: &XsdAnyUri, | ||||
|  | @ -281,7 +285,7 @@ fn generate_accept_follow( | |||
| 
 | ||||
|     prepare_activity( | ||||
|         accept, | ||||
|         state.generate_url(UrlKind::Activity), | ||||
|         config.generate_url(UrlKind::Activity), | ||||
|         actor_id.clone(), | ||||
|     ) | ||||
| } | ||||
|  |  | |||
							
								
								
									
										117
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										117
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -1,122 +1,77 @@ | |||
| use activitystreams::{ | ||||
|     actor::Application, context, endpoint::EndpointProperties, ext::Extensible, | ||||
|     object::properties::ObjectProperties, security, | ||||
| }; | ||||
| use actix_web::{middleware::Logger, web, App, HttpResponse, HttpServer, Responder}; | ||||
| use actix_web::{middleware::Logger, web, App, HttpServer, Responder}; | ||||
| use bb8_postgres::tokio_postgres; | ||||
| use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature}; | ||||
| use rsa_pem::KeyExt; | ||||
| use sha2::{Digest, Sha256}; | ||||
| 
 | ||||
| mod actor; | ||||
| mod apub; | ||||
| mod args; | ||||
| mod config; | ||||
| mod db; | ||||
| mod error; | ||||
| mod inbox; | ||||
| mod nodeinfo; | ||||
| mod notify; | ||||
| mod requests; | ||||
| mod responses; | ||||
| mod state; | ||||
| mod verifier; | ||||
| mod webfinger; | ||||
| 
 | ||||
| use self::{ | ||||
|     apub::PublicKey, | ||||
|     db::Db, | ||||
|     error::MyError, | ||||
|     state::{State, UrlKind}, | ||||
|     verifier::MyVerify, | ||||
|     webfinger::RelayResolver, | ||||
| }; | ||||
| 
 | ||||
| pub fn ok<T>(item: T) -> HttpResponse | ||||
| where | ||||
|     T: serde::ser::Serialize, | ||||
| { | ||||
|     HttpResponse::Ok() | ||||
|         .content_type("application/activity+json") | ||||
|         .json(item) | ||||
| } | ||||
| 
 | ||||
| pub fn accepted<T>(item: T) -> HttpResponse | ||||
| where | ||||
|     T: serde::ser::Serialize, | ||||
| { | ||||
|     HttpResponse::Accepted() | ||||
|         .content_type("application/activity+json") | ||||
|         .json(item) | ||||
| } | ||||
| use self::{args::Args, config::Config, db::Db, state::State, webfinger::RelayResolver}; | ||||
| 
 | ||||
| async fn index() -> impl Responder { | ||||
|     "hewwo, mr obama" | ||||
| } | ||||
| 
 | ||||
| async fn actor_route(state: web::Data<State>) -> Result<impl Responder, MyError> { | ||||
|     let mut application = Application::full(); | ||||
|     let mut endpoint = EndpointProperties::default(); | ||||
| 
 | ||||
|     endpoint.set_shared_inbox(state.generate_url(UrlKind::Inbox))?; | ||||
| 
 | ||||
|     let props: &mut ObjectProperties = application.as_mut(); | ||||
|     props | ||||
|         .set_id(state.generate_url(UrlKind::Actor))? | ||||
|         .set_summary_xsd_string("AodeRelay bot")? | ||||
|         .set_name_xsd_string("AodeRelay")? | ||||
|         .set_url_xsd_any_uri(state.generate_url(UrlKind::Actor))? | ||||
|         .set_many_context_xsd_any_uris(vec![context(), security()])?; | ||||
| 
 | ||||
|     application | ||||
|         .extension | ||||
|         .set_preferred_username("relay")? | ||||
|         .set_followers(state.generate_url(UrlKind::Followers))? | ||||
|         .set_following(state.generate_url(UrlKind::Following))? | ||||
|         .set_inbox(state.generate_url(UrlKind::Inbox))? | ||||
|         .set_outbox(state.generate_url(UrlKind::Outbox))? | ||||
|         .set_endpoints(endpoint)?; | ||||
| 
 | ||||
|     let public_key = PublicKey { | ||||
|         id: state.generate_url(UrlKind::MainKey).parse()?, | ||||
|         owner: state.generate_url(UrlKind::Actor).parse()?, | ||||
|         public_key_pem: state.settings.public_key.to_pem_pkcs8()?, | ||||
|     }; | ||||
| 
 | ||||
|     Ok(ok(application.extend(public_key.to_ext()))) | ||||
| } | ||||
| 
 | ||||
| #[actix_rt::main] | ||||
| async fn main() -> Result<(), anyhow::Error> { | ||||
|     dotenv::dotenv().ok(); | ||||
| 
 | ||||
|     let config = Config::build()?; | ||||
| 
 | ||||
|     if config.debug() { | ||||
|         std::env::set_var("RUST_LOG", "debug") | ||||
|     } else { | ||||
|         std::env::set_var("RUST_LOG", "info") | ||||
|     } | ||||
| 
 | ||||
|     pretty_env_logger::init(); | ||||
| 
 | ||||
|     let pg_config: tokio_postgres::Config = std::env::var("DATABASE_URL")?.parse()?; | ||||
|     let hostname: String = std::env::var("HOSTNAME")?; | ||||
|     let use_whitelist = std::env::var("USE_WHITELIST").is_ok(); | ||||
|     let use_https = std::env::var("USE_HTTPS").is_ok(); | ||||
| 
 | ||||
|     let pg_config: tokio_postgres::Config = config.database_url().parse()?; | ||||
|     let db = Db::build(pg_config.clone()).await?; | ||||
| 
 | ||||
|     let state = State::hydrate(use_https, use_whitelist, hostname, &db).await?; | ||||
|     let args = Args::new(); | ||||
| 
 | ||||
|     if !args.blocks().is_empty() || !args.whitelists().is_empty() { | ||||
|         if args.undo() { | ||||
|             db.remove_blocks(args.blocks()).await?; | ||||
|             db.remove_whitelists(args.whitelists()).await?; | ||||
|         } else { | ||||
|             db.add_blocks(args.blocks()).await?; | ||||
|             db.add_whitelists(args.whitelists()).await?; | ||||
|         } | ||||
|         return Ok(()); | ||||
|     } | ||||
| 
 | ||||
|     let state = State::hydrate(config.clone(), &db).await?; | ||||
| 
 | ||||
|     let _ = notify::NotifyHandler::start_handler(state.clone(), pg_config.clone()); | ||||
| 
 | ||||
|     let bind_address = config.bind_address(); | ||||
|     HttpServer::new(move || { | ||||
|         let state = state.clone(); | ||||
| 
 | ||||
|         App::new() | ||||
|             .wrap(Logger::default()) | ||||
|             .data(db.clone()) | ||||
|             .data(state.clone()) | ||||
|             .data(state.requests()) | ||||
|             .data(config.clone()) | ||||
|             .service(web::resource("/").route(web::get().to(index))) | ||||
|             .service( | ||||
|                 web::resource("/inbox") | ||||
|                     .wrap(VerifyDigest::new(Sha256::new())) | ||||
|                     .wrap(VerifySignature::new( | ||||
|                         MyVerify(state.requests()), | ||||
|                         Default::default(), | ||||
|                     )) | ||||
|                     .wrap(config.digest_middleware()) | ||||
|                     .wrap(config.signature_middleware(state.requests())) | ||||
|                     .route(web::post().to(inbox::inbox)), | ||||
|             ) | ||||
|             .service(web::resource("/actor").route(web::get().to(actor_route))) | ||||
|             .service(web::resource("/actor").route(web::get().to(actor::route))) | ||||
|             .service(web::resource("/nodeinfo/2.0").route(web::get().to(nodeinfo::route))) | ||||
|             .service( | ||||
|                 web::scope("/.well-known") | ||||
|  | @ -124,7 +79,7 @@ async fn main() -> Result<(), anyhow::Error> { | |||
|                     .service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))), | ||||
|             ) | ||||
|     }) | ||||
|     .bind("0.0.0.0:8080")? | ||||
|     .bind(bind_address)? | ||||
|     .run() | ||||
|     .await?; | ||||
|     Ok(()) | ||||
|  |  | |||
|  | @ -1,24 +1,24 @@ | |||
| use crate::state::{State, UrlKind}; | ||||
| use crate::config::{Config, UrlKind}; | ||||
| use actix_web::{web, Responder}; | ||||
| use actix_webfinger::Link; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| pub async fn well_known(state: web::Data<State>) -> impl Responder { | ||||
| pub async fn well_known(config: web::Data<Config>) -> impl Responder { | ||||
|     web::Json(Link { | ||||
|         rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_owned(), | ||||
|         href: Some(state.generate_url(UrlKind::NodeInfo)), | ||||
|         href: Some(config.generate_url(UrlKind::NodeInfo)), | ||||
|         template: None, | ||||
|         kind: None, | ||||
|     }) | ||||
|     .with_header("Content-Type", "application/jrd+json") | ||||
| } | ||||
| 
 | ||||
| pub async fn route(state: web::Data<State>) -> web::Json<NodeInfo> { | ||||
| pub async fn route(config: web::Data<Config>) -> web::Json<NodeInfo> { | ||||
|     web::Json(NodeInfo { | ||||
|         version: NodeInfoVersion, | ||||
|         software: Software { | ||||
|             name: state.software_name(), | ||||
|             version: state.software_version(), | ||||
|             name: config.software_name(), | ||||
|             version: config.software_version(), | ||||
|         }, | ||||
|         protocols: vec![Protocol::ActivityPub], | ||||
|         services: vec![], | ||||
|  |  | |||
							
								
								
									
										20
									
								
								src/responses.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/responses.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| use actix_web::HttpResponse; | ||||
| use serde::ser::Serialize; | ||||
| 
 | ||||
| static CONTENT_TYPE: &str = "application/activity+json"; | ||||
| 
 | ||||
| pub fn ok<T>(item: T) -> HttpResponse | ||||
| where | ||||
|     T: Serialize, | ||||
| { | ||||
|     HttpResponse::Ok().content_type(CONTENT_TYPE).json(item) | ||||
| } | ||||
| 
 | ||||
| pub fn accepted<T>(item: T) -> HttpResponse | ||||
| where | ||||
|     T: Serialize, | ||||
| { | ||||
|     HttpResponse::Accepted() | ||||
|         .content_type(CONTENT_TYPE) | ||||
|         .json(item) | ||||
| } | ||||
							
								
								
									
										155
									
								
								src/state.rs
									
										
									
									
									
								
							
							
						
						
									
										155
									
								
								src/state.rs
									
										
									
									
									
								
							|  | @ -1,5 +1,12 @@ | |||
| use crate::{apub::AcceptedActors, db::Db, error::MyError, requests::Requests}; | ||||
| use crate::{ | ||||
|     apub::AcceptedActors, | ||||
|     config::{Config, UrlKind}, | ||||
|     db::Db, | ||||
|     error::MyError, | ||||
|     requests::Requests, | ||||
| }; | ||||
| use activitystreams::primitives::XsdAnyUri; | ||||
| use actix_web::web; | ||||
| use futures::try_join; | ||||
| use log::info; | ||||
| use lru::LruCache; | ||||
|  | @ -8,13 +15,14 @@ use rsa::{RSAPrivateKey, RSAPublicKey}; | |||
| use std::{collections::HashSet, sync::Arc}; | ||||
| use tokio::sync::RwLock; | ||||
| use ttl_cache::TtlCache; | ||||
| use uuid::Uuid; | ||||
| 
 | ||||
| pub type ActorCache = Arc<RwLock<TtlCache<XsdAnyUri, AcceptedActors>>>; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct State { | ||||
|     pub settings: Settings, | ||||
|     pub public_key: RSAPublicKey, | ||||
|     private_key: RSAPrivateKey, | ||||
|     config: Config, | ||||
|     actor_cache: ActorCache, | ||||
|     actor_id_cache: Arc<RwLock<LruCache<XsdAnyUri, XsdAnyUri>>>, | ||||
|     blocks: Arc<RwLock<HashSet<String>>>, | ||||
|  | @ -22,112 +30,20 @@ pub struct State { | |||
|     listeners: Arc<RwLock<HashSet<XsdAnyUri>>>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct Settings { | ||||
|     pub use_https: bool, | ||||
|     pub whitelist_enabled: bool, | ||||
|     pub hostname: String, | ||||
|     pub public_key: RSAPublicKey, | ||||
|     private_key: RSAPrivateKey, | ||||
| } | ||||
| 
 | ||||
| pub enum UrlKind { | ||||
|     Activity, | ||||
|     Actor, | ||||
|     Followers, | ||||
|     Following, | ||||
|     Inbox, | ||||
|     MainKey, | ||||
|     NodeInfo, | ||||
|     Outbox, | ||||
| } | ||||
| 
 | ||||
| impl Settings { | ||||
|     async fn hydrate( | ||||
|         db: &Db, | ||||
|         use_https: bool, | ||||
|         whitelist_enabled: bool, | ||||
|         hostname: String, | ||||
|     ) -> Result<Self, MyError> { | ||||
|         let private_key = if let Some(key) = db.hydrate_private_key().await? { | ||||
|             key | ||||
|         } else { | ||||
|             info!("Generating new keys"); | ||||
|             let mut rng = thread_rng(); | ||||
|             let key = RSAPrivateKey::new(&mut rng, 4096)?; | ||||
| 
 | ||||
|             db.update_private_key(&key).await?; | ||||
| 
 | ||||
|             key | ||||
|         }; | ||||
| 
 | ||||
|         let public_key = private_key.to_public_key(); | ||||
| 
 | ||||
|         Ok(Settings { | ||||
|             use_https, | ||||
|             whitelist_enabled, | ||||
|             hostname, | ||||
|             private_key, | ||||
|             public_key, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn generate_url(&self, kind: UrlKind) -> String { | ||||
|         let scheme = if self.use_https { "https" } else { "http" }; | ||||
| 
 | ||||
|         match kind { | ||||
|             UrlKind::Activity => { | ||||
|                 format!("{}://{}/activity/{}", scheme, self.hostname, Uuid::new_v4()) | ||||
|             } | ||||
|             UrlKind::Actor => format!("{}://{}/actor", scheme, self.hostname), | ||||
|             UrlKind::Followers => format!("{}://{}/followers", scheme, self.hostname), | ||||
|             UrlKind::Following => format!("{}://{}/following", scheme, self.hostname), | ||||
|             UrlKind::Inbox => format!("{}://{}/inbox", scheme, self.hostname), | ||||
|             UrlKind::MainKey => format!("{}://{}/actor#main-key", scheme, self.hostname), | ||||
|             UrlKind::NodeInfo => format!("{}://{}/nodeinfo/2.0", scheme, self.hostname), | ||||
|             UrlKind::Outbox => format!("{}://{}/outbox", scheme, self.hostname), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn generate_resource(&self) -> String { | ||||
|         format!("relay@{}", self.hostname) | ||||
|     } | ||||
| 
 | ||||
|     fn software_name(&self) -> String { | ||||
|         "AodeRelay".to_owned() | ||||
|     } | ||||
| 
 | ||||
|     fn software_version(&self) -> String { | ||||
|         "v0.1.0-master".to_owned() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl State { | ||||
|     pub fn software_name(&self) -> String { | ||||
|         self.settings.software_name() | ||||
|     } | ||||
| 
 | ||||
|     pub fn software_version(&self) -> String { | ||||
|         self.settings.software_version() | ||||
|     } | ||||
| 
 | ||||
|     pub fn requests(&self) -> Requests { | ||||
|         Requests::new( | ||||
|             self.generate_url(UrlKind::MainKey), | ||||
|             self.settings.private_key.clone(), | ||||
|             self.config.generate_url(UrlKind::MainKey), | ||||
|             self.private_key.clone(), | ||||
|             self.actor_cache.clone(), | ||||
|             format!("{} {}", self.software_name(), self.software_version()), | ||||
|             format!( | ||||
|                 "{} {}", | ||||
|                 self.config.software_name(), | ||||
|                 self.config.software_version() | ||||
|             ), | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     pub fn generate_url(&self, kind: UrlKind) -> String { | ||||
|         self.settings.generate_url(kind) | ||||
|     } | ||||
| 
 | ||||
|     pub fn generate_resource(&self) -> String { | ||||
|         self.settings.generate_resource() | ||||
|     } | ||||
| 
 | ||||
|     pub async fn bust_whitelist(&self, whitelist: &str) { | ||||
|         let hs = self.whitelists.clone(); | ||||
| 
 | ||||
|  | @ -169,7 +85,7 @@ impl State { | |||
|     } | ||||
| 
 | ||||
|     pub async fn is_whitelisted(&self, actor_id: &XsdAnyUri) -> bool { | ||||
|         if !self.settings.whitelist_enabled { | ||||
|         if !self.config.whitelist_mode() { | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|  | @ -236,21 +152,36 @@ impl State { | |||
|         write_guard.insert(listener); | ||||
|     } | ||||
| 
 | ||||
|     pub async fn hydrate( | ||||
|         use_https: bool, | ||||
|         whitelist_enabled: bool, | ||||
|         hostname: String, | ||||
|         db: &Db, | ||||
|     ) -> Result<Self, MyError> { | ||||
|     pub async fn hydrate(config: Config, db: &Db) -> Result<Self, MyError> { | ||||
|         let f1 = db.hydrate_blocks(); | ||||
|         let f2 = db.hydrate_whitelists(); | ||||
|         let f3 = db.hydrate_listeners(); | ||||
|         let f4 = Settings::hydrate(db, use_https, whitelist_enabled, hostname); | ||||
| 
 | ||||
|         let (blocks, whitelists, listeners, settings) = try_join!(f1, f2, f3, f4)?; | ||||
|         let f4 = async move { | ||||
|             if let Some(key) = db.hydrate_private_key().await? { | ||||
|                 Ok(key) | ||||
|             } else { | ||||
|                 info!("Generating new keys"); | ||||
|                 let key = web::block(move || { | ||||
|                     let mut rng = thread_rng(); | ||||
|                     RSAPrivateKey::new(&mut rng, 4096) | ||||
|                 }) | ||||
|                 .await?; | ||||
| 
 | ||||
|                 db.update_private_key(&key).await?; | ||||
| 
 | ||||
|                 Ok(key) | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         let (blocks, whitelists, listeners, private_key) = try_join!(f1, f2, f3, f4)?; | ||||
| 
 | ||||
|         let public_key = private_key.to_public_key(); | ||||
| 
 | ||||
|         Ok(State { | ||||
|             settings, | ||||
|             public_key, | ||||
|             private_key, | ||||
|             config, | ||||
|             actor_cache: Arc::new(RwLock::new(TtlCache::new(1024 * 8))), | ||||
|             actor_id_cache: Arc::new(RwLock::new(LruCache::new(1024 * 8))), | ||||
|             blocks: Arc::new(RwLock::new(blocks)), | ||||
|  |  | |||
|  | @ -1,4 +1,7 @@ | |||
| use crate::state::{State, UrlKind}; | ||||
| use crate::{ | ||||
|     config::{Config, UrlKind}, | ||||
|     state::State, | ||||
| }; | ||||
| use activitystreams::context; | ||||
| use actix_web::web::Data; | ||||
| use actix_webfinger::{Link, Resolver, Webfinger}; | ||||
|  | @ -11,19 +14,19 @@ pub struct RelayResolver; | |||
| #[error("Error resolving webfinger data")] | ||||
| pub struct RelayError; | ||||
| 
 | ||||
| impl Resolver<Data<State>> for RelayResolver { | ||||
| impl Resolver<(Data<State>, Data<Config>)> for RelayResolver { | ||||
|     type Error = RelayError; | ||||
| 
 | ||||
|     fn find( | ||||
|         account: &str, | ||||
|         domain: &str, | ||||
|         state: Data<State>, | ||||
|         (state, config): (Data<State>, Data<Config>), | ||||
|     ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> { | ||||
|         let domain = domain.to_owned(); | ||||
|         let account = account.to_owned(); | ||||
| 
 | ||||
|         let fut = async move { | ||||
|             if domain != state.settings.hostname { | ||||
|             if domain != config.hostname() { | ||||
|                 return Ok(None); | ||||
|             } | ||||
| 
 | ||||
|  | @ -31,13 +34,13 @@ impl Resolver<Data<State>> for RelayResolver { | |||
|                 return Ok(None); | ||||
|             } | ||||
| 
 | ||||
|             let mut wf = Webfinger::new(&state.generate_resource()); | ||||
|             wf.add_alias(&state.generate_url(UrlKind::Actor)) | ||||
|                 .add_activitypub(&state.generate_url(UrlKind::Actor)) | ||||
|                 .add_magic_public_key(&state.settings.public_key.as_magic_public_key()) | ||||
|             let mut wf = Webfinger::new(&config.generate_resource()); | ||||
|             wf.add_alias(&config.generate_url(UrlKind::Actor)) | ||||
|                 .add_activitypub(&config.generate_url(UrlKind::Actor)) | ||||
|                 .add_magic_public_key(&state.public_key.as_magic_public_key()) | ||||
|                 .add_link(Link { | ||||
|                     rel: "self".to_owned(), | ||||
|                     href: Some(state.generate_url(UrlKind::Actor)), | ||||
|                     href: Some(config.generate_url(UrlKind::Actor)), | ||||
|                     template: None, | ||||
|                     kind: Some(format!("application/ld+json; profile=\"{}\"", context())), | ||||
|                 }); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue