feat: login and register HTML pages

master
Aravinth Manivannan 2022-02-21 02:21:13 +05:30
parent 2cf064d565
commit 34e8d8851f
Signed by: realaravinth
GPG Key ID: AD9F0F08E855ED88
15 changed files with 1088 additions and 100 deletions

336
Cargo.lock generated
View File

@ -28,16 +28,33 @@ dependencies = [
"memchr",
"pin-project-lite",
"tokio",
"tokio-util",
"tokio-util 0.6.9",
]
[[package]]
name = "actix-codec"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe"
dependencies = [
"bitflags",
"bytes",
"futures-core",
"futures-sink",
"log",
"memchr",
"pin-project-lite",
"tokio",
"tokio-util 0.7.0",
]
[[package]]
name = "actix-http"
version = "3.0.0-rc.2"
version = "3.0.0-rc.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb0185d65352deeea60d92231708068c04dc64f1ab307a1a307206a47d5a45d3"
checksum = "a8b5ba038f3bb4aa29ad9bdd7eba09955ff04503263c497fc61a389d6412f4e8"
dependencies = [
"actix-codec",
"actix-codec 0.5.0",
"actix-rt",
"actix-service",
"actix-utils",
@ -62,7 +79,7 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project-lite",
"rand 0.8.4",
"rand 0.8.5",
"sha-1 0.10.0",
"smallvec",
"zstd",
@ -70,9 +87,9 @@ dependencies = [
[[package]]
name = "actix-identity"
version = "0.4.0-beta.8"
version = "0.4.0-beta.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f084963856cf7990b1f21d6298626de4ae6178385cadece312e12c9f7a9f432"
checksum = "68895242adbce3e672e60c8fdcd1895491afcbbc8f5b7a7fca14932307ccdde4"
dependencies = [
"actix-service",
"actix-utils",
@ -130,7 +147,7 @@ dependencies = [
"futures-core",
"futures-util",
"log",
"mio 0.8.0",
"mio",
"num_cpus",
"socket2",
"tokio",
@ -163,7 +180,7 @@ version = "4.0.0-rc.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83e3c85bc4116b69913b03f16cff8cade1212508fcd321847d9cfe3d3e41f991"
dependencies = [
"actix-codec",
"actix-codec 0.4.2",
"actix-http",
"actix-macros",
"actix-router",
@ -297,15 +314,14 @@ dependencies = [
[[package]]
name = "ammonia"
version = "3.1.3"
version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b74b175af97d1aecc1add0878b1cbfcbf3bd4c22d7713eeb6d597da23e29bc0d"
checksum = "ea9f21d23d82bae9d33c21080572af1fa749788e68234b5d8fa5e39d3e0783ed"
dependencies = [
"html5ever",
"lazy_static",
"maplit",
"markup5ever_rcdom",
"matches",
"tendril",
"url",
]
@ -319,7 +335,7 @@ dependencies = [
"derive_builder",
"derive_more",
"lazy_static",
"rand 0.8.4",
"rand 0.8.5",
"regex",
"rust-argon2",
"unicode-normalization",
@ -512,11 +528,26 @@ dependencies = [
"bytes",
]
[[package]]
name = "cache-buster"
version = "0.2.0"
source = "git+https://github.com/realaravinth/cache-buster#7011c8c05cd584e82c31ddb20a19f80e2faa756b"
dependencies = [
"data-encoding",
"derive_builder",
"mime",
"mime_guess",
"serde 1.0.136",
"serde_json",
"sha2 0.10.2",
"walkdir",
]
[[package]]
name = "cc"
version = "1.0.72"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
dependencies = [
"jobserver",
]
@ -579,10 +610,10 @@ dependencies = [
"aes-gcm",
"base64",
"hkdf",
"hmac 0.12.0",
"hmac 0.12.1",
"percent-encoding",
"rand 0.8.4",
"sha2 0.10.1",
"rand 0.8.5",
"sha2 0.10.2",
"subtle",
"time 0.3.7",
"version_check",
@ -621,16 +652,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.4"
@ -653,11 +674,12 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
dependencies = [
"generic-array 0.14.5",
"typenum",
]
[[package]]
@ -714,6 +736,12 @@ dependencies = [
"syn",
]
[[package]]
name = "data-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
[[package]]
name = "db-core"
version = "0.1.0"
@ -808,9 +836,9 @@ dependencies = [
[[package]]
name = "digest"
version = "0.10.2"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [
"block-buffer 0.10.2",
"crypto-common",
@ -906,9 +934,9 @@ dependencies = [
[[package]]
name = "flume"
version = "0.10.10"
version = "0.10.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d04dafd11240188e146b6f6476a898004cace3be31d4ec5e08e216bf4947ac0"
checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4"
dependencies = [
"futures-core",
"futures-sink",
@ -992,7 +1020,7 @@ checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e"
dependencies = [
"futures-core",
"lock_api",
"parking_lot",
"parking_lot 0.11.2",
]
[[package]]
@ -1119,6 +1147,7 @@ dependencies = [
"actix-web",
"actix-web-codegen 0.5.0-rc.2 (git+https://github.com/realaravinth/actix-web)",
"argon2-creds",
"cache-buster",
"config",
"db-core",
"db-sqlx-postgres",
@ -1128,10 +1157,13 @@ dependencies = [
"git2",
"lazy_static",
"log",
"mime",
"mime_guess",
"num_cpus",
"num_enum",
"pretty_env_logger",
"rand 0.8.4",
"rand 0.8.5",
"rust-embed",
"serde 1.0.136",
"serde_json",
"sqlx",
@ -1181,7 +1213,7 @@ dependencies = [
"indexmap",
"slab",
"tokio",
"tokio-util",
"tokio-util 0.6.9",
"tracing",
]
@ -1229,11 +1261,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hkdf"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "158bc31e00a68e380286904cc598715f861f2b0ccf7aa6fe20c6d0c49ca5d0f6"
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
dependencies = [
"hmac 0.12.0",
"hmac 0.12.1",
]
[[package]]
@ -1248,11 +1280,11 @@ dependencies = [
[[package]]
name = "hmac"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddca131f3e7f2ce2df364b57949a9d47915cfbd35e46cfee355ccebbf794d6a2"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.2",
"digest 0.10.3",
]
[[package]]
@ -1421,9 +1453,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.117"
version = "0.2.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
[[package]]
name = "libgit2-sys"
@ -1585,6 +1617,16 @@ version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -1601,19 +1643,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mio"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"winapi",
]
[[package]]
name = "mio"
version = "0.8.0"
@ -1776,7 +1805,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
"parking_lot_core 0.8.5",
]
[[package]]
name = "parking_lot"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
dependencies = [
"lock_api",
"parking_lot_core 0.9.1",
]
[[package]]
@ -1793,6 +1832,19 @@ dependencies = [
"winapi",
]
[[package]]
name = "parking_lot_core"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]]
name = "paste"
version = "1.0.6"
@ -2041,20 +2093,19 @@ dependencies = [
"libc",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc 0.2.0",
"rand_hc",
"rand_pcg",
]
[[package]]
name = "rand"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.3",
"rand_hc 0.3.1",
]
[[package]]
@ -2104,15 +2155,6 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_pcg"
version = "0.2.1"
@ -2185,6 +2227,40 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "rust-embed"
version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40377bff8cceee81e28ddb73ac97f5c2856ce5522f0b260b763f434cdfae602"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "6.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e763e24ba2bf0c72bc6be883f967f794a019fafd1b86ba1daff9c91a7edd30"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad22c7226e4829104deab21df575e995bfbc4adfad13a595e387477f238c1aec"
dependencies = [
"sha2 0.9.9",
"walkdir",
]
[[package]]
name = "rust-ini"
version = "0.13.0"
@ -2314,11 +2390,10 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.78"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde 1.0.136",
@ -2369,7 +2444,7 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
dependencies = [
"cfg-if",
"cpufeatures",
"digest 0.10.2",
"digest 0.10.3",
]
[[package]]
@ -2402,13 +2477,13 @@ dependencies = [
[[package]]
name = "sha2"
version = "0.10.1"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
dependencies = [
"cfg-if",
"cpufeatures",
"digest 0.10.2",
"digest 0.10.3",
]
[[package]]
@ -2476,9 +2551,9 @@ dependencies = [
[[package]]
name = "sqlx"
version = "0.5.10"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692749de69603d81e016212199d73a2e14ee20e2def7d7914919e8db5d4d48b9"
checksum = "fc15591eb44ffb5816a4a70a7efd5dd87bfd3aa84c4c200401c4396140525826"
dependencies = [
"sqlx-core",
"sqlx-macros",
@ -2486,9 +2561,9 @@ dependencies = [
[[package]]
name = "sqlx-core"
version = "0.5.10"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518be6f6fff5ca76f985d434f9c37f3662af279642acf730388f271dff7b9016"
checksum = "195183bf6ff8328bb82c0511a83faf60aacf75840103388851db61d7a9854ae3"
dependencies = [
"ahash",
"atoi",
@ -2497,9 +2572,7 @@ dependencies = [
"byteorder",
"bytes",
"crc",
"crossbeam-channel",
"crossbeam-queue",
"crossbeam-utils",
"dirs",
"either",
"flume",
@ -2519,9 +2592,9 @@ dependencies = [
"md-5",
"memchr",
"once_cell",
"parking_lot",
"paste",
"percent-encoding",
"rand 0.8.4",
"rand 0.8.5",
"rustls",
"serde 1.0.136",
"serde_json",
@ -2543,9 +2616,9 @@ dependencies = [
[[package]]
name = "sqlx-macros"
version = "0.5.10"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38e45140529cf1f90a5e1c2e561500ca345821a1c513652c8f486bbf07407cc8"
checksum = "eee35713129561f5e55c554bba1c378e2a7e67f81257b7311183de98c50e6f94"
dependencies = [
"dotenv",
"either",
@ -2565,9 +2638,9 @@ dependencies = [
[[package]]
name = "sqlx-rt"
version = "0.5.10"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8061cbaa91ee75041514f67a09398c65a64efed72c90151ecd47593bad53da99"
checksum = "b555e70fbbf84e269ec3858b7a6515bcfe7a166a7cc9c636dd6efd20431678b6"
dependencies = [
"actix-rt",
"once_cell",
@ -2647,7 +2720,7 @@ checksum = "33994d0838dc2d152d17a62adf608a869b5e846b65b389af7f3dbc1de45c5b26"
dependencies = [
"lazy_static",
"new_debug_unreachable",
"parking_lot",
"parking_lot 0.11.2",
"phf_shared 0.10.0",
"precomputed-hash",
"serde 1.0.136",
@ -2846,19 +2919,20 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.16.1"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
dependencies = [
"bytes",
"libc",
"memchr",
"mio 0.7.14",
"mio",
"num_cpus",
"once_cell",
"parking_lot",
"parking_lot 0.12.0",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"winapi",
]
@ -2898,6 +2972,20 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64910e1b9c1901aaf5375561e35b9c057d95ff41a44ede043a03e09279eabaf1"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
]
[[package]]
name = "toml"
version = "0.5.8"
@ -2909,9 +2997,9 @@ dependencies = [
[[package]]
name = "tracing"
version = "0.1.30"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9"
checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f"
dependencies = [
"cfg-if",
"pin-project-lite",
@ -2989,6 +3077,15 @@ dependencies = [
"unic-common",
]
[[package]]
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.7"
@ -3270,6 +3367,49 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
[[package]]
name = "xml5ever"
version = "0.16.2"

View File

@ -27,6 +27,7 @@ actix-http = "3.0.0-rc.2"
actix-identity = "0.4.0-beta.8"
actix-rt = "2.6.0"
argon2-creds = { branch = "master", git = "https://github.com/realaravinth/argon2-creds"}
cache-buster = { git = "https://github.com/realaravinth/cache-buster" }
config = "0.11"
db-core = {path = "./database/db-core"}
db-sqlx-postgres = {path = "./database/db-sqlx-postgres"}
@ -36,19 +37,29 @@ futures = "0.3.21"
git2 = "0.13.25"
lazy_static = "1.4"
log = "0.4"
mime = "0.3.16"
mime_guess = "2.0.3"
my-codegen = {package = "actix-web-codegen", git ="https://github.com/realaravinth/actix-web"}
num_cpus = "1.13"
num_enum = "0.5.6"
pretty_env_logger = "0.4"
rand = "0.8.4"
rust-embed = "6.0.0"
serde = { version = "1", features = ["derive"]}
serde_json = "1"
sqlx = { version = "0.5.10", features = [ "runtime-actix-rustls", "uuid", "postgres", "time", "offline", "sqlite" ] }
tera = { version = "1.15.0", default-features = false}
tokio = { version = "1.16.1", features = ["fs"] }
url = "2.2"
urlencoding = "2.1.0"
validator = { version = "0.14.0", features = ["derive"] }
num_enum = "0.5.6"
tera = { version = "1.15.0", default-features = false}
[dev-dependencies]
actix-rt = "2"
[build-dependencies]
serde_json = "1"
cache-buster = { git = "https://github.com/realaravinth/cache-buster" }
#cache-buster = { version = "0.2.0", git = "https://github.com/realaravinth/cache-buster" }
mime = "0.3.16"

View File

@ -31,6 +31,7 @@ pub mod data;
mod db;
pub mod demo;
pub mod errors;
mod pages;
mod routes;
mod settings;
mod static_assets;
@ -62,6 +63,7 @@ lazy_static! {
async fn main() -> std::io::Result<()> {
let settings = Settings::new().unwrap();
pretty_env_logger::init();
pages::init(&settings);
info!(
"{}: {}.\nFor more information, see: {}\nBuild info:\nVersion: {} commit: {}",

151
src/pages/auth/login.rs Normal file
View File

@ -0,0 +1,151 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use actix_web::http::header::ContentType;
use crate::settings::Settings;
use crate::AppData;
pub use super::*;
pub struct Login;
pub const LOGIN: &str = "login";
impl Login {
pub fn page(s: &Settings) -> String {
let ctx = context(s);
TEMPLATES.render(LOGIN, &ctx).unwrap()
}
}
#[my_codegen::get(path = "PAGES.auth.login")]
pub async fn get_login(data: AppData) -> impl Responder {
let login = Login::page(&data.settings);
let html = ContentType::html();
HttpResponse::Ok().content_type(html).body(login)
}
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(get_login);
}
//#[post(path = "PAGES.auth.login")]
//pub async fn login_submit(
// id: Identity,
// payload: web::Form<runners::Login>,
// data: AppData,
//) -> PageResult<impl Responder> {
// let payload = payload.into_inner();
// match runners::login_runner(&payload, &data).await {
// Ok(username) => {
// id.remember(username);
// Ok(HttpResponse::Found()
// .insert_header((header::LOCATION, PAGES.home))
// .finish())
// }
// Err(e) => {
// let status = e.status_code();
// let heading = status.canonical_reason().unwrap_or("Error");
//
// Ok(HttpResponseBuilder::new(status)
// .content_type("text/html; charset=utf-8")
// .body(
// IndexPage::new(heading, &format!("{}", e))
// .render_once()
// .unwrap(),
// ))
// }
// }
//}
//
//#[cfg(test)]
//mod tests {
// use actix_web::test;
//
// use super::*;
//
// use crate::api::v1::auth::runners::{Login, Register};
// use crate::data::Data;
// use crate::tests::*;
// use crate::*;
// use actix_web::http::StatusCode;
//
// #[actix_rt::test]
// async fn auth_form_works() {
// let data = Data::new().await;
// const NAME: &str = "testuserform";
// const PASSWORD: &str = "longpassword";
//
// let app = get_app!(data).await;
//
// delete_user(NAME, &data).await;
//
// // 1. Register with email == None
// let msg = Register {
// username: NAME.into(),
// password: PASSWORD.into(),
// confirm_password: PASSWORD.into(),
// email: None,
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, V1_API_ROUTES.auth.register).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::OK);
//
// // correct form login
// let msg = Login {
// login: NAME.into(),
// password: PASSWORD.into(),
// };
//
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::FOUND);
// let headers = resp.headers();
// assert_eq!(headers.get(header::LOCATION).unwrap(), PAGES.home,);
//
// // incorrect form login
// let msg = Login {
// login: NAME.into(),
// password: NAME.into(),
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
//
// // non-existent form login
// let msg = Login {
// login: PASSWORD.into(),
// password: PASSWORD.into(),
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::NOT_FOUND);
// }
//}
//

150
src/pages/auth/mod.rs Normal file
View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use actix_web::*;
pub use super::{context, Footer, PAGES, TEMPLATES};
pub mod login;
pub mod register;
pub const HOME_BASE: &str = "homebase";
pub fn register_templates(t: &mut tera::Tera) {
if let Err(e) = t.add_template_files(vec![
("templates/pages/home/login.html", Some(login::LOGIN)),
(
"templates/pages/home/register.html",
Some(register::REGISTER),
),
("templates/pages/home/base.html", Some(HOME_BASE)),
]) {
println!("Parsing error(s): {}", e);
::std::process::exit(1);
};
}
pub fn services(cfg: &mut web::ServiceConfig) {
register::services(cfg);
login::services(cfg);
}
//#[post(path = "PAGES.auth.login")]
//pub async fn login_submit(
// id: Identity,
// payload: web::Form<runners::Login>,
// data: AppData,
//) -> PageResult<impl Responder> {
// let payload = payload.into_inner();
// match runners::login_runner(&payload, &data).await {
// Ok(username) => {
// id.remember(username);
// Ok(HttpResponse::Found()
// .insert_header((header::LOCATION, PAGES.home))
// .finish())
// }
// Err(e) => {
// let status = e.status_code();
// let heading = status.canonical_reason().unwrap_or("Error");
//
// Ok(HttpResponseBuilder::new(status)
// .content_type("text/html; charset=utf-8")
// .body(
// IndexPage::new(heading, &format!("{}", e))
// .render_once()
// .unwrap(),
// ))
// }
// }
//}
//
//#[cfg(test)]
//mod tests {
// use actix_web::test;
//
// use super::*;
//
// use crate::api::v1::auth::runners::{Login, Register};
// use crate::data::Data;
// use crate::tests::*;
// use crate::*;
// use actix_web::http::StatusCode;
//
// #[actix_rt::test]
// async fn auth_form_works() {
// let data = Data::new().await;
// const NAME: &str = "testuserform";
// const PASSWORD: &str = "longpassword";
//
// let app = get_app!(data).await;
//
// delete_user(NAME, &data).await;
//
// // 1. Register with email == None
// let msg = Register {
// username: NAME.into(),
// password: PASSWORD.into(),
// confirm_password: PASSWORD.into(),
// email: None,
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, V1_API_ROUTES.auth.register).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::OK);
//
// // correct form login
// let msg = Login {
// login: NAME.into(),
// password: PASSWORD.into(),
// };
//
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::FOUND);
// let headers = resp.headers();
// assert_eq!(headers.get(header::LOCATION).unwrap(), PAGES.home,);
//
// // incorrect form login
// let msg = Login {
// login: NAME.into(),
// password: NAME.into(),
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
//
// // non-existent form login
// let msg = Login {
// login: PASSWORD.into(),
// password: PASSWORD.into(),
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::NOT_FOUND);
// }
//}
//

151
src/pages/auth/register.rs Normal file
View File

@ -0,0 +1,151 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use actix_web::http::header::ContentType;
use crate::settings::Settings;
use crate::AppData;
pub use super::*;
pub struct Register;
pub const REGISTER: &str = "register";
impl Register {
pub fn page(s: &Settings) -> String {
let ctx = context(s);
TEMPLATES.render(REGISTER, &ctx).unwrap()
}
}
#[my_codegen::get(path = "PAGES.auth.register")]
pub async fn get_register(data: AppData) -> impl Responder {
let login = Register::page(&data.settings);
let html = ContentType::html();
HttpResponse::Ok().content_type(html).body(login)
}
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(get_register);
}
//#[post(path = "PAGES.auth.login")]
//pub async fn login_submit(
// id: Identity,
// payload: web::Form<runners::Login>,
// data: AppData,
//) -> PageResult<impl Responder> {
// let payload = payload.into_inner();
// match runners::login_runner(&payload, &data).await {
// Ok(username) => {
// id.remember(username);
// Ok(HttpResponse::Found()
// .insert_header((header::LOCATION, PAGES.home))
// .finish())
// }
// Err(e) => {
// let status = e.status_code();
// let heading = status.canonical_reason().unwrap_or("Error");
//
// Ok(HttpResponseBuilder::new(status)
// .content_type("text/html; charset=utf-8")
// .body(
// IndexPage::new(heading, &format!("{}", e))
// .render_once()
// .unwrap(),
// ))
// }
// }
//}
//
//#[cfg(test)]
//mod tests {
// use actix_web::test;
//
// use super::*;
//
// use crate::api::v1::auth::runners::{Login, Register};
// use crate::data::Data;
// use crate::tests::*;
// use crate::*;
// use actix_web::http::StatusCode;
//
// #[actix_rt::test]
// async fn auth_form_works() {
// let data = Data::new().await;
// const NAME: &str = "testuserform";
// const PASSWORD: &str = "longpassword";
//
// let app = get_app!(data).await;
//
// delete_user(NAME, &data).await;
//
// // 1. Register with email == None
// let msg = Register {
// username: NAME.into(),
// password: PASSWORD.into(),
// confirm_password: PASSWORD.into(),
// email: None,
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, V1_API_ROUTES.auth.register).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::OK);
//
// // correct form login
// let msg = Login {
// login: NAME.into(),
// password: PASSWORD.into(),
// };
//
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::FOUND);
// let headers = resp.headers();
// assert_eq!(headers.get(header::LOCATION).unwrap(), PAGES.home,);
//
// // incorrect form login
// let msg = Login {
// login: NAME.into(),
// password: NAME.into(),
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
//
// // non-existent form login
// let msg = Login {
// login: PASSWORD.into(),
// password: PASSWORD.into(),
// };
// let resp = test::call_service(
// &app,
// post_request!(&msg, PAGES.auth.login, FORM).to_request(),
// )
// .await;
// assert_eq!(resp.status(), StatusCode::NOT_FOUND);
// }
//}
//

128
src/pages/mod.rs Normal file
View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use actix_web::*;
use lazy_static::lazy_static;
use serde::*;
use tera::*;
use crate::settings::Settings;
use crate::static_assets::ASSETS;
use crate::{GIT_COMMIT_HASH, VERSION};
pub mod auth;
pub mod routes;
pub use routes::PAGES;
lazy_static! {
pub static ref TEMPLATES: Tera = {
let mut tera = Tera::default();
if let Err(e) = tera.add_template_files(vec![
("templates/components/base.html", Some("base")),
("templates/components/footer.html", Some("footer")),
("templates/components/nav.html", Some("nav")),
]) {
println!("Parsing error(s): {}", e);
::std::process::exit(1);
};
tera.autoescape_on(vec![".html", ".sql"]);
auth::register_templates(&mut tera);
tera
};
}
pub fn context(s: &Settings) -> Context {
let mut ctx = Context::new();
let footer = Footer::new(s);
ctx.insert("footer", &footer);
ctx.insert("page", &PAGES);
ctx.insert("assets", &*ASSETS);
ctx
}
pub fn init(s: &Settings) {
auth::login::Login::page(s);
auth::register::Register::page(s);
}
#[derive(Serialize)]
pub struct Footer<'a> {
version: &'a str,
admin_email: &'a str,
source_code: &'a str,
git_hash: &'a str,
}
impl<'a> Footer<'a> {
pub fn new(settings: &'a Settings) -> Self {
Self {
version: VERSION,
source_code: &settings.source_code,
admin_email: &settings.admin_email,
git_hash: &GIT_COMMIT_HASH[..8],
}
}
}
pub fn services(cfg: &mut web::ServiceConfig) {
auth::services(cfg);
}
#[cfg(test)]
mod tests {
use super::{init, Settings};
#[test]
fn templates_work() {
let settings = Settings::new().unwrap();
init(&settings);
}
}
#[cfg(test)]
mod http_page_tests {
use actix_web::http::StatusCode;
use actix_web::test;
use crate::data::Data;
use crate::db::BoxDB;
use crate::tests::*;
use crate::*;
use super::PAGES;
#[actix_rt::test]
async fn postgrest_templates_work() {
let (db, data) = sqlx_postgres::get_data().await;
templates_work(data, db).await;
}
#[actix_rt::test]
async fn sqlite_templates_work() {
let (db, data) = sqlx_sqlite::get_data().await;
templates_work(data, db).await;
}
async fn templates_work(data: Arc<Data>, db: BoxDB) {
let app = get_app!(data, db).await;
for file in [PAGES.auth.login, PAGES.auth.register].iter() {
let resp = get_request!(&app, file);
assert_eq!(resp.status(), StatusCode::OK);
}
}
}

59
src/pages/routes.rs Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use serde::*;
/// constant [Pages](Pages) instance
pub const PAGES: Pages = Pages::new();
#[derive(Serialize)]
/// Top-level routes data structure for V1 AP1
pub struct Pages {
/// Authentication routes
pub auth: Auth,
}
impl Pages {
/// create new instance of Routes
const fn new() -> Pages {
Pages { auth: Auth::new() }
}
}
#[derive(Serialize)]
/// Authentication routes
pub struct Auth {
/// logout route
pub logout: &'static str,
/// login route
pub login: &'static str,
/// registration route
pub register: &'static str,
}
impl Auth {
/// create new instance of Authentication route
pub const fn new() -> Auth {
let login = "/";
let logout = "/logout";
let register = "/join";
Auth {
logout,
login,
register,
}
}
}

View File

@ -20,5 +20,6 @@ use crate::api::v1;
pub fn services(cfg: &mut web::ServiceConfig) {
v1::services(cfg);
crate::pages::services(cfg);
crate::static_assets::services(cfg);
}

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="{{ assets.css }}" />
<title>Gists</title>
<title>{% block title %} {% endblock %}</title>
</head>
<body>
<header>{% include "nav" %}</header>
<main>{% block main %} {% endblock %}</main>
{% include "footer" %}
</body>
</html>

View File

@ -0,0 +1,46 @@
<footer>
<div class="footer__container">
<div class="footer__column">
<span class="license__conatiner">
<a class="license__link" rel="noreferrer" href="/docs" target="_blank"
>Docs</a
>
<span class="footer__column-divider--mobile-visible">|</span>
<a
class="license__link"
rel="noreferrer"
href="https://www.eff.org/issues/do-not-track/amp/"
target="_blank"
>No AMP</a
>
</span>
</div>
<div class="footer__column">
<a
href="/"
class="footer__link"
target="_blank"
rel="noopener"
title="RSS"
>
Home
</a>
<div class="footer__column-divider">|</div>
<a href="mailto:{{ footer.admin_email }}" class="footer__link"
>Contact Instance Maintainer</a
>
<div class="footer__column-divider">|</div>
<a
class="footer__link"
href="{{ footer.source_code }}"
target="_blank"
rel="noopener"
title="Source Code"
>
v{{ footer.version }}-{{ footer.git_hash }}
</a>
</div>
</div>
</footer>

View File

@ -0,0 +1,26 @@
<nav class="nav__container">
<input type="checkbox" class="nav__toggle" id="nav__toggle" />
<div class="nav__header">
<a class="nav__logo-container" href="/">
<p class="nav__home-btn">GitPad</p>
</a>
<label class="nav__hamburger-menu" for="nav__toggle">
<span class="nav__hamburger-inner"></span>
</label>
</div>
<div class="nav__spacer"></div>
<div class="nav__link-group">
<div class="nav__link-container">
<a class="nav__link" rel="noreferrer" href="/explore">Explore</a>
</div>
<div class="nav__link-container">
<a class="nav__link" rel="noreferrer" href="{{ page.auth.login }}">Login</a>
</div>
<div class="nav__link-container">
<a class="nav__link" rel="noreferrer" href="{{ page.auth.register }}">Register</a>
</div>
</div>
</nav>

View File

@ -0,0 +1,23 @@
{% extends 'base' %}
{% block title %}{% block title_name %} {% endblock %} | GitPad{% endblock %}
{% block main %}
<main>
<section class="main">
<div class="title">
<h1>GitPad</h1>
<p class="welcome">
Welcome to GitPad - A libre pastebin service! Currently implemented
features include:
<ul class="features">
<li>Git-powered version history</li>
<li>Comments on gists</li>
</ul>
</p>
</div>
</section>
<section class="login">
{% block login %} {% endblock %}
</section>
</main>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends 'homebase' %}
{% block login %}
<h2>Sign In</h2>
<form action="{{ page.auth.login }}" method="POST" class="form" accept-charset="utf-8">
<label class="form__label" for="login">
Username or Email
<input class="form__input" name="login" required id="login" type="text" />
</label>
<label class="form__label" for="password">
Password
<input
class="form__input"
name="password"
required
id="password"
type="password"
/>
</label>
<div class="form__action-container">
<a href="/forgot-password">Forgot password?</a>
<button class="form__submit" type="submit">Login</button>
</div>
</form>
<p class="form__alt-action">
New to GitPad?
<a href="{{ page.auth.register }}">Create an account </a>
</p>
{% endblock %}

View File

@ -0,0 +1,54 @@
{% extends 'homebase' %}
{% block title_name %}Sign Up {% endblock %}
{% block login %}
<h2>Sign Up</h2>
<form action="{{ page.auth.register }}" method="POST" class="form" accept-charset="utf-8">
<label class="form__label" for="username">
Username
<input
class="form__input"
name="username"
required
id="username"
type="text"
/>
</label>
<label class="form__label" for="email">
Email(optional)
<input class="form__input" name="email" id="email" type="email" />
</label>
<label class="form__label" for="password">
password
<input
class="form__input"
name="password"
required
id="password"
type="password"
/>
</label>
<label class="form__label" for="confirm_password">
Re-enter Password
<input
class="form__input"
name="confirm_password"
required
id="confirm_password"
type="password"
/>
</label>
<div class="form__action-container">
<a href="/forgot-password">Forgot password?</a>
<button class="form__submit" type="submit">Sign Up</button>
</div>
</form>
<p class="form__alt-action">
Already have an account?
<a href="{{ page.auth.login }}"> Login </a>
</p>
{% endblock %}