feat: change password
This commit is contained in:
parent
0a08a34a00
commit
25b1f8eeb7
|
|
@ -187,6 +187,8 @@ dependencies = [
|
|||
"anyhow",
|
||||
"async-trait",
|
||||
"derive_more",
|
||||
"rand",
|
||||
"redis",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
|
|
@ -401,6 +403,7 @@ dependencies = [
|
|||
"actix-identity",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-session",
|
||||
"actix-web",
|
||||
"actix-web-actors",
|
||||
"actix-web-flash-messages",
|
||||
|
|
@ -434,6 +437,12 @@ dependencies = [
|
|||
"validator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||
|
||||
[[package]]
|
||||
name = "argon2"
|
||||
version = "0.4.1"
|
||||
|
|
@ -655,6 +664,20 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "config"
|
||||
version = "0.13.3"
|
||||
|
|
@ -709,6 +732,16 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
|
|
@ -909,6 +942,27 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.3"
|
||||
|
|
@ -925,6 +979,15 @@ dependencies = [
|
|||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
|
|
@ -941,6 +1004,21 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.1.0"
|
||||
|
|
@ -950,6 +1028,21 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.26"
|
||||
|
|
@ -966,6 +1059,17 @@ version = "0.3.26"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-intrusive"
|
||||
version = "0.4.2"
|
||||
|
|
@ -977,6 +1081,12 @@ dependencies = [
|
|||
"parking_lot 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.26"
|
||||
|
|
@ -1006,10 +1116,13 @@ version = "0.3.26"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
|
|
@ -1279,6 +1392,16 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.7.1"
|
||||
|
|
@ -1365,6 +1488,12 @@ version = "0.5.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||
|
||||
[[package]]
|
||||
name = "local-channel"
|
||||
version = "0.1.3"
|
||||
|
|
@ -1462,7 +1591,25 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1537,6 +1684,51 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
|
@ -1588,7 +1780,7 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1749,6 +1941,29 @@ dependencies = [
|
|||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "152f3863635cbb76b73bc247845781098302c6c9ad2060e1a9a7de56840346b6"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"combine",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"itoa",
|
||||
"native-tls",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"ryu",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-util",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
|
|
@ -1860,6 +2075,20 @@ dependencies = [
|
|||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.20.8"
|
||||
|
|
@ -1887,6 +2116,15 @@ version = "1.0.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
|
||||
dependencies = [
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
|
|
@ -1919,6 +2157,29 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.16"
|
||||
|
|
@ -2198,6 +2459,19 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall",
|
||||
"rustix",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.2.0"
|
||||
|
|
@ -2307,7 +2581,7 @@ dependencies = [
|
|||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2321,6 +2595,16 @@ dependencies = [
|
|||
"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]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
|
|
@ -2578,6 +2862,12 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
|
@ -2742,6 +3032,21 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ actix-service = "2.0.2"
|
|||
actix-identity = "0.5.2"
|
||||
actix-cors = "0.6.4"
|
||||
actix-web-flash-messages = { version = "0.4", features = ["cookies"] }
|
||||
actix-session = { version = "0.7", features = ["redis-rs-tls-session"] }
|
||||
|
||||
# serde
|
||||
serde_json = "1.0"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
mod password;
|
||||
mod token;
|
||||
mod user;
|
||||
|
||||
pub use password::password_scope;
|
||||
pub use token::token_scope;
|
||||
pub use user::user_scope;
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
use crate::component::auth::AuthError;
|
||||
use crate::state::State;
|
||||
|
||||
use actix_web::web::Data;
|
||||
use actix_web::{web, HttpRequest, HttpResponse, Scope};
|
||||
|
||||
pub fn password_scope() -> Scope {
|
||||
web::scope("/api").service(web::resource("/password").route(web::post().to(change_password)))
|
||||
}
|
||||
|
||||
async fn change_password(
|
||||
_req: HttpRequest,
|
||||
_state: Data<State>,
|
||||
) -> Result<HttpResponse, AuthError> {
|
||||
todo!()
|
||||
}
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
use crate::component::auth::{
|
||||
login, logout, register, InputParamsError, LoggedUser, LoginRequest, RegisterRequestParams,
|
||||
login, logout, register, ChangePasswordRequest, InputParamsError, LoggedUser, LoginRequest,
|
||||
RegisterRequest,
|
||||
};
|
||||
use crate::component::token_state::SessionToken;
|
||||
use crate::domain::{UserEmail, UserName, UserPassword};
|
||||
use crate::state::State;
|
||||
use actix_identity::Identity;
|
||||
use actix_session::SessionInsertError;
|
||||
use actix_web::web::{Data, Json, Payload};
|
||||
use actix_web::Result;
|
||||
use actix_web::{web, HttpResponse, Scope};
|
||||
|
|
@ -13,9 +16,14 @@ pub fn user_scope() -> Scope {
|
|||
.service(web::resource("/login").route(web::post().to(login_handler)))
|
||||
.service(web::resource("/logout").route(web::get().to(logout_handler)))
|
||||
.service(web::resource("/register").route(web::post().to(register_handler)))
|
||||
.service(web::resource("/password").route(web::post().to(change_password)))
|
||||
}
|
||||
|
||||
async fn login_handler(req: Json<LoginRequest>, state: Data<State>) -> Result<HttpResponse> {
|
||||
async fn login_handler(
|
||||
req: Json<LoginRequest>,
|
||||
state: Data<State>,
|
||||
session: SessionToken,
|
||||
) -> Result<HttpResponse> {
|
||||
let params = req.into_inner();
|
||||
let email = UserEmail::parse(params.email)
|
||||
.map_err(|e| InputParamsError::InvalidEmail(e))?
|
||||
|
|
@ -23,7 +31,15 @@ async fn login_handler(req: Json<LoginRequest>, state: Data<State>) -> Result<Ht
|
|||
let password = UserPassword::parse(params.password)
|
||||
.map_err(|_| InputParamsError::InvalidPassword)?
|
||||
.0;
|
||||
let resp = login(state.pg_pool.clone(), state.cache.clone(), email, password).await?;
|
||||
let (resp, token) = login(state.pg_pool.clone(), state.cache.clone(), email, password).await?;
|
||||
|
||||
// Renews the session key, assigning existing session state to new key.
|
||||
session.renew();
|
||||
if let Err(err) = session.insert_token(token) {
|
||||
// It needs to navigate to login page in web application
|
||||
tracing::error!("Insert session failed: {}", err);
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().json(resp))
|
||||
}
|
||||
|
||||
|
|
@ -33,10 +49,7 @@ async fn logout_handler(logged_user: LoggedUser, state: Data<State>) -> Result<H
|
|||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(state))]
|
||||
async fn register_handler(
|
||||
req: Json<RegisterRequestParams>,
|
||||
state: Data<State>,
|
||||
) -> Result<HttpResponse> {
|
||||
async fn register_handler(req: Json<RegisterRequest>, state: Data<State>) -> Result<HttpResponse> {
|
||||
let params = req.into_inner();
|
||||
let name = UserName::parse(params.name)
|
||||
.map_err(|e| InputParamsError::InvalidName(e))?
|
||||
|
|
@ -59,3 +72,10 @@ async fn register_handler(
|
|||
|
||||
Ok(HttpResponse::Ok().json(resp))
|
||||
}
|
||||
|
||||
async fn change_password(
|
||||
req: Json<ChangePasswordRequest>,
|
||||
state: Data<State>,
|
||||
) -> Result<HttpResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::api::{token_scope, user_scope};
|
||||
use actix_identity::IdentityMiddleware;
|
||||
use actix_web::{dev::Server, middleware, web, web::Data, App, HttpServer};
|
||||
use sqlx::{postgres::PgPoolOptions, PgPool};
|
||||
|
|
@ -5,8 +6,6 @@ use std::net::TcpListener;
|
|||
use std::sync::Arc;
|
||||
use tracing_actix_web::TracingLogger;
|
||||
|
||||
use crate::api::{password_scope, token_scope, user_scope};
|
||||
|
||||
use crate::config::config::{Config, DatabaseSetting};
|
||||
|
||||
use crate::middleware::cors::default_cors;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use anyhow::Context;
|
|||
use argon2::password_hash::SaltString;
|
||||
use argon2::{Algorithm, Argon2, Params, PasswordHash, PasswordHasher, PasswordVerifier, Version};
|
||||
use secrecy::{ExposeSecret, Secret};
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
||||
pub struct Credentials {
|
||||
|
|
@ -11,7 +12,7 @@ pub struct Credentials {
|
|||
pub password: Secret<String>,
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "Validate credentials", skip(credentials, pool))]
|
||||
#[tracing::instrument(skip(credentials, pool))]
|
||||
pub async fn validate_credentials(
|
||||
credentials: Credentials,
|
||||
pool: &PgPool,
|
||||
|
|
@ -41,7 +42,7 @@ pub async fn validate_credentials(
|
|||
.map_err(AuthError::InvalidCredentials)
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "Change password", skip(password, pool))]
|
||||
#[tracing::instrument(skip(password, pool))]
|
||||
pub async fn change_password(
|
||||
uid: uuid::Uuid,
|
||||
password: Secret<String>,
|
||||
|
|
@ -80,7 +81,7 @@ pub fn compute_hash_password(password: &[u8]) -> Result<String, anyhow::Error> {
|
|||
.to_string())
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "Get stored credentials", skip(email, pool))]
|
||||
#[tracing::instrument(skip(email, pool))]
|
||||
async fn get_stored_credentials(
|
||||
email: &str,
|
||||
pool: &PgPool,
|
||||
|
|
@ -100,10 +101,6 @@ async fn get_stored_credentials(
|
|||
Ok(row)
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "Validate credentials",
|
||||
skip(expected_password_hash, password_candidate)
|
||||
)]
|
||||
fn verify_password_hash(
|
||||
expected_password_hash: Secret<String>,
|
||||
password_candidate: Secret<String>,
|
||||
|
|
@ -118,3 +115,10 @@ fn verify_password_hash(
|
|||
)
|
||||
.context("Invalid password.")
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug)]
|
||||
pub struct ChangePasswordRequest {
|
||||
pub new_password: String,
|
||||
pub current_password: String,
|
||||
pub current_password_check: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ use chrono::Utc;
|
|||
use chrono::{Duration, Local};
|
||||
use futures_util::future::{ready, Ready};
|
||||
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
|
||||
use secrecy::Secret;
|
||||
use secrecy::zeroize::DefaultIsZeroes;
|
||||
use secrecy::{Secret, Zeroize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::types::uuid;
|
||||
use sqlx::{PgPool, Postgres, Transaction};
|
||||
|
|
@ -23,7 +24,7 @@ pub async fn login(
|
|||
cache: Arc<RwLock<Cache>>,
|
||||
email: String,
|
||||
password: String,
|
||||
) -> Result<LoginResponse, AuthError> {
|
||||
) -> Result<(LoginResponse, Secret<Token>), AuthError> {
|
||||
let credentials = Credentials {
|
||||
email,
|
||||
password: Secret::new(password),
|
||||
|
|
@ -32,14 +33,16 @@ pub async fn login(
|
|||
match validate_credentials(credentials, &pg_pool).await {
|
||||
Ok(uid) => {
|
||||
let uid = uid.to_string();
|
||||
let token = Token::create_token(&uid)?.into();
|
||||
let token = Token::create_token(&uid)?;
|
||||
let logged_user = LoggedUser::new(uid.clone());
|
||||
cache.write().await.authorized(logged_user);
|
||||
|
||||
Ok(LoginResponse {
|
||||
token,
|
||||
uid,
|
||||
})
|
||||
Ok((
|
||||
LoginResponse {
|
||||
token: token.clone().into(),
|
||||
uid,
|
||||
},
|
||||
Secret::new(token),
|
||||
))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
|
|
@ -116,26 +119,26 @@ async fn is_email_exist(
|
|||
Ok(result.is_some())
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug)]
|
||||
#[derive(Default, Deserialize, Debug)]
|
||||
pub struct LoginRequest {
|
||||
pub email: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug)]
|
||||
#[derive(Default, Serialize, Debug)]
|
||||
pub struct LoginResponse {
|
||||
pub token: String,
|
||||
pub uid: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug)]
|
||||
pub struct RegisterRequestParams {
|
||||
#[derive(Default, Deserialize, Debug)]
|
||||
pub struct RegisterRequest {
|
||||
pub email: String,
|
||||
pub password: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug)]
|
||||
#[derive(Default, Serialize, Debug)]
|
||||
pub struct RegisterResponse {
|
||||
pub token: String,
|
||||
}
|
||||
|
|
@ -227,8 +230,15 @@ impl Claim {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Token(pub String);
|
||||
|
||||
impl Zeroize for Token {
|
||||
fn zeroize(&mut self) {
|
||||
self.0.zeroize()
|
||||
}
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub fn create_token(user_id: &str) -> Result<Self, AuthError> {
|
||||
let claims = Claim::with_user_id(user_id);
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
pub mod auth;
|
||||
pub mod token_state;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
use crate::component::auth::Token;
|
||||
use actix_session::SessionExt;
|
||||
use actix_session::{Session, SessionGetError, SessionInsertError};
|
||||
use actix_web::dev::Payload;
|
||||
use actix_web::{FromRequest, HttpRequest};
|
||||
use secrecy::{ExposeSecret, Secret};
|
||||
use std::future::{ready, Ready};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct SessionToken(Session);
|
||||
|
||||
impl SessionToken {
|
||||
const TOKEN_ID_KEY: &'static str = "token";
|
||||
|
||||
pub fn renew(&self) {
|
||||
self.0.renew();
|
||||
}
|
||||
|
||||
pub fn insert_token(&self, token: Secret<Token>) -> Result<(), SessionInsertError> {
|
||||
self.0.insert(Self::TOKEN_ID_KEY, token.expose_secret())
|
||||
}
|
||||
|
||||
pub fn get_token(&self) -> Result<Option<String>, SessionGetError> {
|
||||
self.0.get(Self::TOKEN_ID_KEY)
|
||||
}
|
||||
|
||||
pub fn log_out(self) {
|
||||
self.0.purge()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRequest for SessionToken {
|
||||
type Error = <Session as FromRequest>::Error;
|
||||
type Future = Ready<Result<SessionToken, Self::Error>>;
|
||||
|
||||
fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
|
||||
ready(Ok(SessionToken(req.get_session())))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue