mirror of
https://github.com/danbulant/Portfolio
synced 2026-05-24 12:35:31 +00:00
Merge pull request #38 from EETagent/finish_file_upload
File upload & Candidate folder
This commit is contained in:
commit
efac2e1965
9 changed files with 322 additions and 105 deletions
157
Cargo.lock
generated
157
Cargo.lock
generated
|
|
@ -8,6 +8,12 @@ version = "0.11.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.1"
|
||||
|
|
@ -170,6 +176,23 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
|
||||
dependencies = [
|
||||
"bzip2",
|
||||
"flate2",
|
||||
"futures-core",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"xz2",
|
||||
"zstd",
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.3"
|
||||
|
|
@ -212,6 +235,29 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async_io_utilities"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b20cffc5590f4bf33f05f97a3ea587feba9c50d20325b401daa096b92ff7da0"
|
||||
dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async_zip"
|
||||
version = "0.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a36d43bdefc7215b2b3a97edd03b1553b7969ad76551025eedd3b913c645f6e"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"async_io_utilities",
|
||||
"chrono",
|
||||
"crc32fast",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "1.0.0"
|
||||
|
|
@ -326,11 +372,35 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0"
|
||||
dependencies = [
|
||||
"bzip2-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2-sys"
|
||||
version = "0.1.11+1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfb"
|
||||
|
|
@ -536,6 +606,15 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.6"
|
||||
|
|
@ -794,6 +873,16 @@ dependencies = [
|
|||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent"
|
||||
version = "0.16.0"
|
||||
|
|
@ -1373,6 +1462,15 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.60"
|
||||
|
|
@ -1448,6 +1546,17 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma-sys"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
|
|
@ -1484,6 +1593,15 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.5"
|
||||
|
|
@ -1896,6 +2014,7 @@ dependencies = [
|
|||
"argon2",
|
||||
"async-compat",
|
||||
"async-tempfile",
|
||||
"async_zip",
|
||||
"base64",
|
||||
"chrono",
|
||||
"dotenv",
|
||||
|
|
@ -3552,6 +3671,15 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xz2"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
|
||||
dependencies = [
|
||||
"lzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
|
|
@ -3578,3 +3706,32 @@ dependencies = [
|
|||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.11.2+zstd.1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "5.0.2+zstd.1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.1+zstd.1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ async-compat = "^0.2"
|
|||
# file identifier
|
||||
infer = "^0.11"
|
||||
|
||||
async_zip = "0.0.9"
|
||||
|
||||
# crypto
|
||||
rand = "^0.8"
|
||||
aes-gcm-siv = { version = "^0.11", features = ["std"] }
|
||||
|
|
|
|||
|
|
@ -19,19 +19,7 @@ mod tests {
|
|||
use sea_orm::{ActiveModelTrait, DbConn, Set};
|
||||
|
||||
use crate::Query;
|
||||
|
||||
#[cfg(test)]
|
||||
async fn get_memory_sqlite_connection() -> DbConn {
|
||||
let base_url = "sqlite::memory:";
|
||||
let db: DbConn = Database::connect(base_url).await.unwrap();
|
||||
|
||||
let schema = Schema::new(DbBackend::Sqlite);
|
||||
let stmt: TableCreateStatement = schema.create_table_from_entity(candidate::Entity);
|
||||
db.execute(db.get_database_backend().build(&stmt))
|
||||
.await
|
||||
.unwrap();
|
||||
db
|
||||
}
|
||||
use crate::util::get_memory_sqlite_connection;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_find_candidate_by_id() {
|
||||
|
|
|
|||
|
|
@ -24,24 +24,4 @@ impl Query {
|
|||
.all(db)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use entity::candidate;
|
||||
use sea_orm::DbConn;
|
||||
use sea_orm::{sea_query::TableCreateStatement, ConnectionTrait, Database, DbBackend, Schema};
|
||||
|
||||
#[cfg(test)]
|
||||
async fn get_memory_sqlite_connection() -> DbConn {
|
||||
let base_url = "sqlite::memory:";
|
||||
let db: DbConn = Database::connect(base_url).await.unwrap();
|
||||
|
||||
let schema = Schema::new(DbBackend::Sqlite);
|
||||
let stmt: TableCreateStatement = schema.create_table_from_entity(candidate::Entity);
|
||||
db.execute(db.get_database_backend().build(&stmt))
|
||||
.await
|
||||
.unwrap();
|
||||
db
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -54,6 +54,10 @@ pub enum ServiceError {
|
|||
ArgonHashError(#[from] argon2::password_hash::Error),
|
||||
#[error("AES error")]
|
||||
AesError(#[from] aes_gcm_siv::Error),
|
||||
#[error("Portfolio is incomplete")]
|
||||
IncompletePortfolio,
|
||||
#[error("Zip error")]
|
||||
ZipError(#[from] async_zip::error::ZipError)
|
||||
}
|
||||
|
||||
impl ServiceError {
|
||||
|
|
@ -84,6 +88,9 @@ impl ServiceError {
|
|||
ServiceError::TokioJoinError(_) => 500,
|
||||
ServiceError::AesError(_) => 500,
|
||||
ServiceError::ArgonConfigError(_) => 500,
|
||||
//TODO: Correct code
|
||||
ServiceError::IncompletePortfolio => 500,
|
||||
ServiceError::ZipError(_) => 500,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ pub mod filetype;
|
|||
pub mod services;
|
||||
pub mod error;
|
||||
pub mod candidate_details;
|
||||
pub mod util;
|
||||
|
||||
pub use database::mutation::*;
|
||||
pub use database::query::*;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use std::path::Path;
|
||||
|
||||
use entity::candidate;
|
||||
use sea_orm::{prelude::Uuid, DbConn};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
|
||||
use crate::{
|
||||
candidate_details::EncryptedApplicationDetails,
|
||||
|
|
@ -40,19 +43,17 @@ impl CandidateService {
|
|||
return Err(ServiceError::UserAlreadyExists);
|
||||
}
|
||||
|
||||
let Ok(hashed_password) = hash_password(plain_text_password.to_string()).await else {
|
||||
return Err(ServiceError::CryptoHashFailed);
|
||||
};
|
||||
let hashed_password = hash_password(plain_text_password.to_string()).await?;
|
||||
|
||||
let (pubkey, priv_key_plain_text) = crypto::create_identity();
|
||||
|
||||
let Ok(encrypted_priv_key) = crypto::encrypt_password(priv_key_plain_text, plain_text_password.to_string()).await else {
|
||||
return Err(ServiceError::CryptoEncryptFailed);
|
||||
};
|
||||
let encrypted_priv_key = crypto::encrypt_password(priv_key_plain_text, plain_text_password.to_string()).await?;
|
||||
|
||||
let hashed_personal_id_number = hash_password(personal_id_number).await?;
|
||||
|
||||
// TODO: Specify root path in config?
|
||||
tokio::fs::create_dir_all(Path::new(&application_id.to_string()).join("cache")).await?;
|
||||
|
||||
let Ok(hashed_personal_id_number) = hash_password(personal_id_number).await else {
|
||||
return Err(ServiceError::CryptoHashFailed);
|
||||
};
|
||||
|
||||
let candidate = Mutation::create_candidate(
|
||||
db,
|
||||
|
|
@ -88,35 +89,136 @@ impl CandidateService {
|
|||
&& candidate.study.is_some()
|
||||
}
|
||||
|
||||
pub async fn add_cover_letter(candidate_id: i32, letter: Vec<u8>) -> Result<(), ServiceError> {
|
||||
// TODO
|
||||
async fn write_portfolio_file(
|
||||
candidate_id: i32,
|
||||
data: Vec<u8>,
|
||||
filename: &str,
|
||||
) -> Result<(), ServiceError> {
|
||||
let cache_path = Path::new(&candidate_id.to_string()).join("cache");
|
||||
|
||||
let mut file = tokio::fs::File::create(cache_path.join(filename)).await?;
|
||||
|
||||
file.write_all(&data).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_cover_letter(candidate_id: i32, letter: Vec<u8>) -> Result<(), ServiceError> {
|
||||
Self::write_portfolio_file(candidate_id, letter, "MOTIVACNI_DOPIS.pdf").await
|
||||
}
|
||||
|
||||
pub async fn add_portfolio_letter(
|
||||
candidate_id: i32,
|
||||
letter: Vec<u8>,
|
||||
) -> Result<(), ServiceError> {
|
||||
// TODO
|
||||
Ok(())
|
||||
Self::write_portfolio_file(candidate_id, letter, "PORTFOLIO.pdf").await
|
||||
}
|
||||
|
||||
pub async fn add_portfolio_zip(candidate_id: i32, zip: Vec<u8>) -> Result<(), ServiceError> {
|
||||
// TODO
|
||||
Self::write_portfolio_file(candidate_id, zip, "PORTFOLIO.zip").await
|
||||
}
|
||||
|
||||
pub async fn is_portfolio_complete(candidate_id: i32) -> bool {
|
||||
let cache_path = Path::new(&candidate_id.to_string()).join("cache");
|
||||
|
||||
tokio::fs::metadata(cache_path.join("MOTIVACNI_DOPIS.pdf"))
|
||||
.await
|
||||
.is_ok()
|
||||
&& tokio::fs::metadata(cache_path.join("PORTFOLIO.pdf"))
|
||||
.await
|
||||
.is_ok()
|
||||
&& tokio::fs::metadata(cache_path.join("PORTFOLIO.zip"))
|
||||
.await
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
pub async fn submit_portfolio(candidate_id: i32, db: &DbConn) -> Result<(), ServiceError> {
|
||||
let path = Path::new(&candidate_id.to_string()).to_path_buf();
|
||||
let cache_path = path.join("cache");
|
||||
|
||||
if Self::is_portfolio_complete(candidate_id).await == false {
|
||||
return Err(ServiceError::IncompletePortfolio);
|
||||
}
|
||||
|
||||
let mut archive = tokio::fs::File::create(path.join("PORTFOLIO.zip")).await?;
|
||||
|
||||
|
||||
let mut writer = async_zip::write::ZipFileWriter::new(&mut archive);
|
||||
|
||||
for entry in vec!["MOTIVACNI_DOPIS.pdf", "PORTFOLIO.pdf", "PORTFOLIO.zip"] {
|
||||
let mut entry_file = tokio::fs::File::open(cache_path.join(entry))
|
||||
.await?;
|
||||
|
||||
let mut contents = vec![];
|
||||
|
||||
entry_file
|
||||
.read_to_end(&mut contents)
|
||||
.await?;
|
||||
|
||||
let builder =
|
||||
async_zip::ZipEntryBuilder::new(entry.to_string(), async_zip::Compression::Deflate);
|
||||
|
||||
let mut entry_writer = writer
|
||||
.write_entry_stream(builder)
|
||||
.await?;
|
||||
|
||||
// TODO: write_all_buf?
|
||||
entry_writer
|
||||
.write_all(&mut contents)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// TODO: Ne unwrap
|
||||
writer.close().await.unwrap();
|
||||
archive.shutdown().await.unwrap();
|
||||
|
||||
let admin_public_keys = Query::get_all_admin_public_keys(db)
|
||||
.await?;
|
||||
|
||||
let candidate = Query::find_candidate_by_id(db, candidate_id).await?
|
||||
.ok_or(ServiceError::CandidateNotFound)?;
|
||||
|
||||
let candidate_public_key = candidate.public_key;
|
||||
|
||||
let mut admin_public_keys_refrence: Vec<&str> =
|
||||
admin_public_keys.iter().map(|s| &**s).collect();
|
||||
|
||||
let mut recipients = vec![&*candidate_public_key];
|
||||
|
||||
recipients.append(&mut admin_public_keys_refrence);
|
||||
|
||||
let Ok(_) = crypto::encrypt_file_with_recipients(
|
||||
path.join("PORTFOLIO.zip"),
|
||||
path.join("PORTFOLIO.zip"),
|
||||
recipients,
|
||||
)
|
||||
.await else {
|
||||
return Err(ServiceError::CryptoEncryptFailed);
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_portfolio(candidate_id: i32, db: &DbConn) -> Result<Vec<u8>, ServiceError> {
|
||||
let candidate = Query::find_candidate_by_id(db, candidate_id).await?
|
||||
.ok_or(ServiceError::CandidateNotFound)?;
|
||||
|
||||
let candidate_public_key = candidate.public_key;
|
||||
|
||||
let path = Path::new(&candidate_id.to_string()).join("PORTFOLIO.zip");
|
||||
|
||||
let buffer = crypto::decrypt_file_with_private_key_as_buffer(path, &candidate_public_key).await?;
|
||||
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
async fn decrypt_private_key(
|
||||
candidate: candidate::Model,
|
||||
password: String,
|
||||
) -> Result<String, ServiceError> {
|
||||
let private_key_encrypted = candidate.private_key;
|
||||
|
||||
let private_key = crypto::decrypt_password(private_key_encrypted, password).await;
|
||||
|
||||
let Ok(private_key) = private_key else {
|
||||
return Err(ServiceError::CryptoDecryptFailed);
|
||||
};
|
||||
let private_key = crypto::decrypt_password(private_key_encrypted, password).await?;
|
||||
|
||||
Ok(private_key)
|
||||
}
|
||||
|
|
@ -168,6 +270,7 @@ impl CandidateService {
|
|||
mod tests {
|
||||
use sea_orm::{Database, DbConn};
|
||||
|
||||
use crate::util::get_memory_sqlite_connection;
|
||||
use crate::{crypto, services::candidate_service::CandidateService, Mutation};
|
||||
|
||||
use super::EncryptedApplicationDetails;
|
||||
|
|
@ -188,32 +291,6 @@ mod tests {
|
|||
assert!(!CandidateService::is_application_id_valid(101));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
async fn get_memory_sqlite_connection() -> DbConn {
|
||||
use entity::{admin, candidate, parent};
|
||||
use sea_orm::Schema;
|
||||
use sea_orm::{sea_query::TableCreateStatement, ConnectionTrait, DbBackend};
|
||||
|
||||
let base_url = "sqlite::memory:";
|
||||
let db: DbConn = Database::connect(base_url).await.unwrap();
|
||||
|
||||
let schema = Schema::new(DbBackend::Sqlite);
|
||||
let stmt: TableCreateStatement = schema.create_table_from_entity(candidate::Entity);
|
||||
let stmt2: TableCreateStatement = schema.create_table_from_entity(admin::Entity);
|
||||
let stmt3: TableCreateStatement = schema.create_table_from_entity(parent::Entity);
|
||||
|
||||
db.execute(db.get_database_backend().build(&stmt))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt2))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt3))
|
||||
.await
|
||||
.unwrap();
|
||||
db
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_encrypt_decrypt_private_key_with_passphrase() {
|
||||
let db = get_memory_sqlite_connection().await;
|
||||
|
|
|
|||
|
|
@ -171,34 +171,9 @@ mod tests {
|
|||
|
||||
use crate::{
|
||||
crypto,
|
||||
services::{session_service::SessionService, application_service::ApplicationService},
|
||||
services::{session_service::SessionService, application_service::ApplicationService}, util::get_memory_sqlite_connection,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
async fn get_memory_sqlite_connection() -> DbConn {
|
||||
let base_url = "sqlite::memory:";
|
||||
let db: DbConn = Database::connect(base_url).await.unwrap();
|
||||
|
||||
let schema = Schema::new(DbBackend::Sqlite);
|
||||
let stmt: TableCreateStatement = schema.create_table_from_entity(candidate::Entity);
|
||||
let stmt2: TableCreateStatement = schema.create_table_from_entity(admin::Entity);
|
||||
let stmt3: TableCreateStatement = schema.create_table_from_entity(session::Entity);
|
||||
let stmt4: TableCreateStatement = schema.create_table_from_entity(parent::Entity);
|
||||
db.execute(db.get_database_backend().build(&stmt))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt2))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt3))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt4))
|
||||
.await
|
||||
.unwrap();
|
||||
db
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_candidate() {
|
||||
const SECRET: &str = "Tajny_kod";
|
||||
|
|
|
|||
30
core/src/util.rs
Normal file
30
core/src/util.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
use crate::sea_orm::DbConn;
|
||||
|
||||
#[cfg(test)]
|
||||
pub async fn get_memory_sqlite_connection() -> DbConn {
|
||||
use entity::{admin, candidate, parent, session};
|
||||
use sea_orm::{Schema, Database};
|
||||
use sea_orm::{sea_query::TableCreateStatement, ConnectionTrait, DbBackend};
|
||||
|
||||
let base_url = "sqlite::memory:";
|
||||
let db: DbConn = Database::connect(base_url).await.unwrap();
|
||||
|
||||
let schema = Schema::new(DbBackend::Sqlite);
|
||||
let stmt: TableCreateStatement = schema.create_table_from_entity(candidate::Entity);
|
||||
let stmt2: TableCreateStatement = schema.create_table_from_entity(admin::Entity);
|
||||
let stmt3: TableCreateStatement = schema.create_table_from_entity(session::Entity);
|
||||
let stmt4: TableCreateStatement = schema.create_table_from_entity(parent::Entity);
|
||||
db.execute(db.get_database_backend().build(&stmt))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt2))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt3))
|
||||
.await
|
||||
.unwrap();
|
||||
db.execute(db.get_database_backend().build(&stmt4))
|
||||
.await
|
||||
.unwrap();
|
||||
db
|
||||
}
|
||||
Loading…
Reference in a new issue