mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-11 02:30:25 +00:00
feat: password reset
This commit is contained in:
parent
55a0722dc3
commit
45187147d8
4 changed files with 75 additions and 3 deletions
|
|
@ -69,6 +69,7 @@ async fn start() -> Result<(), rocket::Error> {
|
|||
routes::admin::hello,
|
||||
routes::admin::create_candidate,
|
||||
routes::admin::get_candidate,
|
||||
routes::admin::reset_candidate_password,
|
||||
],
|
||||
)
|
||||
.mount(
|
||||
|
|
|
|||
|
|
@ -121,4 +121,19 @@ pub async fn get_candidate(
|
|||
.map_err(|e| Custom(Status::from_code(e.code()).unwrap(), e.to_string()))?;
|
||||
|
||||
Ok(Json(details))
|
||||
}
|
||||
|
||||
#[post("/candidate/<id>/reset_password")]
|
||||
pub async fn reset_candidate_password(
|
||||
conn: Connection<'_, Db>,
|
||||
_session: AdminAuth,
|
||||
id: i32,
|
||||
) -> Result<String, Custom<String>> {
|
||||
let db = conn.into_inner();
|
||||
|
||||
let new_password = CandidateService::reset_password(db, id)
|
||||
.await
|
||||
.map_err(|e| Custom(Status::from_code(e.code()).unwrap(), e.to_string()))?;
|
||||
|
||||
Ok(new_password)
|
||||
}
|
||||
|
|
@ -22,8 +22,23 @@ impl Mutation {
|
|||
updated_at: Set(chrono::offset::Local::now().naive_local()),
|
||||
..Default::default()
|
||||
}
|
||||
.insert(db)
|
||||
.await
|
||||
.insert(db)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn change_candidate_password(
|
||||
db: &DbConn,
|
||||
candidate: candidate::Model,
|
||||
new_password_hash: String,
|
||||
pub_key: String,
|
||||
priv_key_enc: String,
|
||||
) -> Result<candidate::Model, DbErr> {
|
||||
let mut candidate: candidate::ActiveModel = candidate.into();
|
||||
candidate.code = Set(new_password_hash);
|
||||
candidate.public_key = Set(pub_key);
|
||||
candidate.private_key = Set(priv_key_enc);
|
||||
|
||||
candidate.update(db).await
|
||||
}
|
||||
|
||||
pub async fn add_candidate_details(
|
||||
|
|
|
|||
|
|
@ -94,12 +94,32 @@ impl CandidateService {
|
|||
hashed_password,
|
||||
hashed_personal_id_number,
|
||||
pubkey,
|
||||
encrypted_priv_key,
|
||||
encrypted_priv_key,
|
||||
)
|
||||
.await?;
|
||||
Ok(candidate)
|
||||
}
|
||||
|
||||
pub async fn reset_password(
|
||||
db: &DbConn,
|
||||
id: i32,
|
||||
) -> Result<String, ServiceError> {
|
||||
let candidate = Query::find_candidate_by_id(db, id).await?
|
||||
.ok_or(ServiceError::CandidateNotFound)?;
|
||||
|
||||
let new_password_plain = crypto::random_8_char_string();
|
||||
let new_password_hash = crypto::hash_password(new_password_plain.clone()).await?;
|
||||
|
||||
let (pubkey, priv_key_plain_text) = crypto::create_identity();
|
||||
let encrypted_priv_key = crypto::encrypt_password(priv_key_plain_text,
|
||||
new_password_plain.to_string()
|
||||
).await?;
|
||||
|
||||
Mutation::change_candidate_password(db, candidate, new_password_hash, pubkey, encrypted_priv_key).await?;
|
||||
|
||||
Ok(new_password_plain)
|
||||
}
|
||||
|
||||
pub(in crate::services) async fn add_candidate_details(
|
||||
db: &DbConn,
|
||||
candidate: candidate::Model,
|
||||
|
|
@ -423,6 +443,27 @@ mod tests {
|
|||
assert!(!CandidateService::is_application_id_valid(101));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_password_reset() {
|
||||
let db = get_memory_sqlite_connection().await;
|
||||
let (candidate, _parent) = put_user_data(&db).await;
|
||||
|
||||
assert!(
|
||||
CandidateService::login(&db, candidate.application, "test".to_string(), "127.0.0.1".to_string()).await.is_ok()
|
||||
);
|
||||
|
||||
let new_password = CandidateService::reset_password(&db, candidate.application).await.unwrap();
|
||||
|
||||
assert!(
|
||||
CandidateService::login(&db, candidate.application, "test".to_string(), "127.0.0.1".to_string()).await.is_err()
|
||||
);
|
||||
|
||||
assert!(
|
||||
CandidateService::login(&db, candidate.application, new_password, "127.0.0.1".to_string()).await.is_ok()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// TODO
|
||||
/* #[tokio::test]
|
||||
async fn test_list_candidates() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue