#[cfg(any(feature = "postgres", feature = "sqlite"))]
pub(in crate::biome) mod diesel;
pub mod error;
pub(in crate::biome) mod memory;
use crate::error::InvalidStateError;
use serde::{Deserialize, Serialize};
pub use error::UserProfileStoreError;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Profile {
user_id: String,
subject: String,
name: Option<String>,
given_name: Option<String>,
family_name: Option<String>,
email: Option<String>,
picture: Option<String>,
}
impl Profile {
pub fn user_id(&self) -> &str {
&self.user_id
}
pub fn subject(&self) -> &str {
&self.subject
}
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub fn given_name(&self) -> Option<&str> {
self.given_name.as_deref()
}
pub fn family_name(&self) -> Option<&str> {
self.family_name.as_deref()
}
pub fn email(&self) -> Option<&str> {
self.email.as_deref()
}
pub fn picture(&self) -> Option<&str> {
self.picture.as_deref()
}
}
#[derive(Default)]
pub struct ProfileBuilder {
user_id: Option<String>,
subject: Option<String>,
name: Option<String>,
given_name: Option<String>,
family_name: Option<String>,
email: Option<String>,
picture: Option<String>,
}
impl ProfileBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_user_id(mut self, user_id: String) -> ProfileBuilder {
self.user_id = Some(user_id);
self
}
pub fn with_subject(mut self, subject: String) -> ProfileBuilder {
self.subject = Some(subject);
self
}
pub fn with_name(mut self, name: Option<String>) -> ProfileBuilder {
self.name = name;
self
}
pub fn with_given_name(mut self, given_name: Option<String>) -> ProfileBuilder {
self.given_name = given_name;
self
}
pub fn with_family_name(mut self, family_name: Option<String>) -> ProfileBuilder {
self.family_name = family_name;
self
}
pub fn with_email(mut self, email: Option<String>) -> ProfileBuilder {
self.email = email;
self
}
pub fn with_picture(mut self, picture: Option<String>) -> ProfileBuilder {
self.picture = picture;
self
}
pub fn build(self) -> Result<Profile, InvalidStateError> {
Ok(Profile {
user_id: self.user_id.ok_or_else(|| {
InvalidStateError::with_message("A user id is required to build a Profile".into())
})?,
subject: self.subject.ok_or_else(|| {
InvalidStateError::with_message("A subject is required to build a Profile".into())
})?,
name: self.name,
given_name: self.given_name,
family_name: self.family_name,
email: self.email,
picture: self.picture,
})
}
}
pub trait UserProfileStore: Sync + Send {
fn add_profile(&self, profile: Profile) -> Result<(), UserProfileStoreError>;
fn update_profile(&self, profile: Profile) -> Result<(), UserProfileStoreError>;
fn remove_profile(&self, user_id: &str) -> Result<(), UserProfileStoreError>;
fn get_profile(&self, user_id: &str) -> Result<Profile, UserProfileStoreError>;
fn list_profiles(&self) -> Result<Option<Vec<Profile>>, UserProfileStoreError>;
fn clone_box(&self) -> Box<dyn UserProfileStore>;
}
impl Clone for Box<dyn UserProfileStore> {
fn clone(&self) -> Self {
self.clone_box()
}
}
impl<PS> UserProfileStore for Box<PS>
where
PS: UserProfileStore + ?Sized,
{
fn add_profile(&self, profile: Profile) -> Result<(), UserProfileStoreError> {
(**self).add_profile(profile)
}
fn update_profile(&self, profile: Profile) -> Result<(), UserProfileStoreError> {
(**self).update_profile(profile)
}
fn remove_profile(&self, user_id: &str) -> Result<(), UserProfileStoreError> {
(**self).remove_profile(user_id)
}
fn get_profile(&self, user_id: &str) -> Result<Profile, UserProfileStoreError> {
(**self).get_profile(user_id)
}
fn list_profiles(&self) -> Result<Option<Vec<Profile>>, UserProfileStoreError> {
(**self).list_profiles()
}
fn clone_box(&self) -> Box<dyn UserProfileStore> {
(**self).clone_box()
}
}