Save SignedInUser on drop, and make changes necessary to that end
Which was a surprisingly large number of changes /shrug
This commit is contained in:
parent
e7cf782a60
commit
18228bb1c5
|
@ -105,12 +105,12 @@ impl UserManager {
|
|||
if let Some(certificate_data) = self.lookup_certificate(cert_hash)? {
|
||||
let user_inner = self.lookup_user(&certificate_data.owner_username)?
|
||||
.expect("Database corruption: Certificate data refers to non-existant user");
|
||||
Ok(User::SignedIn(SignedInUser {
|
||||
username: certificate_data.owner_username,
|
||||
active_certificate: certificate_data.certificate,
|
||||
manager: self.clone(),
|
||||
inner: user_inner,
|
||||
}))
|
||||
Ok(User::SignedIn(SignedInUser::new(
|
||||
certificate_data.owner_username,
|
||||
certificate_data.certificate,
|
||||
self.clone(),
|
||||
user_inner,
|
||||
)))
|
||||
} else {
|
||||
Ok(User::NotSignedIn(NotSignedInUser {
|
||||
certificate: certificate.clone(),
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
//! [`UserManager::lookup_user()`] method. Unlinke with [`SignedInUser`], these are not
|
||||
//! committed on drop, and [`PartialUser::store()`] must be manually called
|
||||
use rustls::Certificate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
||||
use sled::Transactional;
|
||||
|
||||
use crate::user_management::UserManager;
|
||||
|
@ -86,7 +86,7 @@ impl<UserData> AsMut<UserData> for PartialUser<UserData> {
|
|||
|
||||
/// Any information about the connecting user
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum User<UserData> {
|
||||
pub enum User<UserData: Serialize + DeserializeOwned> {
|
||||
/// A user who is connected without using a client certificate.
|
||||
///
|
||||
/// This could be a user who has an account but just isn't presenting a certificate at
|
||||
|
@ -124,28 +124,25 @@ impl NotSignedInUser {
|
|||
/// The provided username must be unique, or else an error will be raised.
|
||||
///
|
||||
/// Additional errors might occur if there is a problem writing to the database
|
||||
pub fn register<UserData>(
|
||||
pub fn register<UserData: Serialize + DeserializeOwned + Default>(
|
||||
self,
|
||||
username: String,
|
||||
) -> Result<SignedInUser<UserData>>
|
||||
where
|
||||
UserData: Serialize + Default
|
||||
{
|
||||
) -> Result<SignedInUser<UserData>> {
|
||||
if self.manager.users.contains_key(username.as_str())? {
|
||||
Err(super::UserManagerError::UsernameNotUnique)
|
||||
} else {
|
||||
let cert_hash = UserManager::hash_certificate(&self.certificate);
|
||||
|
||||
let newser = SignedInUser {
|
||||
inner: PartialUser {
|
||||
let newser = SignedInUser::new(
|
||||
username.clone(),
|
||||
self.certificate.clone(),
|
||||
self.manager,
|
||||
PartialUser {
|
||||
data: UserData::default(),
|
||||
certificates: vec![cert_hash],
|
||||
pass_hash: None,
|
||||
},
|
||||
username: username.clone(),
|
||||
active_certificate: self.certificate.clone(),
|
||||
manager: self.manager,
|
||||
};
|
||||
);
|
||||
|
||||
let cert_info = CertificateData {
|
||||
certificate: self.certificate,
|
||||
|
@ -188,13 +185,10 @@ impl NotSignedInUser {
|
|||
///
|
||||
/// Additional errors might occur if an error occurs during database lookup and
|
||||
/// deserialization
|
||||
pub fn attach<'de, UserData>(
|
||||
pub fn attach<UserData: Serialize + DeserializeOwned>(
|
||||
username: impl AsRef<[u8]>,
|
||||
password: impl AsRef<[u8]>,
|
||||
) -> Result<SignedInUser<UserData>>
|
||||
where
|
||||
UserData: Serialize + Deserialize<'de>
|
||||
{
|
||||
) -> Result<SignedInUser<UserData>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -203,16 +197,35 @@ impl NotSignedInUser {
|
|||
/// Data about a logged in user
|
||||
///
|
||||
/// For more information about the user lifecycle and sign-in stages, see [`User`]
|
||||
pub struct SignedInUser<UserData> {
|
||||
pub struct SignedInUser<UserData: Serialize + DeserializeOwned> {
|
||||
pub (crate) username: String,
|
||||
pub (crate) active_certificate: Certificate,
|
||||
pub (crate) manager: UserManager,
|
||||
pub (crate) inner: PartialUser<UserData>,
|
||||
/// Indicates that [`SignedInUser::as_mut()`] has been called, but [`SignedInUser::save()`] has not
|
||||
has_changed: bool,
|
||||
}
|
||||
|
||||
impl<UserData> SignedInUser<UserData> {
|
||||
impl<UserData: Serialize + DeserializeOwned> SignedInUser<UserData> {
|
||||
|
||||
/// Create a new user from parts
|
||||
pub (crate) fn new(
|
||||
username: String,
|
||||
active_certificate: Certificate,
|
||||
manager: UserManager,
|
||||
inner: PartialUser<UserData>
|
||||
) -> Self {
|
||||
Self {
|
||||
username,
|
||||
active_certificate,
|
||||
manager,
|
||||
inner,
|
||||
has_changed: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the [`Certificate`] that the user is currently using to connect.
|
||||
pub const fn active_certificate(&self) -> &Certificate {
|
||||
pub fn active_certificate(&self) -> &Certificate {
|
||||
&self.active_certificate
|
||||
}
|
||||
|
||||
|
@ -232,7 +245,7 @@ impl<UserData> SignedInUser<UserData> {
|
|||
/// Get the user's current username.
|
||||
///
|
||||
/// NOTE: This is not guaranteed not to change.
|
||||
pub const fn username(&self) -> &String {
|
||||
pub fn username(&self) -> &String {
|
||||
&self.username
|
||||
}
|
||||
|
||||
|
@ -256,24 +269,37 @@ impl<UserData> SignedInUser<UserData> {
|
|||
///
|
||||
/// Updates caused by calling methods directly on the user do not need to be saved.
|
||||
/// This is only for changes made to the UserData.
|
||||
pub fn save(&self) -> Result<()>
|
||||
pub fn save(&mut self) -> Result<()>
|
||||
where
|
||||
UserData: Serialize
|
||||
{
|
||||
self.inner.store(&self.manager.users, &self.username)
|
||||
self.inner.store(&self.manager.users, &self.username)?;
|
||||
self.has_changed = false;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<UserData> AsRef<UserData> for SignedInUser<UserData> {
|
||||
impl<UserData: Serialize + DeserializeOwned> std::ops::Drop for SignedInUser<UserData> {
|
||||
fn drop(&mut self) {
|
||||
if self.has_changed {
|
||||
if let Err(e) = self.save() {
|
||||
error!("Failed to save user data to database: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<UserData: Serialize + DeserializeOwned> AsRef<UserData> for SignedInUser<UserData> {
|
||||
fn as_ref(&self) -> &UserData {
|
||||
&self.inner.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<UserData> AsMut<UserData> for SignedInUser<UserData> {
|
||||
impl<UserData: Serialize + DeserializeOwned> AsMut<UserData> for SignedInUser<UserData> {
|
||||
/// NOTE: Changes made to the user data won't be persisted until SignedInUser::save
|
||||
/// is called
|
||||
fn as_mut(&mut self) -> &mut UserData {
|
||||
self.has_changed = true;
|
||||
&mut self.inner.data
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue