51 lines
1.3 KiB
Rust
51 lines
1.3 KiB
Rust
use crate::prelude::*;
|
|
use chrono::Utc;
|
|
use redact::{expose_secret, Secret};
|
|
use serde::{Deserialize, Serialize};
|
|
use thiserror::Error;
|
|
|
|
pub const USER_TREE: &str = "user";
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct User {
|
|
pub username: String,
|
|
|
|
#[serde(serialize_with = "expose_secret")]
|
|
password_digest: Secret<Vec<u8>>,
|
|
|
|
pub registered_at: chrono::DateTime<Utc>,
|
|
}
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum Error {
|
|
#[error("username exists: {0}")]
|
|
UsernameExists(Box<String>),
|
|
|
|
#[error("username not found: {0}")]
|
|
UsernameNotFound(Box<String>),
|
|
}
|
|
|
|
impl User {
|
|
pub const fn tree() -> &'static str {
|
|
USER_TREE
|
|
}
|
|
|
|
pub fn try_new(username: &str, password: &str) -> Result<Self, argon2::password_hash::Error> {
|
|
Ok(Self {
|
|
username: username.to_owned(),
|
|
registered_at: Utc::now(),
|
|
password_digest: Secret::new(crate::auth::password_digest(password)?.into()),
|
|
})
|
|
}
|
|
|
|
pub fn verify(&self, password: &str) -> Result<(), argon2::password_hash::Error> {
|
|
crate::auth::verified_password(password, self.password_digest.expose_secret())
|
|
}
|
|
}
|
|
|
|
impl TryFrom<sled::IVec> for User {
|
|
type Error = bincode::Error;
|
|
fn try_from(value: sled::IVec) -> Result<Self, Self::Error> {
|
|
bincode::deserialize(&value)
|
|
}
|
|
}
|