mirror of
https://github.com/danbulant/Portfolio
synced 2026-07-03 10:00:48 +00:00
Merge pull request #25 from EETagent/refactor_requests_with_aes
Refactor candidate structure + use aes instead of age crypto
This commit is contained in:
commit
ffb092512a
10 changed files with 31 additions and 44 deletions
|
|
@ -5,7 +5,7 @@ use std::net::SocketAddr;
|
||||||
|
|
||||||
use portfolio_core::error::ServiceError;
|
use portfolio_core::error::ServiceError;
|
||||||
use portfolio_core::services::candidate_service::CandidateService;
|
use portfolio_core::services::candidate_service::CandidateService;
|
||||||
use requests::LoginRequest;
|
use requests::{LoginRequest, RegisterRequest};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::{Rocket, Build};
|
use rocket::{Rocket, Build};
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
|
|
@ -35,13 +35,13 @@ fn custom_err_from_service_err(service_err: ServiceError) -> Custom<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/", data = "<post_form>")]
|
#[post("/", data = "<post_form>")]
|
||||||
async fn create(conn: Connection<'_, Db>, post_form: Json<candidate::Model>) -> Result<String, Custom<String>> {
|
async fn create(conn: Connection<'_, Db>, post_form: Json<RegisterRequest>) -> Result<String, Custom<String>> {
|
||||||
let db = conn.into_inner();
|
let db = conn.into_inner();
|
||||||
let form = post_form.into_inner();
|
let form = post_form.into_inner();
|
||||||
|
|
||||||
let plain_text_password = random_8_char_string();
|
let plain_text_password = random_8_char_string();
|
||||||
|
|
||||||
Mutation::create_candidate(db, form, &plain_text_password)
|
Mutation::create_candidate(db, form.application_id, &plain_text_password, form.personal_id_number)
|
||||||
.await
|
.await
|
||||||
.expect("Could not insert candidate");
|
.expect("Could not insert candidate");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,10 @@ pub struct LoginRequest {
|
||||||
pub application_id: i32,
|
pub application_id: i32,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
pub struct RegisterRequest {
|
||||||
|
pub application_id: i32,
|
||||||
|
pub personal_id_number: String,
|
||||||
|
}
|
||||||
|
|
@ -7,10 +7,6 @@ publish = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "^0.4"
|
chrono = "^0.4"
|
||||||
|
|
||||||
# serialization & deserialization
|
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
|
||||||
serde_json = "^1.0"
|
|
||||||
|
|
||||||
portfolio-entity = { path = "../entity" }
|
portfolio-entity = { path = "../entity" }
|
||||||
|
|
||||||
# env
|
# env
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
use chrono::{Utc, Duration};
|
use chrono::{Utc, Duration};
|
||||||
use ::entity::{candidate, session};
|
use ::entity::{candidate, session};
|
||||||
use sea_orm::{*, prelude::Uuid};
|
use sea_orm::{*, prelude::Uuid};
|
||||||
|
|
@ -8,17 +10,23 @@ pub struct Mutation;
|
||||||
impl Mutation {
|
impl Mutation {
|
||||||
pub async fn create_candidate(
|
pub async fn create_candidate(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
form_data: candidate::Model,
|
application_id: i32,
|
||||||
plain_text_password: &String,
|
plain_text_password: &String,
|
||||||
|
personal_id_number: String,
|
||||||
) -> Result<candidate::Model, DbErr> {
|
) -> Result<candidate::Model, DbErr> {
|
||||||
// TODO: unwrap pro testing..
|
// TODO: unwrap pro testing..
|
||||||
let hashed_password = hash_password(plain_text_password.to_string()).await.unwrap();
|
let hashed_password = hash_password(plain_text_password.to_string()).await.unwrap();
|
||||||
let (pubkey, priv_key_plain_text) = crypto::create_identity();
|
let (pubkey, priv_key_plain_text) = crypto::create_identity();
|
||||||
let encrypted_priv_key = crypto::encrypt_password_age(&priv_key_plain_text, &plain_text_password.to_string()).await.unwrap();
|
let encrypted_priv_key = crypto::encrypt_password(priv_key_plain_text, plain_text_password.to_string()).await.unwrap();
|
||||||
|
|
||||||
|
let encrypted_personal_id_number = crypto::encrypt_password_with_recipients(
|
||||||
|
&personal_id_number, vec![&pubkey]
|
||||||
|
).await.unwrap();
|
||||||
|
|
||||||
|
|
||||||
candidate::ActiveModel {
|
candidate::ActiveModel {
|
||||||
application: Set(form_data.application),
|
application: Set(application_id),
|
||||||
|
personal_identification_number: Set(encrypted_personal_id_number),
|
||||||
code: Set(hashed_password),
|
code: Set(hashed_password),
|
||||||
public_key: Set(pubkey),
|
public_key: Set(pubkey),
|
||||||
private_key: Set(encrypted_priv_key),
|
private_key: Set(encrypted_priv_key),
|
||||||
|
|
@ -65,7 +73,6 @@ impl Mutation {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use sea_orm::{Database, DbConn};
|
use sea_orm::{Database, DbConn};
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use crate::{Mutation, crypto};
|
use crate::{Mutation, crypto};
|
||||||
|
|
||||||
|
|
@ -89,19 +96,16 @@ mod tests {
|
||||||
async fn test_encrypt_decrypt_private_key_with_passphrase() {
|
async fn test_encrypt_decrypt_private_key_with_passphrase() {
|
||||||
let db = get_memory_sqlite_connection().await;
|
let db = get_memory_sqlite_connection().await;
|
||||||
|
|
||||||
let form = serde_json::from_value(json!({
|
|
||||||
"application": 5555555,
|
|
||||||
})).unwrap();
|
|
||||||
let plain_text_password = "test".to_string();
|
let plain_text_password = "test".to_string();
|
||||||
|
|
||||||
let secret_message = "trnka".to_string();
|
let secret_message = "trnka".to_string();
|
||||||
|
|
||||||
|
|
||||||
let candidate = Mutation::create_candidate(&db, form, &plain_text_password).await.unwrap();
|
let candidate = Mutation::create_candidate(&db, 5555555, &plain_text_password, "".to_string()).await.unwrap();
|
||||||
|
|
||||||
let encrypted_message = crypto::encrypt_password_with_recipients(&secret_message, vec![&candidate.public_key]).await.unwrap();
|
let encrypted_message = crypto::encrypt_password_with_recipients(&secret_message, vec![&candidate.public_key]).await.unwrap();
|
||||||
|
|
||||||
let private_key_plain_text = crypto::decrypt_password_age(&candidate.private_key, &plain_text_password).await.unwrap();
|
let private_key_plain_text = crypto::decrypt_password(candidate.private_key, plain_text_password).await.unwrap();
|
||||||
|
|
||||||
let decrypted_message = crypto::decrypt_password_with_private_key(&encrypted_message, &private_key_plain_text).await.unwrap();
|
let decrypted_message = crypto::decrypt_password_with_private_key(&encrypted_message, &private_key_plain_text).await.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ mod tests {
|
||||||
code: Set("test".to_string()),
|
code: Set("test".to_string()),
|
||||||
public_key: Set("test".to_string()),
|
public_key: Set("test".to_string()),
|
||||||
private_key: Set("test".to_string()),
|
private_key: Set("test".to_string()),
|
||||||
|
personal_identification_number: Set("test".to_string()),
|
||||||
created_at: Set(chrono::offset::Local::now().naive_local()),
|
created_at: Set(chrono::offset::Local::now().naive_local()),
|
||||||
updated_at: Set(chrono::offset::Local::now().naive_local()),
|
updated_at: Set(chrono::offset::Local::now().naive_local()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ impl CandidateService {
|
||||||
mod tests {
|
mod tests {
|
||||||
use entity::candidate;
|
use entity::candidate;
|
||||||
use sea_orm::{DbConn, Database, sea_query::TableCreateStatement, DbBackend, Schema, ConnectionTrait, prelude::Uuid};
|
use sea_orm::{DbConn, Database, sea_query::TableCreateStatement, DbBackend, Schema, ConnectionTrait, prelude::Uuid};
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use crate::{crypto, Mutation, services::candidate_service::CandidateService};
|
use crate::{crypto, Mutation, services::candidate_service::CandidateService};
|
||||||
|
|
||||||
|
|
@ -117,11 +116,7 @@ mod tests {
|
||||||
|
|
||||||
let db = get_memory_sqlite_connection().await;
|
let db = get_memory_sqlite_connection().await;
|
||||||
|
|
||||||
let form = serde_json::from_value(json!({
|
let candidate = Mutation::create_candidate(&db, 5555555, &SECRET.to_string(), "".to_string()).await.unwrap();
|
||||||
"application": 5555555,
|
|
||||||
})).unwrap();
|
|
||||||
|
|
||||||
let candidate = Mutation::create_candidate(&db, form, &SECRET.to_string()).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(candidate.application, 5555555);
|
assert_eq!(candidate.application, 5555555);
|
||||||
assert_ne!(candidate.code, SECRET.to_string());
|
assert_ne!(candidate.code, SECRET.to_string());
|
||||||
|
|
@ -132,11 +127,7 @@ mod tests {
|
||||||
async fn test_candidate_session_correct_password() {
|
async fn test_candidate_session_correct_password() {
|
||||||
let db = &get_memory_sqlite_connection().await;
|
let db = &get_memory_sqlite_connection().await;
|
||||||
|
|
||||||
let form = serde_json::from_value(json!({
|
Mutation::create_candidate(&db, 5555555, &"Tajny_kod".to_string(), "".to_string()).await.unwrap();
|
||||||
"application": 5555555,
|
|
||||||
})).unwrap();
|
|
||||||
|
|
||||||
Mutation::create_candidate(&db, form, &"Tajny_kod".to_string()).await.unwrap();
|
|
||||||
|
|
||||||
// correct password
|
// correct password
|
||||||
let session = CandidateService::new_session(
|
let session = CandidateService::new_session(
|
||||||
|
|
@ -159,11 +150,7 @@ mod tests {
|
||||||
async fn test_candidate_session_incorrect_password() {
|
async fn test_candidate_session_incorrect_password() {
|
||||||
let db = &get_memory_sqlite_connection().await;
|
let db = &get_memory_sqlite_connection().await;
|
||||||
|
|
||||||
let form = serde_json::from_value(json!({
|
let candidate_form = Mutation::create_candidate(&db, 5555555, &"Tajny_kod".to_string(), "".to_string()).await.unwrap();
|
||||||
"application": 5555555,
|
|
||||||
})).unwrap();
|
|
||||||
|
|
||||||
let candidate_form = Mutation::create_candidate(&db, form, &"Tajny_kod".to_string()).await.unwrap();
|
|
||||||
|
|
||||||
// incorrect password
|
// incorrect password
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ name = "entity"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
|
||||||
chrono = "^0.4"
|
chrono = "^0.4"
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
|
||||||
#[sea_orm(table_name = "candidate")]
|
#[sea_orm(table_name = "candidate")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
pub application: i32,
|
pub application: i32,
|
||||||
#[serde(skip_deserializing, skip_serializing)]
|
|
||||||
pub code: String,
|
pub code: String,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub surname: Option<String>,
|
pub surname: Option<String>,
|
||||||
|
|
@ -20,16 +17,12 @@ pub struct Model {
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub sex: Option<String>,
|
pub sex: Option<String>,
|
||||||
pub study: Option<String>,
|
pub study: Option<String>,
|
||||||
pub personal_identification_number: Option<String>,
|
pub personal_identification_number: String,
|
||||||
#[sea_orm(column_type = "Text", nullable)]
|
#[sea_orm(column_type = "Text", nullable)]
|
||||||
pub personal_identification_number_hash: Option<String>,
|
pub personal_identification_number_hash: Option<String>,
|
||||||
#[serde(skip_deserializing, skip_serializing)]
|
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
#[serde(skip_deserializing, skip_serializing)]
|
|
||||||
pub private_key: String,
|
pub private_key: String,
|
||||||
#[serde(skip_deserializing, skip_serializing)]
|
|
||||||
pub created_at: DateTime,
|
pub created_at: DateTime,
|
||||||
#[serde(skip_deserializing, skip_serializing)]
|
|
||||||
pub updated_at: DateTime,
|
pub updated_at: DateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ impl MigrationTrait for Migration {
|
||||||
.col(ColumnDef::new(Candidate::Email).string())
|
.col(ColumnDef::new(Candidate::Email).string())
|
||||||
.col(ColumnDef::new(Candidate::Sex).string())
|
.col(ColumnDef::new(Candidate::Sex).string())
|
||||||
.col(ColumnDef::new(Candidate::Study).string())
|
.col(ColumnDef::new(Candidate::Study).string())
|
||||||
.col(ColumnDef::new(Candidate::PersonalIdentificationNumber).string())
|
.col(ColumnDef::new(Candidate::PersonalIdentificationNumber).string().not_null())
|
||||||
.col(ColumnDef::new(Candidate::PersonalIdentificationNumberHash).text())
|
.col(ColumnDef::new(Candidate::PersonalIdentificationNumberHash).text())
|
||||||
.col(ColumnDef::new(Candidate::PublicKey).string().not_null())
|
.col(ColumnDef::new(Candidate::PublicKey).string().not_null())
|
||||||
.col(ColumnDef::new(Candidate::PrivateKey).string().not_null())
|
.col(ColumnDef::new(Candidate::PrivateKey).string().not_null())
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue