feat(users): Add optional fields to user schemas and update user avatar functionality

This commit is contained in:
MythEclipse
2025-08-12 17:31:12 +07:00
parent a25e896fa2
commit 34b6cdabfb
13 changed files with 297 additions and 5 deletions
+40
View File
@@ -3,6 +3,46 @@ name = "imphnen-backend"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[[bin]]
name = "api"
path = "src/main.rs"
[[bin]]
name = "clear_db_test"
path = "src/bin/clear_db_test.rs"
[[bin]]
name = "seeder"
path = "src/bin/seeder.rs"
[[bin]]
name = "seed_events"
path = "src/bin/seed_events.rs"
[[bin]]
name = "seed_gacha_rolls"
path = "src/bin/seed_gacha_rolls.rs"
[[bin]]
name = "seed_mentor_user"
path = "src/bin/seed_mentor_user.rs"
[[bin]]
name = "seed_permissions"
path = "src/bin/seed_permissions.rs"
[[bin]]
name = "seed_roles"
path = "src/bin/seed_roles.rs"
[[bin]]
name = "seed_roles_permissions"
path = "src/bin/seed_roles_permissions.rs"
[[bin]]
name = "seed_users"
path = "src/bin/seed_users.rs"
[dependencies] [dependencies]
imphnen-libs.workspace = true imphnen-libs.workspace = true
imphnen-utils.workspace = true imphnen-utils.workspace = true
@@ -51,6 +51,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
PermissionsEnum::ReadOwnMentorProfile, PermissionsEnum::ReadOwnMentorProfile,
PermissionsEnum::UpdateOwnMentorProfile, PermissionsEnum::UpdateOwnMentorProfile,
PermissionsEnum::ReadOwnMentorStatus, PermissionsEnum::ReadOwnMentorStatus,
PermissionsEnum::UpdateMentors,
PermissionsEnum::VerifyMentors, PermissionsEnum::VerifyMentors,
PermissionsEnum::DeleteMentors, PermissionsEnum::DeleteMentors,
] { ] {
+10
View File
@@ -46,15 +46,25 @@ async fn main() -> Result<(), Box<dyn Error>> {
let user = UsersSchema { let user = UsersSchema {
id: Thing::from(("app_users", id)), id: Thing::from(("app_users", id)),
fullname: fullname.into(), fullname: fullname.into(),
legal_name: None,
email: email.into(), email: email.into(),
password: hash_password("password").unwrap(), password: hash_password("password").unwrap(),
avatar: None, avatar: None,
phone_number: "081234567890".into(), phone_number: "081234567890".into(),
phone_for_verification: None,
is_active: true, is_active: true,
is_deleted: false, is_deleted: false,
mentor_id: None, mentor_id: None,
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
role: Thing::from(("app_roles", role_id)), role: Thing::from(("app_roles", role_id)),
created_at: get_iso_date(), created_at: get_iso_date(),
updated_at: get_iso_date(), updated_at: get_iso_date(),
@@ -94,13 +94,23 @@ impl<'a> AuthRepository<'a> {
Ok(UsersDetailQueryDto { Ok(UsersDetailQueryDto {
id: Thing::from(("app_users".to_string(), email.clone())), id: Thing::from(("app_users".to_string(), email.clone())),
fullname: "Cached User".to_string(), fullname: "Cached User".to_string(),
legal_name: None,
email: cache.email, email: cache.email,
avatar: None, avatar: None,
phone_number: String::new(), phone_number: String::new(),
phone_for_verification: None,
is_active: true, is_active: true,
is_deleted: false, is_deleted: false,
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
password: String::new(), password: String::new(),
role: role_detail_query_dto, role: role_detail_query_dto,
created_at: String::new(), created_at: String::new(),
@@ -215,9 +215,15 @@ where
// Update avatar if user doesn't have one and Google provides one // Update avatar if user doesn't have one and Google provides one
if user.avatar.is_none() && google_user.picture.is_some() { if user.avatar.is_none() && google_user.picture.is_some() {
info!("Updating avatar for existing user: {}", google_user.email); info!("Updating avatar for existing user: {}", google_user.email);
// Note: We would need to implement an update_user_avatar method in the user service match self.users_service.update_user_avatar(&google_user.email, google_user.picture.clone()).await {
// For now, we'll just log this Ok(_) => {
info!("Avatar would be updated to: {:?}", google_user.picture); info!("Successfully updated avatar for user: {}", google_user.email);
user.avatar = google_user.picture.clone();
},
Err(e) => {
error!("Failed to update avatar for user {}: {:?}", google_user.email, e);
}
}
} }
user user
+77
View File
@@ -67,16 +67,33 @@ pub struct UsersUpdateRequestDto {
pub password: String, pub password: String,
#[validate(length(min = 2, message = "Fullname at least have 2 character"))] #[validate(length(min = 2, message = "Fullname at least have 2 character"))]
pub fullname: String, pub fullname: String,
#[validate(length(min = 2, message = "Legal name at least have 2 character"))]
pub legal_name: Option<String>,
#[validate(length( #[validate(length(
min = 10, min = 10,
message = "Phone number at least have 10 character" message = "Phone number at least have 10 character"
))] ))]
pub phone_number: String, pub phone_number: String,
pub phone_for_verification: Option<String>,
pub is_active: bool, pub is_active: bool,
#[validate(length(min = 1, message = "Gender is required"))] #[validate(length(min = 1, message = "Gender is required"))]
pub gender: Option<String>, pub gender: Option<String>,
#[validate(length(min = 1, message = "Birthdate is required"))] #[validate(length(min = 1, message = "Birthdate is required"))]
pub birthdate: Option<String>, pub birthdate: Option<String>,
pub domicile: Option<String>,
#[validate(url(message = "Invalid identity document URL"))]
pub identity_document_url: Option<String>,
#[validate(length(min = 50, message = "Bio must be at least 50 characters"))]
pub bio: Option<String>,
pub last_education: Option<String>,
#[validate(url(message = "Invalid LinkedIn URL"))]
pub linkedin_url: Option<String>,
#[validate(url(message = "Invalid GitHub URL"))]
pub github_url: Option<String>,
#[validate(url(message = "Invalid CV URL"))]
pub cv_url: Option<String>,
#[validate(url(message = "Invalid portfolio URL"))]
pub portfolio_url: Option<String>,
#[validate(length(min = 1, message = "Avatar is required"))] #[validate(length(min = 1, message = "Avatar is required"))]
pub avatar: Option<String>, pub avatar: Option<String>,
pub role_id: String, pub role_id: String,
@@ -87,12 +104,22 @@ pub struct UsersDetailItemDto {
pub id: String, pub id: String,
pub role: RolesDetailItemDto, pub role: RolesDetailItemDto,
pub fullname: String, pub fullname: String,
pub legal_name: Option<String>,
pub email: String, pub email: String,
pub avatar: Option<String>, pub avatar: Option<String>,
pub phone_number: String, pub phone_number: String,
pub phone_for_verification: Option<String>,
pub is_active: bool, pub is_active: bool,
pub gender: Option<String>, pub gender: Option<String>,
pub birthdate: Option<String>, pub birthdate: Option<String>,
pub domicile: Option<String>,
pub identity_document_url: Option<String>,
pub bio: Option<String>,
pub last_education: Option<String>,
pub linkedin_url: Option<String>,
pub github_url: Option<String>,
pub cv_url: Option<String>,
pub portfolio_url: Option<String>,
pub created_at: String, pub created_at: String,
pub updated_at: String, pub updated_at: String,
} }
@@ -103,12 +130,22 @@ impl UsersDetailItemDto {
id: dto.id.id.to_raw().clone(), id: dto.id.id.to_raw().clone(),
role: RolesDetailItemDto::from(&dto.role), role: RolesDetailItemDto::from(&dto.role),
fullname: dto.fullname.clone(), fullname: dto.fullname.clone(),
legal_name: dto.legal_name.clone(),
email: dto.email.clone(), email: dto.email.clone(),
avatar: dto.avatar.clone(), avatar: dto.avatar.clone(),
phone_number: dto.phone_number.clone(), // Corrected from dto.phone.clone() phone_number: dto.phone_number.clone(), // Corrected from dto.phone.clone()
phone_for_verification: dto.phone_for_verification.clone(),
is_active: dto.is_active, is_active: dto.is_active,
gender: dto.gender.clone(), gender: dto.gender.clone(),
birthdate: dto.birthdate.clone(), birthdate: dto.birthdate.clone(),
domicile: dto.domicile.clone(),
identity_document_url: dto.identity_document_url.clone(),
bio: dto.bio.clone(),
last_education: dto.last_education.clone(),
linkedin_url: dto.linkedin_url.clone(),
github_url: dto.github_url.clone(),
cv_url: dto.cv_url.clone(),
portfolio_url: dto.portfolio_url.clone(),
created_at: dto.created_at.clone(), created_at: dto.created_at.clone(),
updated_at: dto.updated_at.clone(), updated_at: dto.updated_at.clone(),
} }
@@ -119,12 +156,22 @@ impl UsersDetailItemDto {
id: schema.id.id.to_raw(), id: schema.id.id.to_raw(),
role: RolesDetailItemDto::default(), // Placeholder, role needs to be fetched role: RolesDetailItemDto::default(), // Placeholder, role needs to be fetched
fullname: schema.fullname.clone(), fullname: schema.fullname.clone(),
legal_name: schema.legal_name.clone(),
email: schema.email.clone(), email: schema.email.clone(),
avatar: schema.avatar.clone(), avatar: schema.avatar.clone(),
phone_number: schema.phone_number.clone(), phone_number: schema.phone_number.clone(),
phone_for_verification: schema.phone_for_verification.clone(),
is_active: schema.is_active, is_active: schema.is_active,
gender: schema.gender.clone(), gender: schema.gender.clone(),
birthdate: schema.birthdate.clone(), birthdate: schema.birthdate.clone(),
domicile: schema.domicile.clone(),
identity_document_url: schema.identity_document_url.clone(),
bio: schema.bio.clone(),
last_education: schema.last_education.clone(),
linkedin_url: schema.linkedin_url.clone(),
github_url: schema.github_url.clone(),
cv_url: schema.cv_url.clone(),
portfolio_url: schema.portfolio_url.clone(),
created_at: schema.created_at.clone(), created_at: schema.created_at.clone(),
updated_at: schema.updated_at.clone(), updated_at: schema.updated_at.clone(),
} }
@@ -177,13 +224,23 @@ impl UsersListQueryDto {
pub struct UsersDetailQueryDto { pub struct UsersDetailQueryDto {
pub id: Thing, pub id: Thing,
pub fullname: String, pub fullname: String,
pub legal_name: Option<String>,
pub email: String, pub email: String,
pub avatar: Option<String>, pub avatar: Option<String>,
pub phone_number: String, pub phone_number: String,
pub phone_for_verification: Option<String>,
pub is_active: bool, pub is_active: bool,
pub is_deleted: bool, pub is_deleted: bool,
pub gender: Option<String>, pub gender: Option<String>,
pub birthdate: Option<String>, pub birthdate: Option<String>,
pub domicile: Option<String>,
pub identity_document_url: Option<String>,
pub bio: Option<String>,
pub last_education: Option<String>,
pub linkedin_url: Option<String>,
pub github_url: Option<String>,
pub cv_url: Option<String>,
pub portfolio_url: Option<String>,
pub password: String, pub password: String,
pub role: RolesDetailQueryDto, pub role: RolesDetailQueryDto,
pub created_at: String, pub created_at: String,
@@ -197,12 +254,22 @@ impl UsersDetailQueryDto {
id: self.id.clone(), id: self.id.clone(),
role: self.role.clone(), role: self.role.clone(),
fullname: self.fullname.clone(), fullname: self.fullname.clone(),
legal_name: self.legal_name.clone(),
email: self.email.clone(), email: self.email.clone(),
avatar: self.avatar.clone(), avatar: self.avatar.clone(),
phone_number: self.phone_number.clone(), phone_number: self.phone_number.clone(),
phone_for_verification: self.phone_for_verification.clone(),
is_active: self.is_active, is_active: self.is_active,
mentor_id: self.mentor_id.clone(), mentor_id: self.mentor_id.clone(),
gender: self.gender.clone(), gender: self.gender.clone(),
domicile: self.domicile.clone(),
identity_document_url: self.identity_document_url.clone(),
bio: self.bio.clone(),
last_education: self.last_education.clone(),
linkedin_url: self.linkedin_url.clone(),
github_url: self.github_url.clone(),
cv_url: self.cv_url.clone(),
portfolio_url: self.portfolio_url.clone(),
is_deleted: self.is_deleted, is_deleted: self.is_deleted,
password: self.password.clone(), password: self.password.clone(),
birthdate: self.birthdate.clone(), birthdate: self.birthdate.clone(),
@@ -217,13 +284,23 @@ impl From<&UsersDetailItemDto> for UsersDetailQueryDto {
Self { Self {
id: crate::make_thing(&imphnen_libs::ResourceEnum::Users.to_string(), &dto.id), id: crate::make_thing(&imphnen_libs::ResourceEnum::Users.to_string(), &dto.id),
fullname: dto.fullname.clone(), fullname: dto.fullname.clone(),
legal_name: dto.legal_name.clone(),
email: dto.email.clone(), email: dto.email.clone(),
avatar: dto.avatar.clone(), avatar: dto.avatar.clone(),
phone_number: dto.phone_number.clone(), phone_number: dto.phone_number.clone(),
phone_for_verification: dto.phone_for_verification.clone(),
is_active: dto.is_active, is_active: dto.is_active,
is_deleted: false, is_deleted: false,
gender: dto.gender.clone(), gender: dto.gender.clone(),
birthdate: dto.birthdate.clone(), birthdate: dto.birthdate.clone(),
domicile: dto.domicile.clone(),
identity_document_url: dto.identity_document_url.clone(),
bio: dto.bio.clone(),
last_education: dto.last_education.clone(),
linkedin_url: dto.linkedin_url.clone(),
github_url: dto.github_url.clone(),
cv_url: dto.cv_url.clone(),
portfolio_url: dto.portfolio_url.clone(),
password: String::new(), password: String::new(),
role: RolesDetailQueryDto::default(), role: RolesDetailQueryDto::default(),
created_at: dto.created_at.clone(), created_at: dto.created_at.clone(),
+60
View File
@@ -9,11 +9,15 @@ use surrealdb::{Uuid, sql::Thing};
pub struct UsersSchema { pub struct UsersSchema {
pub id: Thing, pub id: Thing,
pub fullname: String, pub fullname: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub legal_name: Option<String>,
pub email: String, pub email: String,
pub password: String, pub password: String,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub avatar: Option<String>, pub avatar: Option<String>,
pub phone_number: String, pub phone_number: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub phone_for_verification: Option<String>,
pub is_active: bool, pub is_active: bool,
pub is_deleted: bool, pub is_deleted: bool,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@@ -22,6 +26,22 @@ pub struct UsersSchema {
pub gender: Option<String>, pub gender: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub birthdate: Option<String>, pub birthdate: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub domicile: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub identity_document_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bio: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_education: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub linkedin_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub github_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cv_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub portfolio_url: Option<String>,
pub role: Thing, pub role: Thing,
pub created_at: String, pub created_at: String,
pub updated_at: String, pub updated_at: String,
@@ -35,10 +55,12 @@ impl Default for UsersSchema {
&Uuid::new_v4().to_string(), &Uuid::new_v4().to_string(),
), ),
fullname: String::new(), fullname: String::new(),
legal_name: None,
email: String::new(), email: String::new(),
password: hash_password("").unwrap(), password: hash_password("").unwrap(),
avatar: None, avatar: None,
phone_number: String::new(), phone_number: String::new(),
phone_for_verification: None,
is_active: false, is_active: false,
is_deleted: false, is_deleted: false,
mentor_id: Some(make_thing( mentor_id: Some(make_thing(
@@ -47,6 +69,14 @@ impl Default for UsersSchema {
)), )),
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
role: make_thing( role: make_thing(
&ResourceEnum::Roles.to_string(), &ResourceEnum::Roles.to_string(),
"5713cb37-dc02-4e87-8048-d7a41d352059", "5713cb37-dc02-4e87-8048-d7a41d352059",
@@ -62,9 +92,11 @@ impl UsersSchema {
Self { Self {
id: dto.id, id: dto.id,
fullname: dto.fullname, fullname: dto.fullname,
legal_name: dto.legal_name,
email: dto.email, email: dto.email,
avatar: dto.avatar, avatar: dto.avatar,
phone_number: dto.phone_number, phone_number: dto.phone_number,
phone_for_verification: dto.phone_for_verification,
is_active: dto.is_active, is_active: dto.is_active,
is_deleted: dto.is_deleted, is_deleted: dto.is_deleted,
mentor_id: Some(dto.mentor_id.unwrap_or_else(|| { mentor_id: Some(dto.mentor_id.unwrap_or_else(|| {
@@ -75,6 +107,14 @@ impl UsersSchema {
})), })),
gender: dto.gender, gender: dto.gender,
birthdate: dto.birthdate, birthdate: dto.birthdate,
domicile: dto.domicile,
identity_document_url: dto.identity_document_url,
bio: dto.bio,
last_education: dto.last_education,
linkedin_url: dto.linkedin_url,
github_url: dto.github_url,
cv_url: dto.cv_url,
portfolio_url: dto.portfolio_url,
password: dto.password, password: dto.password,
created_at: dto.created_at, created_at: dto.created_at,
updated_at: dto.updated_at, updated_at: dto.updated_at,
@@ -86,11 +126,21 @@ impl UsersSchema {
Self { Self {
id: make_thing(&ResourceEnum::Users.to_string(), &id), id: make_thing(&ResourceEnum::Users.to_string(), &id),
fullname: user.fullname, fullname: user.fullname,
legal_name: user.legal_name,
email: user.email, email: user.email,
phone_number: user.phone_number, phone_number: user.phone_number,
phone_for_verification: user.phone_for_verification,
is_active: user.is_active, is_active: user.is_active,
gender: user.gender, gender: user.gender,
birthdate: user.birthdate, birthdate: user.birthdate,
domicile: user.domicile,
identity_document_url: user.identity_document_url,
bio: user.bio,
last_education: user.last_education,
linkedin_url: user.linkedin_url,
github_url: user.github_url,
cv_url: user.cv_url,
portfolio_url: user.portfolio_url,
avatar: user.avatar, avatar: user.avatar,
is_deleted: false, is_deleted: false,
role: make_thing(&ResourceEnum::Roles.to_string(), &user.role_id), role: make_thing(&ResourceEnum::Roles.to_string(), &user.role_id),
@@ -107,9 +157,11 @@ impl UsersSchema {
&Uuid::new_v4().to_string(), &Uuid::new_v4().to_string(),
), ),
fullname: user.fullname, fullname: user.fullname,
legal_name: None,
email: user.email, email: user.email,
password, password,
phone_number: user.phone_number, phone_number: user.phone_number,
phone_for_verification: None,
is_active: false, is_active: false,
mentor_id: Some(make_thing( mentor_id: Some(make_thing(
&ResourceEnum::Users.to_string(), &ResourceEnum::Users.to_string(),
@@ -117,6 +169,14 @@ impl UsersSchema {
)), )),
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
avatar: user.avatar, avatar: user.avatar,
is_deleted: false, is_deleted: false,
role: make_thing(&ResourceEnum::Roles.to_string(), &user.role_id), role: make_thing(&ResourceEnum::Roles.to_string(), &user.role_id),
+32
View File
@@ -16,6 +16,7 @@ use imphnen_utils::make_thing;
use uuid::Uuid; use uuid::Uuid;
use anyhow::Result; use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
use tracing::info;
use crate::v1::users::users_dto::{UsersDetailItemDto as UserDto, UsersCreateRequestDto as CreateUserDto}; use crate::v1::users::users_dto::{UsersDetailItemDto as UserDto, UsersCreateRequestDto as CreateUserDto};
#[async_trait] #[async_trait]
@@ -33,6 +34,7 @@ pub trait UsersServiceTrait: Send + Sync + 'static {
async fn get_user_by_email(&self, email: &str) -> Result<Option<UserDto>>; async fn get_user_by_email(&self, email: &str) -> Result<Option<UserDto>>;
async fn create_user_by_dto(&self, new_user: CreateUserDto) -> Result<UserDto>; async fn create_user_by_dto(&self, new_user: CreateUserDto) -> Result<UserDto>;
async fn update_user_avatar(&self, email: &str, avatar_url: Option<String>) -> Result<()>;
} }
#[derive(Clone)] #[derive(Clone)]
@@ -301,4 +303,34 @@ impl UsersServiceTrait for UsersService {
Err(e) => Err(anyhow::anyhow!(e.to_string())), Err(e) => Err(anyhow::anyhow!(e.to_string())),
} }
} }
async fn update_user_avatar(&self, email: &str, avatar_url: Option<String>) -> Result<()> {
let surrealdb_ws = surrealdb_init_ws().await
.map_err(|e| anyhow::anyhow!("Failed to initialize websocket database: {}", e))?;
let surrealdb_mem = surrealdb_init_mem().await
.map_err(|e| anyhow::anyhow!("Failed to initialize memory database: {}", e))?;
let state = AppState {
surrealdb_ws,
surrealdb_mem,
};
let repo = UsersRepository::new(&state);
// Get the existing user
let mut user = repo.query_user_by_email(email.to_string()).await
.map_err(|e| anyhow::anyhow!("Failed to get user: {}", e))?;
// Update the avatar
user.avatar = avatar_url;
// Convert to schema and update
let user_schema = UsersSchema::from(user);
match repo.query_update_user(user_schema).await {
Ok(_) => {
info!("Successfully updated avatar for user: {}", email);
Ok(())
},
Err(e) => Err(anyhow::anyhow!("Failed to update user avatar: {}", e)),
}
}
} }
+8 -2
View File
@@ -191,8 +191,14 @@ mod tests {
let secret = "test_secret"; let secret = "test_secret";
let token = generate_csrf_token(secret).unwrap(); let token = generate_csrf_token(secret).unwrap();
// Should fail with 0 max age // Add a 2 second delay to ensure the token expires when max_age is 1 second
assert!(validate_csrf_token(&token, secret, 0).is_err()); std::thread::sleep(std::time::Duration::from_secs(2));
// Should fail with 1 second max age (token is now 2 seconds old)
assert!(validate_csrf_token(&token, secret, 1).is_err());
// Should still work with a large max age
assert!(validate_csrf_token(&token, secret, 300).is_ok());
} }
#[test] #[test]
+10
View File
@@ -47,13 +47,23 @@ mod auth_login_tests {
id: crate::make_thing("app_users", &uuid::Uuid::new_v4().to_string()), id: crate::make_thing("app_users", &uuid::Uuid::new_v4().to_string()),
email: email.to_string(), email: email.to_string(),
fullname: "Test User".to_string(), fullname: "Test User".to_string(),
legal_name: None,
password: hash_password(password).unwrap(), password: hash_password(password).unwrap(),
is_deleted: false, is_deleted: false,
avatar: None, avatar: None,
phone_number: "081234567890".to_string(), phone_number: "081234567890".to_string(),
phone_for_verification: None,
is_active, is_active,
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
role: crate::make_thing("app_roles", &role.id), role: crate::make_thing("app_roles", &role.id),
mentor_id: None, mentor_id: None,
created_at: imphnen_utils::get_iso_date(), created_at: imphnen_utils::get_iso_date(),
@@ -21,13 +21,23 @@ mod auth_repository_test {
id: make_thing("app_users", &Uuid::new_v4().to_string()), id: make_thing("app_users", &Uuid::new_v4().to_string()),
email: email.to_string(), email: email.to_string(),
fullname: "Test User".to_string(), fullname: "Test User".to_string(),
legal_name: None,
password: "password".to_string(), password: "password".to_string(),
is_deleted: false, is_deleted: false,
avatar: None, avatar: None,
phone_number: "081234567890".to_string(), phone_number: "081234567890".to_string(),
phone_for_verification: None,
is_active: true, is_active: true,
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
role: make_thing("app_roles", &get_role_id(state).await), role: make_thing("app_roles", &get_role_id(state).await),
mentor_id: None, mentor_id: None,
created_at: get_iso_date(), created_at: get_iso_date(),
@@ -71,12 +81,22 @@ mod auth_repository_test {
let mock_user = UsersDetailQueryDto { let mock_user = UsersDetailQueryDto {
id: make_thing(&ResourceEnum::UsersCache.to_string(), &email), id: make_thing(&ResourceEnum::UsersCache.to_string(), &email),
fullname: "Test User".into(), fullname: "Test User".into(),
legal_name: None,
email: email.clone(), email: email.clone(),
avatar: None, avatar: None,
phone_number: "08123456789".into(), phone_number: "08123456789".into(),
phone_for_verification: None,
is_active: true, is_active: true,
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
role: RolesDetailQueryDto { role: RolesDetailQueryDto {
id: make_thing("app_roles", &Uuid::new_v4().to_string()), id: make_thing("app_roles", &Uuid::new_v4().to_string()),
name: "Dummy Role".into(), name: "Dummy Role".into(),
+10
View File
@@ -21,13 +21,23 @@ pub fn create_test_user(
id: make_thing("app_users", &Uuid::new_v4().to_string()), id: make_thing("app_users", &Uuid::new_v4().to_string()),
email: email.to_string(), email: email.to_string(),
fullname: format!("Randomize {} {}", fullname, rand::random::<u32>()), fullname: format!("Randomize {} {}", fullname, rand::random::<u32>()),
legal_name: None,
password: hash_password("secret").unwrap(), password: hash_password("secret").unwrap(),
is_deleted: false, is_deleted: false,
avatar: None, avatar: None,
phone_number: "081234567890".to_string(), phone_number: "081234567890".to_string(),
phone_for_verification: None,
is_active, is_active,
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
role: make_thing("app_roles", role_id), role: make_thing("app_roles", role_id),
created_at: get_iso_date(), created_at: get_iso_date(),
updated_at: get_iso_date(), updated_at: get_iso_date(),
+10
View File
@@ -149,15 +149,25 @@ pub async fn seed_users_for_test(
let user = UsersSchema { let user = UsersSchema {
id: Thing::from(("app_users", id)), id: Thing::from(("app_users", id)),
fullname: fullname.into(), fullname: fullname.into(),
legal_name: None,
email: email.into(), email: email.into(),
password: hash_password("password").unwrap(), password: hash_password("password").unwrap(),
avatar: None, avatar: None,
phone_number: "081234567890".into(), phone_number: "081234567890".into(),
phone_for_verification: None,
is_active: true, is_active: true,
is_deleted: false, is_deleted: false,
mentor_id: None, mentor_id: None,
gender: None, gender: None,
birthdate: None, birthdate: None,
domicile: None,
identity_document_url: None,
bio: None,
last_education: None,
linkedin_url: None,
github_url: None,
cv_url: None,
portfolio_url: None,
role: Thing::from(("app_roles", role_id)), role: Thing::from(("app_roles", role_id)),
created_at: get_iso_date(), created_at: get_iso_date(),
updated_at: get_iso_date(), updated_at: get_iso_date(),