fuck WIP shit
This commit is contained in:
parent
8a900fe7a7
commit
75e616201b
12
.sqlx/query-0e032978b712ce5ad586ab15bdc4efe82935f5f681c3cf54cbeaf845b70c7ff6.json
generated
Normal file
12
.sqlx/query-0e032978b712ce5ad586ab15bdc4efe82935f5f681c3cf54cbeaf845b70c7ff6.json
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "INSERT INTO users(KEY, NAME) VALUES($1, $2);",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "0e032978b712ce5ad586ab15bdc4efe82935f5f681c3cf54cbeaf845b70c7ff6"
|
||||||
|
}
|
||||||
20
.sqlx/query-1bb4a0ea9450533e5d08db156a7440258c22cc6d14848d247a322a1ff2c73810.json
generated
Normal file
20
.sqlx/query-1bb4a0ea9450533e5d08db156a7440258c22cc6d14848d247a322a1ff2c73810.json
generated
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT key FROM users WHERE name = $1;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "KEY",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "1bb4a0ea9450533e5d08db156a7440258c22cc6d14848d247a322a1ff2c73810"
|
||||||
|
}
|
||||||
20
.sqlx/query-1ea5285096550f447c4ec8eed2aaf623fe2887015ea22f1579f477bc1aeb7a21.json
generated
Normal file
20
.sqlx/query-1ea5285096550f447c4ec8eed2aaf623fe2887015ea22f1579f477bc1aeb7a21.json
generated
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT CREDENTIAL FROM CREDENTIALS WHERE USER_ID = $1;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "CREDENTIAL",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "1ea5285096550f447c4ec8eed2aaf623fe2887015ea22f1579f477bc1aeb7a21"
|
||||||
|
}
|
||||||
20
.sqlx/query-390c853d2fe8777bebbbe3ed5dae7f25415da7e916934e3cf983a9f590804a41.json
generated
Normal file
20
.sqlx/query-390c853d2fe8777bebbbe3ed5dae7f25415da7e916934e3cf983a9f590804a41.json
generated
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT credential FROM CREDENTIALS WHERE user_id = $1;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "CREDENTIAL",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "390c853d2fe8777bebbbe3ed5dae7f25415da7e916934e3cf983a9f590804a41"
|
||||||
|
}
|
||||||
12
.sqlx/query-62612ca2817b12ef492a450be661ad58037c7d5b433cba9855fff21461b9e7fc.json
generated
Normal file
12
.sqlx/query-62612ca2817b12ef492a450be661ad58037c7d5b433cba9855fff21461b9e7fc.json
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "INSERT INTO CREDENTIALS(user_id, credential) VALUES($1, $2);",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "62612ca2817b12ef492a450be661ad58037c7d5b433cba9855fff21461b9e7fc"
|
||||||
|
}
|
||||||
@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\nSELECT NAME, KEY FROM USERS WHERE NAME = ?1 AND KEY = ?2\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "NAME",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "KEY",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "6b379715355f3443d66111020be5c3c7ec2a57c9789d04485b998fd934d6b0a8"
|
|
||||||
}
|
|
||||||
12
.sqlx/query-810f3f513dd59e14557979e50b72b0b40fa6a7ea682a74a806ebf2be30c6e4cc.json
generated
Normal file
12
.sqlx/query-810f3f513dd59e14557979e50b72b0b40fa6a7ea682a74a806ebf2be30c6e4cc.json
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "UPDATE CREDENTIALS SET credential = $1 WHERE user_id = $2 AND credential = $3;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 3
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "810f3f513dd59e14557979e50b72b0b40fa6a7ea682a74a806ebf2be30c6e4cc"
|
||||||
|
}
|
||||||
20
.sqlx/query-db45619d7a6d50b845ed8f31f58b525ae6b4de88eba24b0d4126ba54d07b0731.json
generated
Normal file
20
.sqlx/query-db45619d7a6d50b845ed8f31f58b525ae6b4de88eba24b0d4126ba54d07b0731.json
generated
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT COUNT(KEY) AS count FROM users WHERE KEY = $1;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "count",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Int"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "db45619d7a6d50b845ed8f31f58b525ae6b4de88eba24b0d4126ba54d07b0731"
|
||||||
|
}
|
||||||
20
.sqlx/query-e8b97d3910dbfb9ea1dd5d6d8a105886df0573e55c9ac62ac1cc8ecd15ae9801.json
generated
Normal file
20
.sqlx/query-e8b97d3910dbfb9ea1dd5d6d8a105886df0573e55c9ac62ac1cc8ecd15ae9801.json
generated
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT NAME FROM users WHERE KEY = $1;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "NAME",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "e8b97d3910dbfb9ea1dd5d6d8a105886df0573e55c9ac62ac1cc8ecd15ae9801"
|
||||||
|
}
|
||||||
20
.sqlx/query-f1948f31683e327633ad9ae6b56764a0965331c825faf0a86ca18331e4d8ebdf.json
generated
Normal file
20
.sqlx/query-f1948f31683e327633ad9ae6b56764a0965331c825faf0a86ca18331e4d8ebdf.json
generated
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT KEY FROM users WHERE NAME = $1;",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "KEY",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "f1948f31683e327633ad9ae6b56764a0965331c825faf0a86ca18331e4d8ebdf"
|
||||||
|
}
|
||||||
402
Cargo.lock
generated
402
Cargo.lock
generated
@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.6"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
@ -97,6 +97,45 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asn1-rs"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33"
|
||||||
|
dependencies = [
|
||||||
|
"asn1-rs-derive",
|
||||||
|
"asn1-rs-impl",
|
||||||
|
"displaydoc",
|
||||||
|
"nom 7.1.3",
|
||||||
|
"num-traits",
|
||||||
|
"rusticata-macros",
|
||||||
|
"thiserror",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asn1-rs-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asn1-rs-impl"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.74"
|
version = "0.1.74"
|
||||||
@ -105,7 +144,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -126,6 +165,7 @@ dependencies = [
|
|||||||
"minijinja",
|
"minijinja",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
"totp-rs",
|
"totp-rs",
|
||||||
@ -135,6 +175,7 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"webauthn-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -151,6 +192,7 @@ checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core",
|
"axum-core",
|
||||||
|
"axum-macros",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
@ -198,6 +240,18 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum-macros"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.69"
|
version = "0.3.69"
|
||||||
@ -219,6 +273,12 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa"
|
checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.21.5"
|
version = "0.21.5"
|
||||||
@ -237,6 +297,17 @@ 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 = "base64urlsafedata"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18b3d30abb74120a9d5267463b9e0045fdccc4dd152e7249d966612dc1721384"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.21.5",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -300,6 +371,23 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "compact_jwt"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7aa76ef19968577838a34d02848136bb9b6bdbfd7675fb968fe9c931bc434b33"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"base64urlsafedata",
|
||||||
|
"hex",
|
||||||
|
"openssl",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const-oid"
|
name = "const-oid"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
@ -376,6 +464,12 @@ dependencies = [
|
|||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.7.8"
|
version = "0.7.8"
|
||||||
@ -387,6 +481,20 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "der-parser"
|
||||||
|
version = "7.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82"
|
||||||
|
dependencies = [
|
||||||
|
"asn1-rs",
|
||||||
|
"displaydoc",
|
||||||
|
"nom 7.1.3",
|
||||||
|
"num-bigint",
|
||||||
|
"num-traits",
|
||||||
|
"rusticata-macros",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@ -409,6 +517,17 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "displaydoc"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dotenvy"
|
name = "dotenvy"
|
||||||
version = "0.15.7"
|
version = "0.15.7"
|
||||||
@ -486,6 +605,21 @@ version = "1.0.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -567,7 +701,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -645,6 +779,12 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "1.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.2"
|
version = "0.14.2"
|
||||||
@ -871,9 +1011,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
version = "0.26.0"
|
version = "0.27.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326"
|
checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
@ -1008,6 +1148,17 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint-dig"
|
name = "num-bigint-dig"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@ -1075,12 +1226,59 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oid-registry"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a"
|
||||||
|
dependencies = [
|
||||||
|
"asn1-rs",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-macros",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.101"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1148,7 +1346,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1204,18 +1402,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.69"
|
version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.33"
|
version = "1.0.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@ -1335,6 +1533,15 @@ version = "0.1.23"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusticata-macros"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
|
||||||
|
dependencies = [
|
||||||
|
"nom 7.1.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.21"
|
version = "0.38.21"
|
||||||
@ -1368,29 +1575,39 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.190"
|
version = "1.0.197"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_cbor_2"
|
||||||
version = "1.0.190"
|
version = "0.12.0-dev"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
checksum = "b46d75f449e01f1eddbe9b00f432d616fbbd899b809c837d0fbc380496a0dd55"
|
||||||
|
dependencies = [
|
||||||
|
"half",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.197"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.107"
|
version = "1.0.114"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@ -1532,9 +1749,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx"
|
name = "sqlx"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33"
|
checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"sqlx-macros",
|
"sqlx-macros",
|
||||||
@ -1545,9 +1762,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-core"
|
name = "sqlx-core"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d"
|
checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"atoi",
|
"atoi",
|
||||||
@ -1555,7 +1772,6 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"crc",
|
"crc",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"dotenvy",
|
|
||||||
"either",
|
"either",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@ -1585,9 +1801,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-macros"
|
name = "sqlx-macros"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec"
|
checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1598,9 +1814,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-macros-core"
|
name = "sqlx-macros-core"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc"
|
checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"either",
|
"either",
|
||||||
@ -1623,9 +1839,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-mysql"
|
name = "sqlx-mysql"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db"
|
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64 0.21.5",
|
"base64 0.21.5",
|
||||||
@ -1665,9 +1881,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-postgres"
|
name = "sqlx-postgres"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624"
|
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64 0.21.5",
|
"base64 0.21.5",
|
||||||
@ -1692,7 +1908,6 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
|
||||||
"sha2",
|
"sha2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
@ -1704,9 +1919,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-sqlite"
|
name = "sqlx-sqlite"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f"
|
checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"flume",
|
"flume",
|
||||||
@ -1722,6 +1937,7 @@ dependencies = [
|
|||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
|
"urlencoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1760,9 +1976,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.38"
|
version = "2.0.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
|
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1775,6 +1991,18 @@ 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 = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "synstructure"
|
||||||
|
version = "0.12.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tap"
|
name = "tap"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -1811,7 +2039,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1895,7 +2123,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2078,7 +2306,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2153,6 +2381,12 @@ version = "1.10.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode_categories"
|
name = "unicode_categories"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -2168,8 +2402,15 @@ dependencies = [
|
|||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna",
|
"idna",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urlencoding"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@ -2178,6 +2419,7 @@ checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"rand",
|
"rand",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2204,6 +2446,56 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webauthn-rs"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2db00711c712414e93b019c4596315085792215bc2ac2d5872f9e8913b0a6316"
|
||||||
|
dependencies = [
|
||||||
|
"base64urlsafedata",
|
||||||
|
"serde",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
"uuid",
|
||||||
|
"webauthn-rs-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webauthn-rs-core"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "294c78c83f12153a51e1cf1e6970b5da1397645dada39033a9c3173a8fc4fc2b"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"base64urlsafedata",
|
||||||
|
"compact_jwt",
|
||||||
|
"der-parser",
|
||||||
|
"nom 7.1.3",
|
||||||
|
"openssl",
|
||||||
|
"rand",
|
||||||
|
"serde",
|
||||||
|
"serde_cbor_2",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
"uuid",
|
||||||
|
"webauthn-rs-proto",
|
||||||
|
"x509-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webauthn-rs-proto"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d24e638361a63ba5c0a0be6a60229490fcdf33740ed63df5bb6bdb627b52a138"
|
||||||
|
dependencies = [
|
||||||
|
"base64urlsafedata",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "whoami"
|
name = "whoami"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
@ -2305,23 +2597,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "x509-parser"
|
||||||
version = "0.7.18"
|
version = "0.13.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ede7d7c7970ca2215b8c1ccf4d4f354c4733201dfaaba72d44ae5b37472e4901"
|
checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c"
|
||||||
|
dependencies = [
|
||||||
|
"asn1-rs",
|
||||||
|
"base64 0.13.1",
|
||||||
|
"data-encoding",
|
||||||
|
"der-parser",
|
||||||
|
"lazy_static",
|
||||||
|
"nom 7.1.3",
|
||||||
|
"oid-registry",
|
||||||
|
"rusticata-macros",
|
||||||
|
"thiserror",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.7.18"
|
version = "0.7.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4b27b1bb92570f989aac0ab7e9cbfbacdd65973f7ee920d9f0e71ebac878fd0b"
|
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.38",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -6,9 +6,9 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = {version = "0.7.4", features = [ "default", "form" ]}
|
axum = {version = "0.7.4", features = [ "default", "form", "tracing", "macros" ]}
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.0", features = ["full"] }
|
||||||
sqlx = { version = "0.7", features = ["runtime-tokio", "sqlite"] }
|
sqlx = { version = "0.7.4", features = ["runtime-tokio", "sqlite"] }
|
||||||
tower-cookies = "0.10.0"
|
tower-cookies = "0.10.0"
|
||||||
serde = "1.0.190"
|
serde = "1.0.190"
|
||||||
uuid = { version = "1.5.0", features = ["v4", "fast-rng"] }
|
uuid = { version = "1.5.0", features = ["v4", "fast-rng"] }
|
||||||
@ -20,3 +20,5 @@ askama = "0.10"
|
|||||||
minijinja = "1.0.9"
|
minijinja = "1.0.9"
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
tower-sessions = "0.11.0"
|
tower-sessions = "0.11.0"
|
||||||
|
webauthn-rs = { version = "0.4.8", features = [ "danger-allow-state-serialisation" ]}
|
||||||
|
serde_json = "1.0.114"
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::env;
|
||||||
|
pub const COOKIE_NAME: Lazy<String> =
|
||||||
|
Lazy::new(|| env::var("COOKIE_NAME").unwrap_or("aaron_auth".to_string()));
|
||||||
|
pub const SESSION_ACTIVE_TIME: Lazy<u64> = Lazy::new(|| {
|
||||||
|
env::var("SESSION_ACTIVE_TIME")
|
||||||
|
.ok()
|
||||||
|
.and_then(|value| value.parse().ok())
|
||||||
|
.unwrap_or(600)
|
||||||
|
});
|
||||||
|
pub const COOKIE_DOMAIN: Lazy<String> =
|
||||||
|
Lazy::new(|| env::var("DOMAIN").ok().unwrap_or(".aaronhu.cn".to_owned()));
|
||||||
|
pub const LOGIN_PAGE_HTML: &str = include_str!("../loginpage.html");
|
||||||
|
pub const PORT: Lazy<String> = Lazy::new(|| env::var("PORT").unwrap_or("3000".to_string()));
|
||||||
|
pub const DATABASE_URL: Lazy<String> =
|
||||||
|
Lazy::new(|| env::var("DATABASE_URL").unwrap_or("".to_owned()));
|
||||||
|
pub const RP_ID: Lazy<String> =
|
||||||
|
Lazy::new(|| env::var("RP_ID").unwrap_or("localhost".to_owned()));
|
||||||
|
pub const RP_ORIGIN: Lazy<String> =
|
||||||
|
Lazy::new(|| env::var("RP_ORIGIN").unwrap_or("http://localhost:8080".to_owned()));
|
||||||
|
pub const RP_NAME: Lazy<String> =
|
||||||
|
Lazy::new(|| env::var("RP_NAME").unwrap_or("Localhost".to_owned()));
|
||||||
@ -1,14 +1,52 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::time::Instant;
|
use sqlx::SqlitePool;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Instant;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use webauthn_rs::prelude::Url;
|
||||||
|
use webauthn_rs::{Webauthn, WebauthnBuilder};
|
||||||
|
|
||||||
|
use crate::config::{DATABASE_URL, RP_ID, RP_NAME, RP_ORIGIN};
|
||||||
|
|
||||||
pub struct ServerState {
|
pub struct ServerState {
|
||||||
pub db: sqlx::Pool<sqlx::Sqlite>,
|
pub db: sqlx::Pool<sqlx::Sqlite>,
|
||||||
pub session: Mutex<HashMap<Uuid, Instant>>,
|
pub session: Mutex<HashMap<Uuid, Instant>>,
|
||||||
|
pub webauthn: Arc<Webauthn>,
|
||||||
// started: Instant,
|
// started: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ServerState {
|
||||||
|
pub async fn new() -> Self {
|
||||||
|
// Effective domain name.
|
||||||
|
let rp_id = RP_ID;
|
||||||
|
// Url containing the effective domain name
|
||||||
|
// MUST include the port number!
|
||||||
|
let rp_origin = Url::parse(&RP_ORIGIN).expect("Invalid URL");
|
||||||
|
let builder = WebauthnBuilder::new(&rp_id, &rp_origin).expect("Invalid configuration");
|
||||||
|
|
||||||
|
// Now, with the builder you can define other options.
|
||||||
|
// Set a "nice" relying party name. Has no security properties and
|
||||||
|
// may be changed in the future.
|
||||||
|
let _RP_NAME = RP_NAME.to_string();
|
||||||
|
let builder = builder.rp_name(&_RP_NAME);
|
||||||
|
|
||||||
|
// Consume the builder and create our webauthn instance.
|
||||||
|
let webauthn = Arc::new(builder.build().expect("Invalid configuration"));
|
||||||
|
|
||||||
|
let session = Mutex::new(HashMap::new());
|
||||||
|
let db = SqlitePool::connect(&DATABASE_URL)
|
||||||
|
.await
|
||||||
|
.expect("DB OPEN FAILURE"); // our router
|
||||||
|
ServerState {
|
||||||
|
db,
|
||||||
|
session,
|
||||||
|
webauthn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, sqlx::FromRow, Debug)]
|
#[derive(Deserialize, sqlx::FromRow, Debug)]
|
||||||
pub struct UserLoginForm {
|
pub struct UserLoginForm {
|
||||||
#[sqlx(rename = "NAME")]
|
#[sqlx(rename = "NAME")]
|
||||||
@ -23,4 +61,4 @@ pub struct User {
|
|||||||
pub username: String,
|
pub username: String,
|
||||||
#[sqlx(rename = "KEY")]
|
#[sqlx(rename = "KEY")]
|
||||||
pub uid: String,
|
pub uid: String,
|
||||||
}
|
}
|
||||||
|
|||||||
58
src/main.rs
58
src/main.rs
@ -1,36 +1,22 @@
|
|||||||
use axum::extract::Query;
|
|
||||||
use axum::http::{HeaderMap, HeaderValue};
|
|
||||||
use axum::response::{Html, Redirect};
|
|
||||||
use axum::{extract::State, http::StatusCode, response::IntoResponse, routing::get, Form, Router};
|
use axum::{routing::{get, post, Route}, Router};
|
||||||
use entities::*;
|
use entities::*;
|
||||||
use minijinja::{context, Environment};
|
|
||||||
use once_cell::sync::Lazy;
|
use services::{auth::{self, finish_authentication, start_authentication}, gc_task, login, login_page};
|
||||||
use services::{auth, gc_task, login, login_page, login_with_passkey};
|
|
||||||
use sqlx::sqlite::SqlitePool;
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use tower_cookies::{CookieManagerLayer};
|
||||||
use std::{borrow::BorrowMut, env};
|
|
||||||
use std::{collections::HashMap, str::FromStr};
|
|
||||||
use tower_cookies::{Cookie, CookieManagerLayer, Cookies};
|
|
||||||
use tower_http::trace::{self, TraceLayer};
|
use tower_http::trace::{self, TraceLayer};
|
||||||
use tower_sessions::{Expiry, MemoryStore, Session, SessionManagerLayer};
|
use tower_sessions::{Expiry, MemoryStore, SessionManagerLayer};
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
use uuid::Uuid;
|
|
||||||
|
pub mod config;
|
||||||
pub mod controllers;
|
pub mod controllers;
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
pub mod services;
|
pub mod services;
|
||||||
static COOKIE_NAME: Lazy<String> =
|
use config::{PORT};
|
||||||
Lazy::new(|| env::var("COOKIE_NAME").unwrap_or("aaron_auth".to_string()));
|
|
||||||
const SESSION_ACTIVE_TIME: Lazy<u64> = Lazy::new(|| {
|
|
||||||
env::var("SESSION_ACTIVE_TIME")
|
|
||||||
.ok()
|
|
||||||
.and_then(|value| value.parse().ok())
|
|
||||||
.unwrap_or(600)
|
|
||||||
});
|
|
||||||
const COOKIE_DOMAIN: Lazy<String> =
|
|
||||||
Lazy::new(|| env::var("DOMAIN").ok().unwrap_or(".aaronhu.cn".to_owned()));
|
|
||||||
const LOGIN_PAGE_HTML: &str = include_str!("../loginpage.html");
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
// 初始化日志记录器
|
// 初始化日志记录器
|
||||||
@ -39,17 +25,15 @@ async fn main() {
|
|||||||
let session_layer = SessionManagerLayer::new(session_store)
|
let session_layer = SessionManagerLayer::new(session_store)
|
||||||
.with_secure(false)
|
.with_secure(false)
|
||||||
.with_expiry(Expiry::OnSessionEnd);
|
.with_expiry(Expiry::OnSessionEnd);
|
||||||
let pool = SqlitePool::connect(&env::var("DATABASE_URL").expect("DB URL NOT SPECIFIED"))
|
let state = Arc::new(ServerState::new().await);
|
||||||
.await
|
|
||||||
.expect("DB OPEN FAILURE"); // our router
|
|
||||||
let state = Arc::new(ServerState {
|
|
||||||
db: pool,
|
|
||||||
session: HashMap::new().into(),
|
|
||||||
// started: std::time::Instant::now(),
|
|
||||||
});
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/auth", get(auth)) // http://127.0.0.1:3000
|
.route("/auth", get(crate::services::auth_otp)) // http://127.0.0.1:3000
|
||||||
.route("/login", get(login_page).post(login))
|
.route("/login", get(login_page).post(login))
|
||||||
|
.route("/register_start/:username", post(auth::start_register))
|
||||||
|
.route("/register_finish/:username", post(auth::finish_register))
|
||||||
|
.route("/webauthn_login_start/:username", post(start_authentication))
|
||||||
|
.route("/webauthn_login_finish/:username", post(finish_authentication))
|
||||||
|
|
||||||
.layer(
|
.layer(
|
||||||
TraceLayer::new_for_http()
|
TraceLayer::new_for_http()
|
||||||
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
|
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
|
||||||
@ -58,11 +42,11 @@ async fn main() {
|
|||||||
.with_state(state.clone())
|
.with_state(state.clone())
|
||||||
.layer(CookieManagerLayer::new())
|
.layer(CookieManagerLayer::new())
|
||||||
.layer(session_layer);
|
.layer(session_layer);
|
||||||
let port = env::var("PORT").unwrap_or("3000".to_string());
|
let aaronhu = Router::new().nest("/aaron/", app);
|
||||||
let port = port.parse::<u16>().unwrap_or(3000);
|
let port = PORT.parse::<u16>().unwrap_or(3000);
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], port));
|
let addr = SocketAddr::from(([127, 0, 0, 1], port));
|
||||||
// run it with hyper on localhost:3000
|
// run it with hyper on localhost:3000
|
||||||
tokio::spawn(gc_task(state.clone()));
|
tokio::spawn(gc_task(state.clone()));
|
||||||
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, aaronhu).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
413
src/services/auth.rs
Normal file
413
src/services/auth.rs
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use axum::debug_handler;
|
||||||
|
use axum::extract::State;
|
||||||
|
use axum::{
|
||||||
|
extract::{Json, Path},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use std::time::Instant;
|
||||||
|
use tower_cookies::Cookies;
|
||||||
|
use tower_sessions::Session;
|
||||||
|
use tracing::*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Webauthn RS auth handlers.
|
||||||
|
* These files use webauthn to process the data received from each route, and are closely tied to axum
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 1. Import the prelude - this contains everything needed for the server to function.
|
||||||
|
use webauthn_rs::prelude::*;
|
||||||
|
|
||||||
|
use crate::config::{COOKIE_NAME, SESSION_ACTIVE_TIME};
|
||||||
|
use crate::ServerState;
|
||||||
|
|
||||||
|
// 2. The first step a client (user) will carry out is requesting a credential to be
|
||||||
|
// registered. We need to provide a challenge for this. The work flow will be:
|
||||||
|
//
|
||||||
|
// ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||||
|
// │ Authenticator │ │ Browser │ │ Site │
|
||||||
|
// └───────────────┘ └───────────────┘ └───────────────┘
|
||||||
|
// │ │ │
|
||||||
|
// │ │ 1. Start Reg │
|
||||||
|
// │ │─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶│
|
||||||
|
// │ │ │
|
||||||
|
// │ │ 2. Challenge │
|
||||||
|
// │ │◀ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
|
||||||
|
// │ │ │
|
||||||
|
// │ 3. Select Token │ │
|
||||||
|
// ─ ─ ─│◀ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│ │
|
||||||
|
// 4. Verify │ │ │ │
|
||||||
|
// │ 4. Yield PubKey │ │
|
||||||
|
// └ ─ ─▶│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶ │
|
||||||
|
// │ │ │
|
||||||
|
// │ │ 5. Send Reg Opts │
|
||||||
|
// │ │─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶│─ ─ ─
|
||||||
|
// │ │ │ │ 5. Verify
|
||||||
|
// │ │ │ PubKey
|
||||||
|
// │ │ │◀─ ─ ┘
|
||||||
|
// │ │ │─ ─ ─
|
||||||
|
// │ │ │ │ 6. Persist
|
||||||
|
// │ │ │ Credential
|
||||||
|
// │ │ │◀─ ─ ┘
|
||||||
|
// │ │ │
|
||||||
|
// │ │ │
|
||||||
|
//
|
||||||
|
// In this step, we are responding to the start reg(istration) request, and providing
|
||||||
|
// the challenge to the browser.
|
||||||
|
|
||||||
|
// TODO - Improve error handling and messages
|
||||||
|
fn auth_user(cookie_content:String,session_table:&mut HashMap<Uuid, Instant>) -> bool {
|
||||||
|
let Ok(uuid) = Uuid::parse_str(&cookie_content) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Some(expire) = session_table.get(&uuid) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if *expire <= Instant::now() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
session_table.insert(uuid, Instant::now()+Duration::from_secs(*SESSION_ACTIVE_TIME));
|
||||||
|
tracing::info!("valid cookie {}",uuid);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
#[debug_handler]
|
||||||
|
pub async fn start_register(
|
||||||
|
State(state): State<Arc<ServerState>>,
|
||||||
|
cookies: Cookies,
|
||||||
|
session: Session,
|
||||||
|
Path(username): Path<String>,
|
||||||
|
) -> Result<Json<CreationChallengeResponse>, String> {
|
||||||
|
tracing::info!("Start register");
|
||||||
|
// todo!("Auth User");
|
||||||
|
let Some(cookie_content) = cookies.get(&COOKIE_NAME) else {
|
||||||
|
return Err(WebauthnError::AuthenticationFailure.to_string());
|
||||||
|
};
|
||||||
|
let mut session_table = state.session.lock().await;
|
||||||
|
if !auth_user(cookie_content.value().to_string(), &mut session_table){
|
||||||
|
return Err(WebauthnError::AuthenticationFailure.to_string());
|
||||||
|
}
|
||||||
|
// Remove any previous registrations that may have occurred from the session.
|
||||||
|
let _ = session
|
||||||
|
.remove::<(String, Uuid, PasskeyRegistration)>("reg_state")
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?;
|
||||||
|
let pool = &state.db;
|
||||||
|
let username = username.clone();
|
||||||
|
let (user_id, exclude_credentials): (Uuid, Option<Vec<CredentialID>>) =
|
||||||
|
match sqlx::query!("SELECT key FROM users WHERE name = $1;", username)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?
|
||||||
|
{
|
||||||
|
Some(record) => {
|
||||||
|
let uid = record.KEY.clone();
|
||||||
|
let records = sqlx::query!(
|
||||||
|
"SELECT credential FROM CREDENTIALS WHERE user_id = $1;",
|
||||||
|
uid
|
||||||
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?;
|
||||||
|
|
||||||
|
(
|
||||||
|
Uuid::parse_str(&record.KEY)
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?,
|
||||||
|
Some(
|
||||||
|
records
|
||||||
|
.iter()
|
||||||
|
.map(|record| serde_json::from_str::<Passkey>(&record.CREDENTIAL))
|
||||||
|
.collect::<Result<Vec<Passkey>, _>>()
|
||||||
|
.map_err(|_| WebauthnError::CredentialPersistenceError.to_string())?
|
||||||
|
.iter()
|
||||||
|
.map(|passkey| passkey.cred_id().clone())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => (Uuid::new_v4(), None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = match state.webauthn.start_passkey_registration(
|
||||||
|
user_id,
|
||||||
|
&username,
|
||||||
|
&username,
|
||||||
|
exclude_credentials,
|
||||||
|
) {
|
||||||
|
Ok((ccr, reg_state)) => {
|
||||||
|
// Note that due to the session store in use being a server side memory store, this is
|
||||||
|
// safe to store the reg_state into the session since it is not client controlled and
|
||||||
|
// not open to replay attacks. If this was a cookie store, this would be UNSAFE.
|
||||||
|
session
|
||||||
|
.insert("reg_state", (username, user_id, reg_state))
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::ChallengePersistenceError.to_string())?;
|
||||||
|
Json(ccr)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!("challenge_register -> {:?}", e);
|
||||||
|
return Err(WebauthnError::ChallengePersistenceError.to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. The browser has completed it's steps and the user has created a public key
|
||||||
|
// on their device. Now we have the registration options sent to us, and we need
|
||||||
|
// to verify these and persist them.
|
||||||
|
|
||||||
|
pub async fn finish_register(
|
||||||
|
State(state): State<Arc<ServerState>>,
|
||||||
|
session: Session,
|
||||||
|
Json(reg): Json<RegisterPublicKeyCredential>,
|
||||||
|
) -> Result<impl IntoResponse, String> {
|
||||||
|
info!("Confirming registration....");
|
||||||
|
let pool = &state.db;
|
||||||
|
let Ok(Some((user_name, user_id, reg_state))) = session
|
||||||
|
.get::<(String, Uuid, PasskeyRegistration)>("reg_state")
|
||||||
|
.await
|
||||||
|
else {
|
||||||
|
return Err(WebauthnError::AuthenticationFailure.to_string()); //Corrupt Session
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = session.remove::<(Uuid, PasskeyAuthentication)>("reg_state").await;
|
||||||
|
|
||||||
|
let res = match state.webauthn.finish_passkey_registration(®, ®_state) {
|
||||||
|
Ok(key) => {
|
||||||
|
info!("Passkey is okay");
|
||||||
|
let uid = &user_id.to_string();
|
||||||
|
let username = &user_name.to_string();
|
||||||
|
// Check if the user_id already exists
|
||||||
|
let record = sqlx::query!(
|
||||||
|
"SELECT COUNT(KEY) AS count FROM users WHERE KEY = $1;",
|
||||||
|
uid
|
||||||
|
)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?;
|
||||||
|
|
||||||
|
// If the user doesn't exist, insert them into the users table
|
||||||
|
if record.count == 0
|
||||||
|
&& sqlx::query!(
|
||||||
|
"INSERT INTO users(KEY, NAME) VALUES($1, $2);",
|
||||||
|
uid,
|
||||||
|
username
|
||||||
|
)
|
||||||
|
.execute(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::UserNotPresent.to_string())?
|
||||||
|
.rows_affected()
|
||||||
|
!= 1
|
||||||
|
{
|
||||||
|
return Err(WebauthnError::AuthenticationFailure.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialise the key
|
||||||
|
let serialised_key = serde_json::ser::to_string(&key)
|
||||||
|
.map_err(|_| WebauthnError::CredentialPersistenceError.to_string())?;
|
||||||
|
|
||||||
|
// Insert the key into the auth table
|
||||||
|
if sqlx::query!(
|
||||||
|
"INSERT INTO CREDENTIALS(user_id, credential) VALUES($1, $2);",
|
||||||
|
uid,
|
||||||
|
serialised_key
|
||||||
|
)
|
||||||
|
.execute(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::UserNotPresent.to_string())?
|
||||||
|
.rows_affected()
|
||||||
|
!= 1
|
||||||
|
{
|
||||||
|
return Err(WebauthnError::AuthenticationFailure.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusCode::OK
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!("challenge_register -> {:?}", e);
|
||||||
|
StatusCode::BAD_REQUEST
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Now that our public key has been registered, we can authenticate a user and verify
|
||||||
|
// that they are the holder of that security token. The work flow is similar to registration.
|
||||||
|
//
|
||||||
|
// ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||||
|
// │ Authenticator │ │ Browser │ │ Site │
|
||||||
|
// └───────────────┘ └───────────────┘ └───────────────┘
|
||||||
|
// │ │ │
|
||||||
|
// │ │ 1. Start Auth │
|
||||||
|
// │ │─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶│
|
||||||
|
// │ │ │
|
||||||
|
// │ │ 2. Challenge │
|
||||||
|
// │ │◀ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
|
||||||
|
// │ │ │
|
||||||
|
// │ 3. Select Token │ │
|
||||||
|
// ─ ─ ─│◀ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│ │
|
||||||
|
// 4. Verify │ │ │ │
|
||||||
|
// │ 4. Yield Sig │ │
|
||||||
|
// └ ─ ─▶│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶ │
|
||||||
|
// │ │ 5. Send Auth │
|
||||||
|
// │ │ Opts │
|
||||||
|
// │ │─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶│─ ─ ─
|
||||||
|
// │ │ │ │ 5. Verify
|
||||||
|
// │ │ │ Sig
|
||||||
|
// │ │ │◀─ ─ ┘
|
||||||
|
// │ │ │
|
||||||
|
// │ │ │
|
||||||
|
//
|
||||||
|
// The user indicates the wish to start authentication and we need to provide a challenge.
|
||||||
|
|
||||||
|
pub async fn start_authentication(
|
||||||
|
State(state): State<Arc<ServerState>>,
|
||||||
|
session: Session,
|
||||||
|
Path(user_name): Path<String>,
|
||||||
|
) -> Result<impl IntoResponse, String> {
|
||||||
|
info!("Start Authentication");
|
||||||
|
let pool = &state.db;
|
||||||
|
// Remove any previous authentication that may have occurred from the session.
|
||||||
|
let _ = session.remove::<(Uuid, PasskeyAuthentication)>("auth_state");
|
||||||
|
let user_id = sqlx::query!("SELECT KEY FROM users WHERE NAME = $1;", user_name)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::UserNotPresent.to_string())?
|
||||||
|
.KEY;
|
||||||
|
|
||||||
|
let records = sqlx::query!(
|
||||||
|
"SELECT credential FROM CREDENTIALS WHERE user_id = $1;",
|
||||||
|
user_id
|
||||||
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?;
|
||||||
|
|
||||||
|
if records.is_empty() {
|
||||||
|
return Err(WebauthnError::CredentialNotFound.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let allow_credentials: Vec<Passkey> = records
|
||||||
|
.iter()
|
||||||
|
.map(|record| serde_json::de::from_str::<Passkey>(&record.CREDENTIAL))
|
||||||
|
.collect::<Result<Vec<Passkey>, _>>()
|
||||||
|
.map_err(|_| WebauthnError::CredentialPersistenceError.to_string())?;
|
||||||
|
|
||||||
|
let res = match state
|
||||||
|
.webauthn
|
||||||
|
.start_passkey_authentication(&allow_credentials)
|
||||||
|
{
|
||||||
|
Ok((rcr, auth_state)) => {
|
||||||
|
// Note that due to the session store in use being a server side memory store, this is
|
||||||
|
// safe to store the auth_state into the session since it is not client controlled and
|
||||||
|
// not open to replay attacks. If this was a cookie store, this would be UNSAFE.
|
||||||
|
session
|
||||||
|
.insert("auth_state", (&user_id, auth_state))
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?;
|
||||||
|
Json(rcr)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!("challenge_authenticate -> {:?}", e);
|
||||||
|
return Err(WebauthnError::MismatchedChallenge.to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. The browser and user have completed their part of the processing. Only in the
|
||||||
|
// case that the webauthn authenticate call returns Ok, is authentication considered
|
||||||
|
// a success. If the browser does not complete this call, or *any* error occurs,
|
||||||
|
// this is an authentication failure.
|
||||||
|
|
||||||
|
pub async fn finish_authentication(
|
||||||
|
State(state): State<Arc<ServerState>>,
|
||||||
|
session: Session,
|
||||||
|
Json(auth): Json<PublicKeyCredential>,
|
||||||
|
) -> Result<impl IntoResponse, String> {
|
||||||
|
let pool = &state.db;
|
||||||
|
let (user_id, auth_state): (Uuid, PasskeyAuthentication) = session
|
||||||
|
.get("auth_state")
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.ok_or(WebauthnError::AuthenticationFailure.to_string())?;
|
||||||
|
|
||||||
|
let _ = session.remove::<(Uuid, PasskeyAuthentication)>("auth_state");
|
||||||
|
|
||||||
|
let res = match state
|
||||||
|
.webauthn
|
||||||
|
.finish_passkey_authentication(&auth, &auth_state)
|
||||||
|
{
|
||||||
|
Ok(auth_result) => {
|
||||||
|
let uid = user_id.clone().to_string();
|
||||||
|
let records = sqlx::query!(
|
||||||
|
"SELECT CREDENTIAL FROM CREDENTIALS WHERE USER_ID = $1;",
|
||||||
|
uid
|
||||||
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticatorDataMissingExtension.to_string())?;
|
||||||
|
if records.is_empty() {
|
||||||
|
return Err(WebauthnError::UserNotPresent.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
for record in records {
|
||||||
|
let mut credential = serde_json::from_str::<Passkey>(&record.CREDENTIAL)
|
||||||
|
.map_err(|_| WebauthnError::CredentialExistCheckError.to_string())?;
|
||||||
|
|
||||||
|
if credential.cred_id() == auth_result.cred_id() {
|
||||||
|
credential.update_credential(&auth_result);
|
||||||
|
|
||||||
|
let credential = serde_json::to_string(&credential)
|
||||||
|
.map_err(|_| WebauthnError::CredentialPersistenceError.to_string())?;
|
||||||
|
|
||||||
|
if sqlx::query!(
|
||||||
|
"UPDATE CREDENTIALS SET credential = $1 WHERE user_id = $2 AND credential = $3;",
|
||||||
|
credential,
|
||||||
|
uid,
|
||||||
|
record.CREDENTIAL
|
||||||
|
)
|
||||||
|
.execute(pool)
|
||||||
|
.await.is_ok_and(|e|e.rows_affected() !=1 )
|
||||||
|
{
|
||||||
|
return Err(WebauthnError::AuthenticationFailure.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_name = sqlx::query!(
|
||||||
|
"SELECT NAME FROM users WHERE KEY = $1;",
|
||||||
|
uid
|
||||||
|
)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::AuthenticationFailure.to_string())?;
|
||||||
|
// Add our own values to the session
|
||||||
|
session
|
||||||
|
.insert("user_id", user_id)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::InvalidUserUniqueId.to_string())?;
|
||||||
|
session
|
||||||
|
.insert("user_name", user_name.NAME)
|
||||||
|
.await
|
||||||
|
.map_err(|_| WebauthnError::InvalidUsername.to_string())?;
|
||||||
|
|
||||||
|
StatusCode::OK
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!("challenge_register -> {:?}", e);
|
||||||
|
StatusCode::BAD_REQUEST
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("Authentication Successful!");
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
@ -1,22 +1,23 @@
|
|||||||
use axum::extract::Query;
|
use axum::extract::Query;
|
||||||
use axum::http::{HeaderMap, HeaderValue};
|
use axum::http::{HeaderMap, HeaderValue};
|
||||||
use axum::response::{Html, Redirect};
|
use axum::response::{Html, Redirect};
|
||||||
use axum::{extract::State, http::StatusCode, response::IntoResponse, routing::get, Form, Router};
|
use axum::{extract::State, http::StatusCode, response::IntoResponse, Form};
|
||||||
use minijinja::{context, Environment};
|
use minijinja::{context, Environment};
|
||||||
use serde::Deserialize;
|
|
||||||
use sqlx::sqlite::SqlitePool;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::{borrow::BorrowMut, env};
|
use std::borrow::BorrowMut;
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use std::{collections::HashMap, str::FromStr};
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use tower_cookies::{Cookie, CookieManagerLayer, Cookies};
|
use tower_cookies::{Cookie, Cookies};
|
||||||
use tower_http::trace::{self, TraceLayer};
|
|
||||||
use tracing::Level;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{ServerState, UserLoginForm, COOKIE_DOMAIN, COOKIE_NAME, LOGIN_PAGE_HTML, SESSION_ACTIVE_TIME};
|
use crate::{ServerState, UserLoginForm};
|
||||||
|
use super::config::{COOKIE_DOMAIN, COOKIE_NAME, LOGIN_PAGE_HTML, SESSION_ACTIVE_TIME};
|
||||||
|
|
||||||
|
|
||||||
pub async fn gc_task(state: Arc<ServerState>) {
|
pub async fn gc_task(state: Arc<ServerState>) {
|
||||||
@ -32,7 +33,7 @@ pub async fn gc_task(state: Arc<ServerState>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理/auth
|
// 处理/auth
|
||||||
pub async fn auth(
|
pub async fn auth_otp(
|
||||||
State(state): State<Arc<ServerState>>,
|
State(state): State<Arc<ServerState>>,
|
||||||
// Form(frm): Form<UserLoginForm>,
|
// Form(frm): Form<UserLoginForm>,
|
||||||
cookies: Cookies,
|
cookies: Cookies,
|
||||||
@ -69,9 +70,9 @@ pub async fn login(
|
|||||||
};
|
};
|
||||||
tracing::info!("{:?}", &frm);
|
tracing::info!("{:?}", &frm);
|
||||||
let target = sqlx::query_as::<_, UserLoginForm>(
|
let target = sqlx::query_as::<_, UserLoginForm>(
|
||||||
r#"
|
r"
|
||||||
SELECT NAME, KEY FROM USERS WHERE NAME = ?
|
SELECT NAME, KEY FROM USERS WHERE NAME = ?
|
||||||
"#,
|
",
|
||||||
)
|
)
|
||||||
.bind(frm.username)
|
.bind(frm.username)
|
||||||
.fetch_optional(&mut *conn)
|
.fetch_optional(&mut *conn)
|
||||||
@ -86,7 +87,7 @@ pub async fn login(
|
|||||||
s,
|
s,
|
||||||
Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME),
|
Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME),
|
||||||
);
|
);
|
||||||
let mut new_cookie = Cookie::new(&*COOKIE_NAME, s.to_string());
|
let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), s.to_string());
|
||||||
new_cookie.set_domain(COOKIE_DOMAIN.to_string());
|
new_cookie.set_domain(COOKIE_DOMAIN.to_string());
|
||||||
cookies.add(new_cookie);
|
cookies.add(new_cookie);
|
||||||
if let Some(original_uri) = params.get("original_url") {
|
if let Some(original_uri) = params.get("original_url") {
|
||||||
@ -166,9 +167,9 @@ pub async fn login_with_passkey(
|
|||||||
};
|
};
|
||||||
tracing::info!("{:?}", &frm);
|
tracing::info!("{:?}", &frm);
|
||||||
let target = sqlx::query_as::<_, UserLoginForm>(
|
let target = sqlx::query_as::<_, UserLoginForm>(
|
||||||
r#"
|
r"
|
||||||
SELECT NAME, KEY FROM USERS WHERE NAME = ?
|
SELECT NAME, KEY FROM USERS WHERE NAME = ?
|
||||||
"#,
|
",
|
||||||
)
|
)
|
||||||
.bind(frm.username)
|
.bind(frm.username)
|
||||||
.fetch_optional(&mut *conn)
|
.fetch_optional(&mut *conn)
|
||||||
@ -183,7 +184,7 @@ pub async fn login_with_passkey(
|
|||||||
s,
|
s,
|
||||||
Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME),
|
Instant::now() + Duration::from_secs(*SESSION_ACTIVE_TIME),
|
||||||
);
|
);
|
||||||
let mut new_cookie = Cookie::new(&*COOKIE_NAME, s.to_string());
|
let mut new_cookie = Cookie::new(COOKIE_NAME.to_string(), s.to_string());
|
||||||
new_cookie.set_domain(COOKIE_DOMAIN.to_string());
|
new_cookie.set_domain(COOKIE_DOMAIN.to_string());
|
||||||
cookies.add(new_cookie);
|
cookies.add(new_cookie);
|
||||||
if let Some(original_uri) = params.get("original_url") {
|
if let Some(original_uri) = params.get("original_url") {
|
||||||
@ -199,3 +200,4 @@ pub async fn login_with_passkey(
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
pub mod auth;
|
||||||
Loading…
x
Reference in New Issue
Block a user