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 | 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", |  "activitystreams-derive", | ||||||
|  "chrono", |  "chrono", | ||||||
|  "mime", |  "mime", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "thiserror", |  "thiserror", | ||||||
|  "url", |  "url", | ||||||
|  | @ -127,7 +127,7 @@ dependencies = [ | ||||||
|  "pin-project", |  "pin-project", | ||||||
|  "rand", |  "rand", | ||||||
|  "regex", |  "regex", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "serde_urlencoded", |  "serde_urlencoded", | ||||||
|  "sha-1", |  "sha-1", | ||||||
|  | @ -155,7 +155,7 @@ dependencies = [ | ||||||
|  "http", |  "http", | ||||||
|  "log", |  "log", | ||||||
|  "regex", |  "regex", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
|  | @ -298,7 +298,7 @@ dependencies = [ | ||||||
|  "pin-project", |  "pin-project", | ||||||
|  "regex", |  "regex", | ||||||
|  "rustls", |  "rustls", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "serde_urlencoded", |  "serde_urlencoded", | ||||||
|  "time 0.2.9", |  "time 0.2.9", | ||||||
|  | @ -324,7 +324,7 @@ checksum = "120ce509b4ad2a0dedfbaebc1c1fb2b5e7bb34430a851c3eb264a704135e30a7" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "actix-http", |  "actix-http", | ||||||
|  "actix-web", |  "actix-web", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_derive", |  "serde_derive", | ||||||
|  "thiserror", |  "thiserror", | ||||||
| ] | ] | ||||||
|  | @ -364,6 +364,15 @@ dependencies = [ | ||||||
|  "memchr", |  "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]] | [[package]] | ||||||
| name = "anyhow" | name = "anyhow" | ||||||
| version = "1.0.27" | version = "1.0.27" | ||||||
|  | @ -382,6 +391,7 @@ dependencies = [ | ||||||
|  "anyhow", |  "anyhow", | ||||||
|  "base64 0.12.0", |  "base64 0.12.0", | ||||||
|  "bb8-postgres", |  "bb8-postgres", | ||||||
|  |  "config", | ||||||
|  "dotenv", |  "dotenv", | ||||||
|  "futures", |  "futures", | ||||||
|  "http-signature-normalization-actix", |  "http-signature-normalization-actix", | ||||||
|  | @ -393,9 +403,10 @@ dependencies = [ | ||||||
|  "rsa", |  "rsa", | ||||||
|  "rsa-magic-public-key", |  "rsa-magic-public-key", | ||||||
|  "rsa-pem", |  "rsa-pem", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "sha2", |  "sha2", | ||||||
|  |  "structopt", | ||||||
|  "thiserror", |  "thiserror", | ||||||
|  "tokio", |  "tokio", | ||||||
|  "ttl_cache", |  "ttl_cache", | ||||||
|  | @ -408,6 +419,15 @@ version = "0.4.5" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825" | checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "arrayvec" | ||||||
|  | version = "0.4.12" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" | ||||||
|  | dependencies = [ | ||||||
|  |  "nodrop", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "async-trait" | name = "async-trait" | ||||||
| version = "0.1.24" | version = "0.1.24" | ||||||
|  | @ -461,7 +481,7 @@ dependencies = [ | ||||||
|  "percent-encoding", |  "percent-encoding", | ||||||
|  "rand", |  "rand", | ||||||
|  "rustls", |  "rustls", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "serde_urlencoded", |  "serde_urlencoded", | ||||||
| ] | ] | ||||||
|  | @ -635,10 +655,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" | checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "num-integer", |  "num-integer", | ||||||
|  "num-traits", |  "num-traits 0.2.11", | ||||||
|  "time 0.1.42", |  "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]] | [[package]] | ||||||
| name = "cloudabi" | name = "cloudabi" | ||||||
| version = "0.0.3" | version = "0.0.3" | ||||||
|  | @ -648,6 +683,22 @@ dependencies = [ | ||||||
|  "bitflags", |  "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]] | [[package]] | ||||||
| name = "const-random" | name = "const-random" | ||||||
| version = "0.1.8" | version = "0.1.8" | ||||||
|  | @ -1183,6 +1234,19 @@ dependencies = [ | ||||||
|  "spin", |  "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]] | [[package]] | ||||||
| name = "libc" | name = "libc" | ||||||
| version = "0.2.68" | version = "0.2.68" | ||||||
|  | @ -1195,6 +1259,16 @@ version = "0.2.1" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" | 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]] | [[package]] | ||||||
| name = "linked-hash-map" | name = "linked-hash-map" | ||||||
| version = "0.5.2" | version = "0.5.2" | ||||||
|  | @ -1234,7 +1308,7 @@ version = "0.1.2" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" | checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "linked-hash-map", |  "linked-hash-map 0.5.2", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
|  | @ -1335,6 +1409,23 @@ dependencies = [ | ||||||
|  "winapi 0.3.8", |  "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]] | [[package]] | ||||||
| name = "num-bigint" | name = "num-bigint" | ||||||
| version = "0.2.6" | version = "0.2.6" | ||||||
|  | @ -1343,7 +1434,7 @@ checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "autocfg 1.0.0", |  "autocfg 1.0.0", | ||||||
|  "num-integer", |  "num-integer", | ||||||
|  "num-traits", |  "num-traits 0.2.11", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
|  | @ -1358,9 +1449,9 @@ dependencies = [ | ||||||
|  "libm", |  "libm", | ||||||
|  "num-integer", |  "num-integer", | ||||||
|  "num-iter", |  "num-iter", | ||||||
|  "num-traits", |  "num-traits 0.2.11", | ||||||
|  "rand", |  "rand", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "smallvec", |  "smallvec", | ||||||
|  "zeroize", |  "zeroize", | ||||||
| ] | ] | ||||||
|  | @ -1372,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" | checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "autocfg 1.0.0", |  "autocfg 1.0.0", | ||||||
|  "num-traits", |  "num-traits 0.2.11", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
|  | @ -1383,7 +1474,16 @@ checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "autocfg 1.0.0", |  "autocfg 1.0.0", | ||||||
|  "num-integer", |  "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]] | [[package]] | ||||||
|  | @ -1547,6 +1647,32 @@ dependencies = [ | ||||||
|  "log", |  "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]] | [[package]] | ||||||
| name = "proc-macro-hack" | name = "proc-macro-hack" | ||||||
| version = "0.5.12" | version = "0.5.12" | ||||||
|  | @ -1690,7 +1816,7 @@ dependencies = [ | ||||||
|  "num-bigint-dig", |  "num-bigint-dig", | ||||||
|  "num-integer", |  "num-integer", | ||||||
|  "num-iter", |  "num-iter", | ||||||
|  "num-traits", |  "num-traits 0.2.11", | ||||||
|  "rand", |  "rand", | ||||||
|  "subtle 2.2.2", |  "subtle 2.2.2", | ||||||
|  "zeroize", |  "zeroize", | ||||||
|  | @ -1716,13 +1842,19 @@ dependencies = [ | ||||||
|  "log", |  "log", | ||||||
|  "num-bigint", |  "num-bigint", | ||||||
|  "num-bigint-dig", |  "num-bigint-dig", | ||||||
|  "num-traits", |  "num-traits 0.2.11", | ||||||
|  "pem", |  "pem", | ||||||
|  "rsa", |  "rsa", | ||||||
|  "thiserror", |  "thiserror", | ||||||
|  "yasna", |  "yasna", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "rust-ini" | ||||||
|  | version = "0.13.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "rustc-demangle" | name = "rustc-demangle" | ||||||
| version = "0.1.16" | version = "0.1.16" | ||||||
|  | @ -1799,6 +1931,12 @@ version = "0.7.0" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "serde" | ||||||
|  | version = "0.8.23" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "serde" | name = "serde" | ||||||
| version = "1.0.105" | version = "1.0.105" | ||||||
|  | @ -1808,6 +1946,19 @@ dependencies = [ | ||||||
|  "serde_derive", |  "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]] | [[package]] | ||||||
| name = "serde_derive" | name = "serde_derive" | ||||||
| version = "1.0.105" | version = "1.0.105" | ||||||
|  | @ -1827,7 +1978,16 @@ checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "itoa", |  "itoa", | ||||||
|  "ryu", |  "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]] | [[package]] | ||||||
|  | @ -1838,7 +1998,7 @@ checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "dtoa", |  "dtoa", | ||||||
|  "itoa", |  "itoa", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "url", |  "url", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | @ -1924,6 +2084,12 @@ version = "0.2.1" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "4edf667ea8f60afc06d6aeec079d20d5800351109addec1faea678a8663da4e1" | checksum = "4edf667ea8f60afc06d6aeec079d20d5800351109addec1faea678a8663da4e1" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "static_assertions" | ||||||
|  | version = "0.3.4" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "stdweb" | name = "stdweb" | ||||||
| version = "0.4.20" | version = "0.4.20" | ||||||
|  | @ -1946,7 +2112,7 @@ checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
|  "quote", |  "quote", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_derive", |  "serde_derive", | ||||||
|  "syn", |  "syn", | ||||||
| ] | ] | ||||||
|  | @ -1960,7 +2126,7 @@ dependencies = [ | ||||||
|  "base-x", |  "base-x", | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
|  "quote", |  "quote", | ||||||
|  "serde", |  "serde 1.0.105", | ||||||
|  "serde_derive", |  "serde_derive", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "sha1", |  "sha1", | ||||||
|  | @ -1983,6 +2149,36 @@ dependencies = [ | ||||||
|  "unicode-normalization", |  "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]] | [[package]] | ||||||
| name = "subtle" | name = "subtle" | ||||||
| version = "1.0.0" | version = "1.0.0" | ||||||
|  | @ -2006,6 +2202,17 @@ dependencies = [ | ||||||
|  "unicode-xid", |  "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]] | [[package]] | ||||||
| name = "synstructure" | name = "synstructure" | ||||||
| version = "0.12.3" | version = "0.12.3" | ||||||
|  | @ -2027,6 +2234,15 @@ dependencies = [ | ||||||
|  "winapi-util", |  "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]] | [[package]] | ||||||
| name = "thiserror" | name = "thiserror" | ||||||
| version = "1.0.11" | version = "1.0.11" | ||||||
|  | @ -2196,6 +2412,15 @@ dependencies = [ | ||||||
|  "tokio", |  "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]] | [[package]] | ||||||
| name = "trust-dns-proto" | name = "trust-dns-proto" | ||||||
| version = "0.19.3" | version = "0.19.3" | ||||||
|  | @ -2242,7 +2467,7 @@ version = "0.5.1" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "4189890526f0168710b6ee65ceaedf1460c48a14318ceec933cb26baa492096a" | checksum = "4189890526f0168710b6ee65ceaedf1460c48a14318ceec933cb26baa492096a" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "linked-hash-map", |  "linked-hash-map 0.5.2", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
|  | @ -2275,6 +2500,12 @@ version = "1.6.0" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" | checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "unicode-width" | ||||||
|  | version = "0.1.7" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "unicode-xid" | name = "unicode-xid" | ||||||
| version = "0.2.0" | version = "0.2.0" | ||||||
|  | @ -2307,6 +2538,18 @@ dependencies = [ | ||||||
|  "rand", |  "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]] | [[package]] | ||||||
| name = "wasi" | name = "wasi" | ||||||
| version = "0.9.0+wasi-snapshot-preview1" | version = "0.9.0+wasi-snapshot-preview1" | ||||||
|  | @ -2464,6 +2707,15 @@ dependencies = [ | ||||||
|  "winapi-build", |  "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]] | [[package]] | ||||||
| name = "yasna" | name = "yasna" | ||||||
| version = "0.3.1" | version = "0.3.1" | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ actix-webfinger = "0.3.0-alpha.3" | ||||||
| activitystreams = "0.5.0-alpha.11" | activitystreams = "0.5.0-alpha.11" | ||||||
| base64 = "0.12" | base64 = "0.12" | ||||||
| bb8-postgres = "0.4.0" | bb8-postgres = "0.4.0" | ||||||
|  | config = "0.10.1" | ||||||
| dotenv = "0.15.0" | dotenv = "0.15.0" | ||||||
| futures = "0.3.4" | futures = "0.3.4" | ||||||
| http-signature-normalization-actix = { version = "0.3.0-alpha.5", default-features = false, features = ["sha-2"] } | 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 = { version = "1.0", features = ["derive"] } | ||||||
| serde_json = "1.0" | serde_json = "1.0" | ||||||
| sha2 = "0.8" | sha2 = "0.8" | ||||||
|  | structopt = "0.3.12" | ||||||
| thiserror = "1.0" | thiserror = "1.0" | ||||||
| tokio = { version = "0.2.13", features = ["sync"] } | tokio = { version = "0.2.13", features = ["sync"] } | ||||||
| ttl_cache = "0.5.1" | 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 activitystreams::primitives::XsdAnyUri; | ||||||
| use bb8_postgres::{ | use bb8_postgres::{ | ||||||
|     bb8, |     bb8, | ||||||
|     tokio_postgres::{row::Row, Client, Config, NoTls}, |     tokio_postgres::{ | ||||||
|  |         error::{Error, SqlState}, | ||||||
|  |         row::Row, | ||||||
|  |         Client, Config, NoTls, | ||||||
|  |     }, | ||||||
|     PostgresConnectionManager, |     PostgresConnectionManager, | ||||||
| }; | }; | ||||||
| use log::{info, warn}; | use log::{info, warn}; | ||||||
|  | @ -43,6 +47,48 @@ impl Db { | ||||||
|         Ok(()) |         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> { |     pub async fn hydrate_blocks(&self) -> Result<HashSet<String>, MyError> { | ||||||
|         let conn = self.pool.get().await?; |         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_blocks;"); | ||||||
|     info!("LISTEN new_whitelists;"); |     info!("LISTEN new_whitelists;"); | ||||||
|     info!("LISTEN new_listeners;"); |     info!("LISTEN new_listeners;"); | ||||||
|  | @ -117,49 +163,67 @@ async fn update_private_key(client: &Client, key: &RSAPrivateKey) -> Result<(), | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async fn add_block(client: &Client, block: &XsdAnyUri) -> Result<(), MyError> { | async fn add_block(client: &Client, domain: &str) -> Result<(), Error> { | ||||||
|     let host = if let Some(host) = block.as_url().host() { |  | ||||||
|         host |  | ||||||
|     } else { |  | ||||||
|         return Err(MyError::Host(block.to_string())); |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     info!( |     info!( | ||||||
|         "INSERT INTO blocks (domain_name, created_at) VALUES ($1::TEXT, 'now'); [{}]", |         "INSERT INTO blocks (domain_name, created_at) VALUES ($1::TEXT, 'now'); [{}]", | ||||||
|         host.to_string() |         domain, | ||||||
|     ); |     ); | ||||||
|     client |     client | ||||||
|         .execute( |         .execute( | ||||||
|             "INSERT INTO blocks (domain_name, created_at) VALUES ($1::TEXT, 'now');", |             "INSERT INTO blocks (domain_name, created_at) VALUES ($1::TEXT, 'now');", | ||||||
|             &[&host.to_string()], |             &[&domain], | ||||||
|         ) |         ) | ||||||
|         .await?; |         .await?; | ||||||
| 
 | 
 | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async fn add_whitelist(client: &Client, whitelist: &XsdAnyUri) -> Result<(), MyError> { | async fn remove_block(client: &Client, domain: &str) -> Result<(), Error> { | ||||||
|     let host = if let Some(host) = whitelist.as_url().host() { |     info!( | ||||||
|         host |         "DELETE FROM blocks WHERE domain_name = $1::TEXT; [{}]", | ||||||
|     } else { |         domain, | ||||||
|         return Err(MyError::Host(whitelist.to_string())); |     ); | ||||||
|     }; |     client | ||||||
|  |         .execute( | ||||||
|  |             "DELETE FROM blocks WHERE domain_name = $1::TEXT;", | ||||||
|  |             &[&domain], | ||||||
|  |         ) | ||||||
|  |         .await?; | ||||||
| 
 | 
 | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | async fn add_whitelist(client: &Client, domain: &str) -> Result<(), Error> { | ||||||
|     info!( |     info!( | ||||||
|         "INSERT INTO whitelists (domain_name, created_at) VALUES ($1::TEXT, 'now'); [{}]", |         "INSERT INTO whitelists (domain_name, created_at) VALUES ($1::TEXT, 'now'); [{}]", | ||||||
|         host.to_string() |         domain, | ||||||
|     ); |     ); | ||||||
|     client |     client | ||||||
|         .execute( |         .execute( | ||||||
|             "INSERT INTO whitelists (domain_name, created_at) VALUES ($1::TEXT, 'now');", |             "INSERT INTO whitelists (domain_name, created_at) VALUES ($1::TEXT, 'now');", | ||||||
|             &[&host.to_string()], |             &[&domain], | ||||||
|         ) |         ) | ||||||
|         .await?; |         .await?; | ||||||
| 
 | 
 | ||||||
|     Ok(()) |     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!( |     info!( | ||||||
|         "DELETE FROM listeners WHERE actor_id = {};", |         "DELETE FROM listeners WHERE actor_id = {};", | ||||||
|         listener.as_str() |         listener.as_str() | ||||||
|  | @ -174,7 +238,7 @@ async fn remove_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), My | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async fn add_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), MyError> { | async fn add_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), Error> { | ||||||
|     info!( |     info!( | ||||||
|         "INSERT INTO listeners (actor_id, created_at) VALUES ($1::TEXT, 'now'); [{}]", |         "INSERT INTO listeners (actor_id, created_at) VALUES ($1::TEXT, 'now'); [{}]", | ||||||
|         listener.as_str(), |         listener.as_str(), | ||||||
|  | @ -189,14 +253,14 @@ async fn add_listener(client: &Client, listener: &XsdAnyUri) -> Result<(), MyErr | ||||||
|     Ok(()) |     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"); |     info!("SELECT domain_name FROM blocks"); | ||||||
|     let rows = client.query("SELECT domain_name FROM blocks", &[]).await?; |     let rows = client.query("SELECT domain_name FROM blocks", &[]).await?; | ||||||
| 
 | 
 | ||||||
|     parse_rows(rows) |     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"); |     info!("SELECT domain_name FROM whitelists"); | ||||||
|     let rows = client |     let rows = client | ||||||
|         .query("SELECT domain_name FROM whitelists", &[]) |         .query("SELECT domain_name FROM whitelists", &[]) | ||||||
|  | @ -205,14 +269,14 @@ async fn hydrate_whitelists(client: &Client) -> Result<HashSet<String>, MyError> | ||||||
|     parse_rows(rows) |     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"); |     info!("SELECT actor_id FROM listeners"); | ||||||
|     let rows = client.query("SELECT actor_id FROM listeners", &[]).await?; |     let rows = client.query("SELECT actor_id FROM listeners", &[]).await?; | ||||||
| 
 | 
 | ||||||
|     parse_rows(rows) |     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 | where | ||||||
|     T: std::str::FromStr<Err = E> + Eq + std::hash::Hash, |     T: std::str::FromStr<Err = E> + Eq + std::hash::Hash, | ||||||
|     E: std::fmt::Display, |     E: std::fmt::Display, | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								src/error.rs
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								src/error.rs
									
										
									
									
									
								
							|  | @ -1,11 +1,18 @@ | ||||||
| use activitystreams::primitives::XsdAnyUriError; | 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 log::error; | ||||||
| use rsa_pem::KeyError; | use rsa_pem::KeyError; | ||||||
| use std::{convert::Infallible, io::Error}; | use std::{convert::Infallible, fmt::Debug, io::Error}; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, thiserror::Error)] | #[derive(Debug, thiserror::Error)] | ||||||
| pub enum MyError { | pub enum MyError { | ||||||
|  |     #[error("Error in configuration, {0}")] | ||||||
|  |     Config(#[from] config::ConfigError), | ||||||
|  | 
 | ||||||
|     #[error("Error in db, {0}")] |     #[error("Error in db, {0}")] | ||||||
|     DbError(#[from] bb8_postgres::tokio_postgres::error::Error), |     DbError(#[from] bb8_postgres::tokio_postgres::error::Error), | ||||||
| 
 | 
 | ||||||
|  | @ -51,9 +58,6 @@ pub enum MyError { | ||||||
|     #[error("Wrong ActivityPub kind, {0}")] |     #[error("Wrong ActivityPub kind, {0}")] | ||||||
|     Kind(String), |     Kind(String), | ||||||
| 
 | 
 | ||||||
|     #[error("No host present in URI, {0}")] |  | ||||||
|     Host(String), |  | ||||||
| 
 |  | ||||||
|     #[error("Too many CPUs, {0}")] |     #[error("Too many CPUs, {0}")] | ||||||
|     CpuCount(#[from] std::num::TryFromIntError), |     CpuCount(#[from] std::num::TryFromIntError), | ||||||
| 
 | 
 | ||||||
|  | @ -77,6 +81,9 @@ pub enum MyError { | ||||||
| 
 | 
 | ||||||
|     #[error("URI is missing domain field")] |     #[error("URI is missing domain field")] | ||||||
|     Domain, |     Domain, | ||||||
|  | 
 | ||||||
|  |     #[error("Blocking operation was canceled")] | ||||||
|  |     Canceled, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ResponseError for MyError { | 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 | impl<T> From<bb8_postgres::bb8::RunError<T>> for MyError | ||||||
| where | where | ||||||
|     T: Into<MyError>, |     T: Into<MyError>, | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								src/inbox.rs
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								src/inbox.rs
									
										
									
									
									
								
							|  | @ -1,10 +1,11 @@ | ||||||
| use crate::{ | use crate::{ | ||||||
|     accepted, |  | ||||||
|     apub::{AcceptedActors, AcceptedObjects, ValidTypes}, |     apub::{AcceptedActors, AcceptedObjects, ValidTypes}, | ||||||
|  |     config::{Config, UrlKind}, | ||||||
|     db::Db, |     db::Db, | ||||||
|     error::MyError, |     error::MyError, | ||||||
|     requests::Requests, |     requests::Requests, | ||||||
|     state::{State, UrlKind}, |     responses::accepted, | ||||||
|  |     state::State, | ||||||
| }; | }; | ||||||
| use activitystreams::{ | use activitystreams::{ | ||||||
|     activity::{Accept, Announce, Follow, Undo}, |     activity::{Accept, Announce, Follow, Undo}, | ||||||
|  | @ -22,6 +23,7 @@ use std::convert::TryInto; | ||||||
| pub async fn inbox( | pub async fn inbox( | ||||||
|     db: web::Data<Db>, |     db: web::Data<Db>, | ||||||
|     state: web::Data<State>, |     state: web::Data<State>, | ||||||
|  |     config: web::Data<Config>, | ||||||
|     client: web::Data<Requests>, |     client: web::Data<Requests>, | ||||||
|     input: web::Json<AcceptedObjects>, |     input: web::Json<AcceptedObjects>, | ||||||
|     verified: SignatureVerified, |     verified: SignatureVerified, | ||||||
|  | @ -58,19 +60,20 @@ pub async fn inbox( | ||||||
| 
 | 
 | ||||||
|     match input.kind { |     match input.kind { | ||||||
|         ValidTypes::Announce | ValidTypes::Create => { |         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 => { |         ValidTypes::Delete | ValidTypes::Update => { | ||||||
|             handle_forward(&state, &client, input, actor).await |             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( | async fn handle_undo( | ||||||
|     db: &Db, |     db: &Db, | ||||||
|     state: &State, |     state: &State, | ||||||
|  |     config: &Config, | ||||||
|     client: &Requests, |     client: &Requests, | ||||||
|     input: AcceptedObjects, |     input: AcceptedObjects, | ||||||
|     actor: AcceptedActors, |     actor: AcceptedActors, | ||||||
|  | @ -88,7 +91,7 @@ async fn handle_undo( | ||||||
|         return handle_forward(state, client, input, actor).await; |         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()) { |     if !input.object.child_object_is(&my_id) && !input.object.child_object_is(&public()) { | ||||||
|         return Err(MyError::WrongActor(input.object.id().to_string())); |         return Err(MyError::WrongActor(input.object.id().to_string())); | ||||||
|  | @ -97,7 +100,7 @@ async fn handle_undo( | ||||||
|     let inbox = actor.inbox().to_owned(); |     let inbox = actor.inbox().to_owned(); | ||||||
|     db.remove_listener(inbox).await?; |     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 client2 = client.clone(); | ||||||
|     let inbox = actor.inbox().clone(); |     let inbox = actor.inbox().clone(); | ||||||
|  | @ -125,6 +128,7 @@ async fn handle_forward( | ||||||
| 
 | 
 | ||||||
| async fn handle_announce( | async fn handle_announce( | ||||||
|     state: &State, |     state: &State, | ||||||
|  |     config: &Config, | ||||||
|     client: &Requests, |     client: &Requests, | ||||||
|     input: AcceptedObjects, |     input: AcceptedObjects, | ||||||
|     actor: AcceptedActors, |     actor: AcceptedActors, | ||||||
|  | @ -135,9 +139,9 @@ async fn handle_announce( | ||||||
|         return Err(MyError::Duplicate); |         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?; |     let inboxes = get_inboxes(state, &actor, &object_id).await?; | ||||||
|     client.deliver_many(inboxes, announce.clone()); |     client.deliver_many(inboxes, announce.clone()); | ||||||
| 
 | 
 | ||||||
|  | @ -148,13 +152,13 @@ async fn handle_announce( | ||||||
| 
 | 
 | ||||||
| async fn handle_follow( | async fn handle_follow( | ||||||
|     db: &Db, |     db: &Db, | ||||||
|     state: &State, |     config: &Config, | ||||||
|     client: &Requests, |     client: &Requests, | ||||||
|     input: AcceptedObjects, |     input: AcceptedObjects, | ||||||
|     actor: AcceptedActors, |     actor: AcceptedActors, | ||||||
|     is_listener: bool, |     is_listener: bool, | ||||||
| ) -> Result<HttpResponse, MyError> { | ) -> 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()) { |     if !input.object.is(&my_id) && !input.object.is(&public()) { | ||||||
|         return Err(MyError::WrongActor(input.object.id().to_string())); |         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 following relay directly, not just following 'public', followback
 | ||||||
|         if input.object.is(&my_id) { |         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 client2 = client.clone(); | ||||||
|             let inbox = actor.inbox().clone(); |             let inbox = actor.inbox().clone(); | ||||||
|             let follow2 = follow.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 client2 = client.clone(); | ||||||
|     let inbox = actor.inbox().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"
 | // Generate a type that says "I want to stop following you"
 | ||||||
| fn generate_undo_follow( | fn generate_undo_follow( | ||||||
|     state: &State, |     config: &Config, | ||||||
|     actor_id: &XsdAnyUri, |     actor_id: &XsdAnyUri, | ||||||
|     my_id: &XsdAnyUri, |     my_id: &XsdAnyUri, | ||||||
| ) -> Result<Undo, MyError> { | ) -> Result<Undo, MyError> { | ||||||
|  | @ -203,7 +207,7 @@ fn generate_undo_follow( | ||||||
| 
 | 
 | ||||||
|             follow |             follow | ||||||
|                 .object_props |                 .object_props | ||||||
|                 .set_id(state.generate_url(UrlKind::Activity))?; |                 .set_id(config.generate_url(UrlKind::Activity))?; | ||||||
|             follow |             follow | ||||||
|                 .follow_props |                 .follow_props | ||||||
|                 .set_actor_xsd_any_uri(actor_id.clone())? |                 .set_actor_xsd_any_uri(actor_id.clone())? | ||||||
|  | @ -212,12 +216,12 @@ fn generate_undo_follow( | ||||||
|             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"
 | // Generate a type that says "Look at this object"
 | ||||||
| fn generate_announce( | fn generate_announce( | ||||||
|     state: &State, |     config: &Config, | ||||||
|     activity_id: &XsdAnyUri, |     activity_id: &XsdAnyUri, | ||||||
|     object_id: &XsdAnyUri, |     object_id: &XsdAnyUri, | ||||||
| ) -> Result<Announce, MyError> { | ) -> Result<Announce, MyError> { | ||||||
|  | @ -226,18 +230,18 @@ fn generate_announce( | ||||||
|     announce |     announce | ||||||
|         .announce_props |         .announce_props | ||||||
|         .set_object_xsd_any_uri(object_id.clone())? |         .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( |     prepare_activity( | ||||||
|         announce, |         announce, | ||||||
|         activity_id.clone(), |         activity_id.clone(), | ||||||
|         state.generate_url(UrlKind::Followers), |         config.generate_url(UrlKind::Followers), | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Generate a type that says "I want to follow you"
 | // Generate a type that says "I want to follow you"
 | ||||||
| fn generate_follow( | fn generate_follow( | ||||||
|     state: &State, |     config: &Config, | ||||||
|     actor_id: &XsdAnyUri, |     actor_id: &XsdAnyUri, | ||||||
|     my_id: &XsdAnyUri, |     my_id: &XsdAnyUri, | ||||||
| ) -> Result<Follow, MyError> { | ) -> Result<Follow, MyError> { | ||||||
|  | @ -250,14 +254,14 @@ fn generate_follow( | ||||||
| 
 | 
 | ||||||
|     prepare_activity( |     prepare_activity( | ||||||
|         follow, |         follow, | ||||||
|         state.generate_url(UrlKind::Activity), |         config.generate_url(UrlKind::Activity), | ||||||
|         actor_id.clone(), |         actor_id.clone(), | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Generate a type that says "I accept your follow request"
 | // Generate a type that says "I accept your follow request"
 | ||||||
| fn generate_accept_follow( | fn generate_accept_follow( | ||||||
|     state: &State, |     config: &Config, | ||||||
|     actor_id: &XsdAnyUri, |     actor_id: &XsdAnyUri, | ||||||
|     input_id: &XsdAnyUri, |     input_id: &XsdAnyUri, | ||||||
|     my_id: &XsdAnyUri, |     my_id: &XsdAnyUri, | ||||||
|  | @ -281,7 +285,7 @@ fn generate_accept_follow( | ||||||
| 
 | 
 | ||||||
|     prepare_activity( |     prepare_activity( | ||||||
|         accept, |         accept, | ||||||
|         state.generate_url(UrlKind::Activity), |         config.generate_url(UrlKind::Activity), | ||||||
|         actor_id.clone(), |         actor_id.clone(), | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										117
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										117
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -1,122 +1,77 @@ | ||||||
| use activitystreams::{ | use actix_web::{middleware::Logger, web, App, HttpServer, Responder}; | ||||||
|     actor::Application, context, endpoint::EndpointProperties, ext::Extensible, |  | ||||||
|     object::properties::ObjectProperties, security, |  | ||||||
| }; |  | ||||||
| use actix_web::{middleware::Logger, web, App, HttpResponse, HttpServer, Responder}; |  | ||||||
| use bb8_postgres::tokio_postgres; | 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 apub; | ||||||
|  | mod args; | ||||||
|  | mod config; | ||||||
| mod db; | mod db; | ||||||
| mod error; | mod error; | ||||||
| mod inbox; | mod inbox; | ||||||
| mod nodeinfo; | mod nodeinfo; | ||||||
| mod notify; | mod notify; | ||||||
| mod requests; | mod requests; | ||||||
|  | mod responses; | ||||||
| mod state; | mod state; | ||||||
| mod verifier; | mod verifier; | ||||||
| mod webfinger; | mod webfinger; | ||||||
| 
 | 
 | ||||||
| use self::{ | use self::{args::Args, config::Config, db::Db, state::State, webfinger::RelayResolver}; | ||||||
|     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) |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| async fn index() -> impl Responder { | async fn index() -> impl Responder { | ||||||
|     "hewwo, mr obama" |     "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] | #[actix_rt::main] | ||||||
| async fn main() -> Result<(), anyhow::Error> { | async fn main() -> Result<(), anyhow::Error> { | ||||||
|     dotenv::dotenv().ok(); |     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(); |     pretty_env_logger::init(); | ||||||
| 
 | 
 | ||||||
|     let pg_config: tokio_postgres::Config = std::env::var("DATABASE_URL")?.parse()?; |     let pg_config: tokio_postgres::Config = config.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 db = Db::build(pg_config.clone()).await?; |     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 _ = notify::NotifyHandler::start_handler(state.clone(), pg_config.clone()); | ||||||
| 
 | 
 | ||||||
|  |     let bind_address = config.bind_address(); | ||||||
|     HttpServer::new(move || { |     HttpServer::new(move || { | ||||||
|         let state = state.clone(); |  | ||||||
| 
 |  | ||||||
|         App::new() |         App::new() | ||||||
|             .wrap(Logger::default()) |             .wrap(Logger::default()) | ||||||
|             .data(db.clone()) |             .data(db.clone()) | ||||||
|             .data(state.clone()) |             .data(state.clone()) | ||||||
|             .data(state.requests()) |             .data(state.requests()) | ||||||
|  |             .data(config.clone()) | ||||||
|             .service(web::resource("/").route(web::get().to(index))) |             .service(web::resource("/").route(web::get().to(index))) | ||||||
|             .service( |             .service( | ||||||
|                 web::resource("/inbox") |                 web::resource("/inbox") | ||||||
|                     .wrap(VerifyDigest::new(Sha256::new())) |                     .wrap(config.digest_middleware()) | ||||||
|                     .wrap(VerifySignature::new( |                     .wrap(config.signature_middleware(state.requests())) | ||||||
|                         MyVerify(state.requests()), |  | ||||||
|                         Default::default(), |  | ||||||
|                     )) |  | ||||||
|                     .route(web::post().to(inbox::inbox)), |                     .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::resource("/nodeinfo/2.0").route(web::get().to(nodeinfo::route))) | ||||||
|             .service( |             .service( | ||||||
|                 web::scope("/.well-known") |                 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))), |                     .service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))), | ||||||
|             ) |             ) | ||||||
|     }) |     }) | ||||||
|     .bind("0.0.0.0:8080")? |     .bind(bind_address)? | ||||||
|     .run() |     .run() | ||||||
|     .await?; |     .await?; | ||||||
|     Ok(()) |     Ok(()) | ||||||
|  |  | ||||||
|  | @ -1,24 +1,24 @@ | ||||||
| use crate::state::{State, UrlKind}; | use crate::config::{Config, UrlKind}; | ||||||
| use actix_web::{web, Responder}; | use actix_web::{web, Responder}; | ||||||
| use actix_webfinger::Link; | use actix_webfinger::Link; | ||||||
| use std::collections::HashMap; | 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 { |     web::Json(Link { | ||||||
|         rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_owned(), |         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, |         template: None, | ||||||
|         kind: None, |         kind: None, | ||||||
|     }) |     }) | ||||||
|     .with_header("Content-Type", "application/jrd+json") |     .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 { |     web::Json(NodeInfo { | ||||||
|         version: NodeInfoVersion, |         version: NodeInfoVersion, | ||||||
|         software: Software { |         software: Software { | ||||||
|             name: state.software_name(), |             name: config.software_name(), | ||||||
|             version: state.software_version(), |             version: config.software_version(), | ||||||
|         }, |         }, | ||||||
|         protocols: vec![Protocol::ActivityPub], |         protocols: vec![Protocol::ActivityPub], | ||||||
|         services: vec![], |         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 activitystreams::primitives::XsdAnyUri; | ||||||
|  | use actix_web::web; | ||||||
| use futures::try_join; | use futures::try_join; | ||||||
| use log::info; | use log::info; | ||||||
| use lru::LruCache; | use lru::LruCache; | ||||||
|  | @ -8,13 +15,14 @@ use rsa::{RSAPrivateKey, RSAPublicKey}; | ||||||
| use std::{collections::HashSet, sync::Arc}; | use std::{collections::HashSet, sync::Arc}; | ||||||
| use tokio::sync::RwLock; | use tokio::sync::RwLock; | ||||||
| use ttl_cache::TtlCache; | use ttl_cache::TtlCache; | ||||||
| use uuid::Uuid; |  | ||||||
| 
 | 
 | ||||||
| pub type ActorCache = Arc<RwLock<TtlCache<XsdAnyUri, AcceptedActors>>>; | pub type ActorCache = Arc<RwLock<TtlCache<XsdAnyUri, AcceptedActors>>>; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct State { | pub struct State { | ||||||
|     pub settings: Settings, |     pub public_key: RSAPublicKey, | ||||||
|  |     private_key: RSAPrivateKey, | ||||||
|  |     config: Config, | ||||||
|     actor_cache: ActorCache, |     actor_cache: ActorCache, | ||||||
|     actor_id_cache: Arc<RwLock<LruCache<XsdAnyUri, XsdAnyUri>>>, |     actor_id_cache: Arc<RwLock<LruCache<XsdAnyUri, XsdAnyUri>>>, | ||||||
|     blocks: Arc<RwLock<HashSet<String>>>, |     blocks: Arc<RwLock<HashSet<String>>>, | ||||||
|  | @ -22,112 +30,20 @@ pub struct State { | ||||||
|     listeners: Arc<RwLock<HashSet<XsdAnyUri>>>, |     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 { | 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 { |     pub fn requests(&self) -> Requests { | ||||||
|         Requests::new( |         Requests::new( | ||||||
|             self.generate_url(UrlKind::MainKey), |             self.config.generate_url(UrlKind::MainKey), | ||||||
|             self.settings.private_key.clone(), |             self.private_key.clone(), | ||||||
|             self.actor_cache.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) { |     pub async fn bust_whitelist(&self, whitelist: &str) { | ||||||
|         let hs = self.whitelists.clone(); |         let hs = self.whitelists.clone(); | ||||||
| 
 | 
 | ||||||
|  | @ -169,7 +85,7 @@ impl State { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub async fn is_whitelisted(&self, actor_id: &XsdAnyUri) -> bool { |     pub async fn is_whitelisted(&self, actor_id: &XsdAnyUri) -> bool { | ||||||
|         if !self.settings.whitelist_enabled { |         if !self.config.whitelist_mode() { | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -236,21 +152,36 @@ impl State { | ||||||
|         write_guard.insert(listener); |         write_guard.insert(listener); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub async fn hydrate( |     pub async fn hydrate(config: Config, db: &Db) -> Result<Self, MyError> { | ||||||
|         use_https: bool, |  | ||||||
|         whitelist_enabled: bool, |  | ||||||
|         hostname: String, |  | ||||||
|         db: &Db, |  | ||||||
|     ) -> Result<Self, MyError> { |  | ||||||
|         let f1 = db.hydrate_blocks(); |         let f1 = db.hydrate_blocks(); | ||||||
|         let f2 = db.hydrate_whitelists(); |         let f2 = db.hydrate_whitelists(); | ||||||
|         let f3 = db.hydrate_listeners(); |         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 { |         Ok(State { | ||||||
|             settings, |             public_key, | ||||||
|  |             private_key, | ||||||
|  |             config, | ||||||
|             actor_cache: Arc::new(RwLock::new(TtlCache::new(1024 * 8))), |             actor_cache: Arc::new(RwLock::new(TtlCache::new(1024 * 8))), | ||||||
|             actor_id_cache: Arc::new(RwLock::new(LruCache::new(1024 * 8))), |             actor_id_cache: Arc::new(RwLock::new(LruCache::new(1024 * 8))), | ||||||
|             blocks: Arc::new(RwLock::new(blocks)), |             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 activitystreams::context; | ||||||
| use actix_web::web::Data; | use actix_web::web::Data; | ||||||
| use actix_webfinger::{Link, Resolver, Webfinger}; | use actix_webfinger::{Link, Resolver, Webfinger}; | ||||||
|  | @ -11,19 +14,19 @@ pub struct RelayResolver; | ||||||
| #[error("Error resolving webfinger data")] | #[error("Error resolving webfinger data")] | ||||||
| pub struct RelayError; | pub struct RelayError; | ||||||
| 
 | 
 | ||||||
| impl Resolver<Data<State>> for RelayResolver { | impl Resolver<(Data<State>, Data<Config>)> for RelayResolver { | ||||||
|     type Error = RelayError; |     type Error = RelayError; | ||||||
| 
 | 
 | ||||||
|     fn find( |     fn find( | ||||||
|         account: &str, |         account: &str, | ||||||
|         domain: &str, |         domain: &str, | ||||||
|         state: Data<State>, |         (state, config): (Data<State>, Data<Config>), | ||||||
|     ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> { |     ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> { | ||||||
|         let domain = domain.to_owned(); |         let domain = domain.to_owned(); | ||||||
|         let account = account.to_owned(); |         let account = account.to_owned(); | ||||||
| 
 | 
 | ||||||
|         let fut = async move { |         let fut = async move { | ||||||
|             if domain != state.settings.hostname { |             if domain != config.hostname() { | ||||||
|                 return Ok(None); |                 return Ok(None); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -31,13 +34,13 @@ impl Resolver<Data<State>> for RelayResolver { | ||||||
|                 return Ok(None); |                 return Ok(None); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             let mut wf = Webfinger::new(&state.generate_resource()); |             let mut wf = Webfinger::new(&config.generate_resource()); | ||||||
|             wf.add_alias(&state.generate_url(UrlKind::Actor)) |             wf.add_alias(&config.generate_url(UrlKind::Actor)) | ||||||
|                 .add_activitypub(&state.generate_url(UrlKind::Actor)) |                 .add_activitypub(&config.generate_url(UrlKind::Actor)) | ||||||
|                 .add_magic_public_key(&state.settings.public_key.as_magic_public_key()) |                 .add_magic_public_key(&state.public_key.as_magic_public_key()) | ||||||
|                 .add_link(Link { |                 .add_link(Link { | ||||||
|                     rel: "self".to_owned(), |                     rel: "self".to_owned(), | ||||||
|                     href: Some(state.generate_url(UrlKind::Actor)), |                     href: Some(config.generate_url(UrlKind::Actor)), | ||||||
|                     template: None, |                     template: None, | ||||||
|                     kind: Some(format!("application/ld+json; profile=\"{}\"", context())), |                     kind: Some(format!("application/ld+json; profile=\"{}\"", context())), | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue