feat: stuff
This commit is contained in:
parent
2e2b01990e
commit
6d58fd47a1
11 changed files with 244 additions and 366 deletions
347
Cargo.lock
generated
347
Cargo.lock
generated
|
|
@ -8,20 +8,20 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"base64",
|
"base64",
|
||||||
|
"bcrypt",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"hex",
|
"hex",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"quick-xml 0.37.2",
|
"quick-xml",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rust-s3",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"thiserror 2.0.11",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -139,52 +139,12 @@ dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "attohttpc"
|
|
||||||
version = "0.28.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07a9b245ba0739fc90935094c29adbaee3f977218b5fb95e822e261cda7f56a3"
|
|
||||||
dependencies = [
|
|
||||||
"http 1.2.0",
|
|
||||||
"log",
|
|
||||||
"native-tls",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aws-creds"
|
|
||||||
version = "0.37.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f84143206b9c72b3c5cb65415de60c7539c79cd1559290fddec657939131be0"
|
|
||||||
dependencies = [
|
|
||||||
"attohttpc",
|
|
||||||
"home",
|
|
||||||
"log",
|
|
||||||
"quick-xml 0.32.0",
|
|
||||||
"rust-ini",
|
|
||||||
"serde",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
"time",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aws-region"
|
|
||||||
version = "0.25.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e9aed3f9c7eac9be28662fdb3b0f4d1951e812f7c64fed4f0327ba702f459b3b"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.74"
|
version = "0.3.74"
|
||||||
|
|
@ -212,6 +172,19 @@ 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 = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bcrypt"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92758ad6077e4c76a6cadbce5005f666df70d4f13b19976b1a8062eef880040f"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"blowfish",
|
||||||
|
"getrandom 0.3.1",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "binascii"
|
name = "binascii"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
@ -245,6 +218,16 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blowfish"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.17.0"
|
version = "3.17.0"
|
||||||
|
|
@ -299,6 +282,16 @@ dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
|
@ -314,26 +307,6 @@ version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-random"
|
|
||||||
version = "0.1.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
|
||||||
dependencies = [
|
|
||||||
"const-random-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-random-macro"
|
|
||||||
version = "0.1.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom 0.2.15",
|
|
||||||
"once_cell",
|
|
||||||
"tiny-keccak",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cookie"
|
name = "cookie"
|
||||||
version = "0.18.1"
|
version = "0.18.1"
|
||||||
|
|
@ -400,12 +373,6 @@ version = "0.8.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crunchy"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
@ -434,7 +401,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
"serde",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -493,15 +459,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dlv-list"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
|
|
||||||
dependencies = [
|
|
||||||
"const-random",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dotenvy"
|
name = "dotenvy"
|
||||||
version = "0.15.7"
|
version = "0.15.7"
|
||||||
|
|
@ -639,7 +596,6 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-executor",
|
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
|
@ -690,17 +646,6 @@ version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-macro"
|
|
||||||
version = "0.3.31"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
|
@ -722,7 +667,6 @@ dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-macro",
|
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -808,12 +752,6 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.14.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.2"
|
version = "0.15.2"
|
||||||
|
|
@ -831,7 +769,7 @@ version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
|
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown 0.15.2",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -954,19 +892,6 @@ dependencies = [
|
||||||
"want",
|
"want",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper-tls"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"hyper",
|
|
||||||
"native-tls",
|
|
||||||
"tokio",
|
|
||||||
"tokio-native-tls",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.61"
|
version = "0.1.61"
|
||||||
|
|
@ -1136,7 +1061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
|
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.15.2",
|
"hashbrown",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1146,6 +1071,15 @@ version = "0.1.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
|
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-terminal"
|
name = "is-terminal"
|
||||||
version = "0.4.15"
|
version = "0.4.15"
|
||||||
|
|
@ -1256,17 +1190,6 @@ dependencies = [
|
||||||
"regex-automata 0.1.10",
|
"regex-automata 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "maybe-async"
|
|
||||||
version = "0.2.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
|
@ -1277,12 +1200,6 @@ dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "md5"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
|
|
@ -1295,15 +1212,6 @@ version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minidom"
|
|
||||||
version = "0.15.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f45614075738ce1b77a1768912a60c0227525971b03e09122a05b8a34a2a6278"
|
|
||||||
dependencies = [
|
|
||||||
"rxml",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
|
@ -1492,16 +1400,6 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ordered-multimap"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
|
|
||||||
dependencies = [
|
|
||||||
"dlv-list",
|
|
||||||
"hashbrown 0.14.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -1662,16 +1560,6 @@ dependencies = [
|
||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quick-xml"
|
|
||||||
version = "0.32.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.37.2"
|
version = "0.37.2"
|
||||||
|
|
@ -1895,54 +1783,6 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-ini"
|
|
||||||
version = "0.21.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"ordered-multimap",
|
|
||||||
"trim-in-place",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-s3"
|
|
||||||
version = "0.35.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c3df3f353b1f4209dcf437d777cda90279c397ab15a0cd6fd06bd32c88591533"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"aws-creds",
|
|
||||||
"aws-region",
|
|
||||||
"base64",
|
|
||||||
"bytes",
|
|
||||||
"cfg-if",
|
|
||||||
"futures",
|
|
||||||
"hex",
|
|
||||||
"hmac",
|
|
||||||
"http 0.2.12",
|
|
||||||
"hyper",
|
|
||||||
"hyper-tls",
|
|
||||||
"log",
|
|
||||||
"maybe-async",
|
|
||||||
"md5",
|
|
||||||
"minidom",
|
|
||||||
"native-tls",
|
|
||||||
"percent-encoding",
|
|
||||||
"quick-xml 0.32.0",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"sha2",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
"time",
|
|
||||||
"tokio",
|
|
||||||
"tokio-native-tls",
|
|
||||||
"tokio-stream",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
|
|
@ -1968,23 +1808,6 @@ version = "1.0.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rxml"
|
|
||||||
version = "0.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a98f186c7a2f3abbffb802984b7f1dfd65dac8be1aafdaabbca4137f53f0dff7"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"rxml_validation",
|
|
||||||
"smartstring",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rxml_validation"
|
|
||||||
version = "0.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "22a197350ece202f19a166d1ad6d9d6de145e1d2a8ef47db299abe164dbd7530"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.19"
|
version = "1.0.19"
|
||||||
|
|
@ -2162,17 +1985,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smartstring"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"static_assertions",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.8"
|
version = "0.5.8"
|
||||||
|
|
@ -2222,6 +2034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0"
|
checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"chrono",
|
||||||
"crc",
|
"crc",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"either",
|
"either",
|
||||||
|
|
@ -2230,7 +2043,7 @@ dependencies = [
|
||||||
"futures-intrusive",
|
"futures-intrusive",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hashbrown 0.15.2",
|
"hashbrown",
|
||||||
"hashlink",
|
"hashlink",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
|
|
@ -2242,7 +2055,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.11",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -2299,6 +2112,7 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"chrono",
|
||||||
"crc",
|
"crc",
|
||||||
"digest",
|
"digest",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
|
@ -2325,7 +2139,7 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror 2.0.11",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
@ -2340,6 +2154,7 @@ dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"chrono",
|
||||||
"crc",
|
"crc",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"etcetera",
|
"etcetera",
|
||||||
|
|
@ -2362,7 +2177,7 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror 2.0.11",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
@ -2374,6 +2189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540"
|
checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
|
"chrono",
|
||||||
"flume",
|
"flume",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
|
@ -2414,12 +2230,6 @@ dependencies = [
|
||||||
"loom",
|
"loom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_assertions"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stringprep"
|
name = "stringprep"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
|
@ -2473,33 +2283,13 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "1.0.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl 1.0.69",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.11"
|
version = "2.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
|
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl 2.0.11",
|
"thiserror-impl",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "1.0.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2554,15 +2344,6 @@ dependencies = [
|
||||||
"time-core",
|
"time-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tiny-keccak"
|
|
||||||
version = "2.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
|
||||||
dependencies = [
|
|
||||||
"crunchy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
|
|
@ -2616,16 +2397,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-native-tls"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
|
||||||
dependencies = [
|
|
||||||
"native-tls",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.17"
|
version = "0.1.17"
|
||||||
|
|
@ -2752,12 +2523,6 @@ dependencies = [
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "trim-in-place"
|
|
||||||
version = "0.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try-lock"
|
name = "try-lock"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ dotenvy = "0.15.7"
|
||||||
once_cell = "1.20.3"
|
once_cell = "1.20.3"
|
||||||
serde_json = "1.0.139"
|
serde_json = "1.0.139"
|
||||||
chrono = { version = "0.4.39", features = ["serde"] }
|
chrono = { version = "0.4.39", features = ["serde"] }
|
||||||
rust-s3 = "0.35.1"
|
|
||||||
argon2 = "0.5.3"
|
argon2 = "0.5.3"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
bytemuck = "1.21.0"
|
bytemuck = "1.21.0"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
thiserror = "2.0.11"
|
thiserror = "2.0.11"
|
||||||
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-native-tls", "postgres" ] }
|
bcrypt = "0.17.0"
|
||||||
|
sqlx = { version = "0.8.3", features = [ "runtime-tokio", "tls-native-tls", "postgres", "chrono" ] }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use argon2::password_hash::SaltString;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use base64::prelude::BASE64_STANDARD;
|
use base64::prelude::BASE64_STANDARD;
|
||||||
use bytemuck::bytes_of;
|
use bytemuck::bytes_of;
|
||||||
|
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::{async_trait, Request};
|
use rocket::{async_trait, Request};
|
||||||
|
|
@ -34,18 +35,21 @@ const INVALID_TOKEN_ERRORS: Errors<'static> = Errors{
|
||||||
|
|
||||||
// optimization note: add token caching
|
// optimization note: add token caching
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: i32,
|
pub pid: i32,
|
||||||
pub name: String,
|
pub username: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
pub birthdate: chrono::NaiveDate,
|
pub birthdate: NaiveDate,
|
||||||
pub timezone: String,
|
pub timezone: String,
|
||||||
pub email: String,
|
pub email: String,
|
||||||
|
pub account_level: i32,
|
||||||
|
pub email_verified_since: Option<NaiveDateTime>,
|
||||||
pub gender: String,
|
pub gender: String,
|
||||||
pub country: String,
|
pub country: String,
|
||||||
pub language: String,
|
pub language: String,
|
||||||
pub marketing_allowed: bool,
|
pub marketing_allowed: bool,
|
||||||
|
pub off_device_allowed: bool,
|
||||||
pub region: i32,
|
pub region: i32,
|
||||||
pub mii_identifier: String
|
pub mii_data: String
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_nintendo_hash(pid: i32, text_password: &str) -> String{
|
fn generate_nintendo_hash(pid: i32, text_password: &str) -> String{
|
||||||
|
|
@ -59,40 +63,39 @@ fn generate_nintendo_hash(pid: i32, text_password: &str) -> String{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User{
|
impl User{
|
||||||
fn generate_nintendo_hash(&self, text_password: &str) -> String{
|
pub async fn get_by_username(name: &str, pool: &Pool) -> Option<Self>{
|
||||||
generate_nintendo_hash(self.id, text_password)
|
sqlx::query_as!(
|
||||||
|
Self,
|
||||||
|
"SELECT * FROM users WHERE username = $1",
|
||||||
|
name
|
||||||
|
).fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_password(&self, cleartext_password: &str) -> (bool, bool){
|
fn generate_nintendo_hash(&self, text_password: &str) -> String{
|
||||||
let Ok(hash) = PasswordHash::new(&self.password) else {
|
generate_nintendo_hash(self.pid, text_password)
|
||||||
error!("invalid password in database for user with pid: {}", self.id);
|
}
|
||||||
|
|
||||||
if self.password == self.generate_nintendo_hash(cleartext_password){
|
pub fn verify_cleartext_password(&self, cleartext_password: &str) -> Option<bool>{
|
||||||
return (true, true)
|
let nintendo_hash = self.generate_nintendo_hash(cleartext_password);
|
||||||
}
|
|
||||||
|
|
||||||
return (false, false)
|
self.verify_hashed_password(cleartext_password)
|
||||||
};
|
}
|
||||||
|
|
||||||
let argon = Argon2::default();
|
pub fn verify_hashed_password(&self, hashed_password: &str) -> Option<bool>{
|
||||||
|
bcrypt::verify(hashed_password, &self.password).ok()
|
||||||
(argon.verify_password(cleartext_password.as_bytes(), &hash).is_ok(), false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_password(pid: i32, cleartext_password: &str) -> Option<String>{
|
pub fn generate_password(pid: i32, cleartext_password: &str) -> Option<String>{
|
||||||
let password = generate_nintendo_hash(pid, cleartext_password);
|
let password = generate_nintendo_hash(pid, cleartext_password);
|
||||||
|
|
||||||
let salt = SaltString::generate(&mut OsRng);
|
bcrypt::hash(password, 10).ok()
|
||||||
let argon = Argon2::default();
|
|
||||||
|
|
||||||
let pw = argon.hash_password(password.as_bytes(), &salt).ok()?;
|
|
||||||
|
|
||||||
Some(pw.to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn read_basic_auth_token(connection: &mut AsyncMysqlConnection, token: &str) -> Option<User> {
|
pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<User> {
|
||||||
let data = BASE64_STANDARD.decode(&token).ok()?;
|
let data = BASE64_STANDARD.decode(&token).ok()?;
|
||||||
|
|
||||||
let decoded_basic_token = String::from_utf8(data).ok()?;
|
let decoded_basic_token = String::from_utf8(data).ok()?;
|
||||||
|
|
@ -101,28 +104,22 @@ pub async fn read_basic_auth_token(connection: &mut AsyncMysqlConnection, token:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mut user: User = users
|
let mut user = sqlx::query_as!(
|
||||||
.filter(name.eq(login_username))
|
User,
|
||||||
.select(User::as_select())
|
"SELECT * FROM users WHERE username = $1",
|
||||||
.first(connection)
|
login_username
|
||||||
.await.ok()?;
|
).fetch_one(connection).await.ok()?;
|
||||||
|
|
||||||
let (password_valid, upgrade_password) = user.verify_password(&login_password);
|
let password_valid = user.verify_cleartext_password(&login_password);
|
||||||
|
|
||||||
if password_valid{
|
|
||||||
if upgrade_password{
|
|
||||||
user.password = generate_password(&login_password).unwrap();
|
|
||||||
|
|
||||||
user = connection.update_and_fetch(&user).await.ok()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if password_valid == Some(true){
|
||||||
Some(user)
|
Some(user)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_bearer_auth_token(connection: &mut AsyncMysqlConnection, token: &str) -> Option<User> {
|
async fn read_bearer_auth_token(connection: &Pool, token: &str) -> Option<User> {
|
||||||
let data = BASE64_STANDARD.decode(&token).ok()?;
|
let data = BASE64_STANDARD.decode(&token).ok()?;
|
||||||
|
|
||||||
warn!("bearer token login currently unsupported");
|
warn!("bearer token login currently unsupported");
|
||||||
|
|
@ -137,15 +134,13 @@ impl<'r> FromRequest<'r> for User{
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
||||||
let pool: &Pool = request.rocket().state().unwrap();
|
let pool: &Pool = request.rocket().state().unwrap();
|
||||||
|
|
||||||
let mut connection = pool.get().await.unwrap();
|
|
||||||
|
|
||||||
let auth = request_try!(request.headers().get("Authorization").next().ok_or(INVALID_TOKEN_ERRORS));
|
let auth = request_try!(request.headers().get("Authorization").next().ok_or(INVALID_TOKEN_ERRORS));
|
||||||
|
|
||||||
let (auth_type, token) = request_try!(auth.split_once(' ').ok_or(INVALID_TOKEN_ERRORS));
|
let (auth_type, token) = request_try!(auth.split_once(' ').ok_or(INVALID_TOKEN_ERRORS));
|
||||||
|
|
||||||
let user = match auth_type{
|
let user = match auth_type{
|
||||||
"Basic" => read_basic_auth_token(&mut connection, token).await,
|
"Basic" => read_basic_auth_token(pool, token).await,
|
||||||
"Bearer" => read_bearer_auth_token(&mut connection, token).await,
|
"Bearer" => read_bearer_auth_token(pool, token).await,
|
||||||
_ => return Outcome::Error((Status::BadRequest, INVALID_TOKEN_ERRORS)),
|
_ => return Outcome::Error((Status::BadRequest, INVALID_TOKEN_ERRORS)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
5
src/data_wrapper.rs
Normal file
5
src/data_wrapper.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
trait DataWrapper{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ mod nnid;
|
||||||
mod account;
|
mod account;
|
||||||
mod error;
|
mod error;
|
||||||
mod dsresponse;
|
mod dsresponse;
|
||||||
|
mod data_wrapper;
|
||||||
|
|
||||||
type Pool = sqlx::Pool<Postgres>;
|
type Pool = sqlx::Pool<Postgres>;
|
||||||
|
|
||||||
|
|
@ -42,7 +43,7 @@ async fn launch() -> _ {
|
||||||
.to_string()
|
.to_string()
|
||||||
));
|
));
|
||||||
|
|
||||||
response.adjoin_header(Header::new("Content-Type", "text/xml; charset=utf-8"));
|
//response.adjoin_header(Header::new("Content-Type", "text/xml; charset=utf-8"));
|
||||||
|
|
||||||
|
|
||||||
response.remove_header("x-content-type-options");
|
response.remove_header("x-content-type-options");
|
||||||
|
|
@ -55,6 +56,8 @@ async fn launch() -> _ {
|
||||||
nnid::agreements::get_agreement,
|
nnid::agreements::get_agreement,
|
||||||
nnid::timezones::get_timezone,
|
nnid::timezones::get_timezone,
|
||||||
nnid::person_exists::person_exists,
|
nnid::person_exists::person_exists,
|
||||||
nnid::email::validate
|
nnid::email::validate,
|
||||||
|
nnid::create_account::create_account,
|
||||||
|
nnid::oauth::generate_token::generate_token
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
use chrono::NaiveDate;
|
use chrono::{Datelike, NaiveDate};
|
||||||
use rocket::{post, State};
|
use rocket::{post, State};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::account::account::{generate_password, User};
|
use crate::account::account::{generate_password, User};
|
||||||
use crate::error::Errors;
|
use crate::error::Errors;
|
||||||
|
use crate::nnid::pid_distribution::next_pid;
|
||||||
use crate::Pool;
|
use crate::Pool;
|
||||||
use crate::xml::{Xml, YesNoVal};
|
use crate::xml::{Xml, YesNoVal};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Email{
|
pub struct Email{
|
||||||
address: Box<str>
|
address: Box<str>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
struct Mii{
|
pub struct Mii{
|
||||||
name: Box<str>,
|
name: Box<str>,
|
||||||
primary: YesNoVal,
|
primary: YesNoVal,
|
||||||
data: Box<str>,
|
data: Box<str>,
|
||||||
|
|
@ -20,7 +23,7 @@ struct Mii{
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename(serialize = "person"))]
|
#[serde(rename(serialize = "person"))]
|
||||||
struct AccountCreationData{
|
pub struct AccountCreationData{
|
||||||
birth_date: NaiveDate,
|
birth_date: NaiveDate,
|
||||||
user_id: Box<str>,
|
user_id: Box<str>,
|
||||||
password: Box<str>,
|
password: Box<str>,
|
||||||
|
|
@ -28,21 +31,28 @@ struct AccountCreationData{
|
||||||
language: Box<str>,
|
language: Box<str>,
|
||||||
tz_name: Box<str>,
|
tz_name: Box<str>,
|
||||||
email: Email,
|
email: Email,
|
||||||
|
mii: Mii,
|
||||||
gender: Box<str>,
|
gender: Box<str>,
|
||||||
marketing_flag: YesNoVal,
|
marketing_flag: YesNoVal,
|
||||||
|
off_device_flag: YesNoVal,
|
||||||
region: i32
|
region: i32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(rename(serialize = "person"))]
|
#[serde(rename(serialize = "person"))]
|
||||||
struct AccountCreationResponseData{
|
pub struct AccountCreationResponseData{
|
||||||
pid: i32
|
pid: i32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/v1/api/people", data="<data>")]
|
#[post("/v1/api/people", data="<data>")]
|
||||||
async fn create_account(database: &State<Pool>, data: Xml<AccountCreationData>) -> Result<Xml<AccountCreationResponseData>, Errors>{
|
pub async fn create_account(database: &State<Pool>, data: Xml<AccountCreationData>) -> Result<Xml<AccountCreationResponseData>, Option<Errors>>{
|
||||||
let database = database.inner();
|
let database = database.inner();
|
||||||
|
|
||||||
|
// its fine to crash here if we cant get the next pid as that is in my opinion a dead state
|
||||||
|
// anyways as noone can register anymore, EVER
|
||||||
|
|
||||||
|
let pid = next_pid(database).await;
|
||||||
|
|
||||||
let AccountCreationData {
|
let AccountCreationData {
|
||||||
user_id,
|
user_id,
|
||||||
password,
|
password,
|
||||||
|
|
@ -52,22 +62,27 @@ async fn create_account(database: &State<Pool>, data: Xml<AccountCreationData>)
|
||||||
email: Email{
|
email: Email{
|
||||||
address
|
address
|
||||||
},
|
},
|
||||||
|
mii: Mii{
|
||||||
|
data,
|
||||||
|
..
|
||||||
|
},
|
||||||
marketing_flag,
|
marketing_flag,
|
||||||
gender,
|
gender,
|
||||||
region,
|
region,
|
||||||
country,
|
country,
|
||||||
|
off_device_flag,
|
||||||
..
|
..
|
||||||
} = *data;
|
} = data.0;
|
||||||
|
|
||||||
|
|
||||||
|
let password = generate_password(pid, &password).ok_or(None)?;
|
||||||
|
|
||||||
let new_account = sqlx::query("
|
sqlx::query!("
|
||||||
INSERT INTO users.users (
|
INSERT INTO users (
|
||||||
pid,
|
pid,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
birthdate,
|
birthdate,
|
||||||
birthdate,
|
|
||||||
timezone,
|
timezone,
|
||||||
email,
|
email,
|
||||||
country,
|
country,
|
||||||
|
|
@ -75,26 +90,34 @@ async fn create_account(database: &State<Pool>, data: Xml<AccountCreationData>)
|
||||||
marketing_allowed,
|
marketing_allowed,
|
||||||
off_device_allowed,
|
off_device_allowed,
|
||||||
region,
|
region,
|
||||||
|
gender,
|
||||||
mii_data
|
mii_data
|
||||||
) VALUES (
|
) VALUES (
|
||||||
?,?,?,?,?,?,?,?,?,?
|
$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13
|
||||||
)
|
)
|
||||||
");
|
",
|
||||||
|
pid,
|
||||||
|
user_id.as_ref(),
|
||||||
|
password,
|
||||||
|
birth_date,
|
||||||
|
tz_name.as_ref(),
|
||||||
|
address.as_ref(),
|
||||||
|
country.as_ref(),
|
||||||
|
language.as_ref(),
|
||||||
|
marketing_flag.0,
|
||||||
|
off_device_flag.0,
|
||||||
|
region,
|
||||||
|
gender.as_ref(),
|
||||||
|
data.as_ref()
|
||||||
|
).execute(database).await.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let pid = connection.transaction::<_, diesel::result::Error, _>(|conn| Box::pin(async move{
|
Ok(
|
||||||
use crate::schema::users::dsl::*;
|
Xml(AccountCreationResponseData{
|
||||||
|
pid
|
||||||
diesel::insert_into(users)
|
})
|
||||||
.values(&new_account)
|
)
|
||||||
.returning(User::as_returning())
|
|
||||||
.get_result(conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})).await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,6 @@ pub mod agreements;
|
||||||
pub mod timezones;
|
pub mod timezones;
|
||||||
pub mod person_exists;
|
pub mod person_exists;
|
||||||
pub mod email;
|
pub mod email;
|
||||||
mod create_account;
|
pub mod create_account;
|
||||||
|
pub mod oauth;
|
||||||
|
mod pid_distribution;
|
||||||
|
|
|
||||||
52
src/nnid/oauth/generate_token.rs
Normal file
52
src/nnid/oauth/generate_token.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
use rocket::{post, FromForm, State};
|
||||||
|
use rocket::form::Form;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use crate::account::account::User;
|
||||||
|
use crate::error::{Error, Errors};
|
||||||
|
use crate::Pool;
|
||||||
|
|
||||||
|
const ACCOUNT_ID_OR_PASSWORD_ERRORS: Errors = Errors{
|
||||||
|
error: &[
|
||||||
|
Error{
|
||||||
|
code: "0106",
|
||||||
|
message: "Invalid account ID or password"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const ACCOUNT_BANNED_ERRORS: Errors = Errors{
|
||||||
|
error: &[
|
||||||
|
Error{
|
||||||
|
code: "0122",
|
||||||
|
message: "Device has been banned by game server"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(FromForm)]
|
||||||
|
pub struct TokenRequestData<'a>{
|
||||||
|
grant_type: &'a str,
|
||||||
|
user_id: &'a str,
|
||||||
|
password: &'a str,
|
||||||
|
password_type: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/v1/api/oauth20/access_token/generate", data="<data>")]
|
||||||
|
pub async fn generate_token(pool: &State<Pool>, data: Form<TokenRequestData<'_>>) -> Result<(), Option<Errors<'static>>>{
|
||||||
|
let pool = pool.inner();
|
||||||
|
|
||||||
|
let user = User::get_by_username(data.user_id, pool).await
|
||||||
|
.ok_or(Some(ACCOUNT_ID_OR_PASSWORD_ERRORS))?;
|
||||||
|
|
||||||
|
if !user.verify_hashed_password(&data.password).is_some_and(|v| v){
|
||||||
|
return Err(Some(ACCOUNT_ID_OR_PASSWORD_ERRORS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.account_level < 0{
|
||||||
|
return Err(Some(ACCOUNT_BANNED_ERRORS));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
1
src/nnid/oauth/mod.rs
Normal file
1
src/nnid/oauth/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod generate_token;
|
||||||
|
|
@ -4,16 +4,19 @@ use crate::error::{Error, Errors};
|
||||||
use crate::Pool;
|
use crate::Pool;
|
||||||
use crate::xml::Xml;
|
use crate::xml::Xml;
|
||||||
|
|
||||||
|
|
||||||
#[get("/v1/api/people/<username>")]
|
#[get("/v1/api/people/<username>")]
|
||||||
pub async fn person_exists(database: &State<Pool>, username: &str) -> Result<(), Errors<'static>>{
|
pub async fn person_exists(database: &State<Pool>, username: &str) -> Result<(), Errors<'static>>{
|
||||||
let database = database.inner();
|
let database = database.inner();
|
||||||
|
|
||||||
let exists: bool = sqlx::query_as!(
|
let exists = sqlx::query!(
|
||||||
bool,
|
"SELECT EXISTS(SELECT 1 FROM users WHERE username = $1 ) as exists",
|
||||||
"SELECT EXISTS(SELECT 1 FROM users.users WHERE username = ? )",
|
|
||||||
username
|
username
|
||||||
).fetch_one(database)
|
).fetch_one(database)
|
||||||
.await
|
.await
|
||||||
|
.ok()
|
||||||
|
.map(|v| v.exists)
|
||||||
|
.flatten()
|
||||||
.unwrap_or(true);
|
.unwrap_or(true);
|
||||||
|
|
||||||
if exists {
|
if exists {
|
||||||
|
|
|
||||||
29
src/nnid/pid_distribution.rs
Normal file
29
src/nnid/pid_distribution.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use crate::Pool;
|
||||||
|
|
||||||
|
pub async fn next_pid(pool: &Pool) -> i32{
|
||||||
|
loop {
|
||||||
|
let next_pid = sqlx::query!("SELECT nextval('pid_counter') as pid")
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.expect("unable to get next pid")
|
||||||
|
.pid
|
||||||
|
.expect("unable to get next pid") as i32;
|
||||||
|
|
||||||
|
let already_exists = sqlx::query!(
|
||||||
|
"SELECT EXISTS(select 1 from users where pid = $1)",
|
||||||
|
next_pid
|
||||||
|
).fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.map(|v| v.exists)
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or(true);
|
||||||
|
|
||||||
|
if !already_exists{
|
||||||
|
break next_pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue