feat: password reset

This commit is contained in:
Sebastian Pravda 2022-11-17 19:28:04 +01:00
parent 55a0722dc3
commit 45187147d8
No known key found for this signature in database
GPG key ID: F3BC84F08EFA3F57
4 changed files with 75 additions and 3 deletions

View file

@ -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(

View file

@ -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)
}

View file

@ -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(

View file

@ -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() {