|
@@ -10,11 +10,6 @@ pub enum UserError {
|
|
|
InvalidInput,
|
|
|
}
|
|
|
|
|
|
-pub struct User<'a> {
|
|
|
- realm: &'a schema::Realm,
|
|
|
- user: Stored<schema::User>,
|
|
|
-}
|
|
|
-
|
|
|
static PBKDF2_ROUNDS: std::num::NonZeroU32 = unsafe { std::num::NonZeroU32::new_unchecked(20000) };
|
|
|
|
|
|
fn generate_totp_digits(secret: &[u8], time_offset: isize) -> Result<u32, UIDCError> {
|
|
@@ -39,12 +34,11 @@ fn generate_totp_digits(secret: &[u8], time_offset: isize) -> Result<u32, UIDCEr
|
|
|
Ok(truncation % 1_000_000)
|
|
|
}
|
|
|
|
|
|
-impl<'a> User<'a> {
|
|
|
- pub fn from_schema(realm: &'a schema::Realm, user: Stored<schema::User>) -> Self {
|
|
|
- Self { realm, user }
|
|
|
- }
|
|
|
+pub trait UserExt {
|
|
|
+ fn stored_user(&self) -> &Stored<schema::User>;
|
|
|
|
|
|
- pub fn change_username(&mut self, new_name: &String) -> Result<(), UIDCError> {
|
|
|
+ /*fn change_username(&mut self, new_name: &String) -> Result<(), UIDCError> {
|
|
|
+ let realm = self.stored_user().realm;
|
|
|
// check to ensure the new username isn't already in use
|
|
|
if self.realm.users.with(schema::User::Username, new_name).first().get()?.is_some() {
|
|
|
Err(UIDCError::Abort("username already in use"))
|
|
@@ -53,18 +47,18 @@ impl<'a> User<'a> {
|
|
|
self.user.sync()?;
|
|
|
Ok(())
|
|
|
}
|
|
|
- }
|
|
|
+ }*/
|
|
|
|
|
|
/// returns Ok(true) if challenge passed, Ok(false) if challenge failed, and
|
|
|
/// UserError::NoSuchChallenge if challenge not found
|
|
|
- pub fn verify_challenge_by_type(
|
|
|
+ fn verify_challenge_by_type(
|
|
|
&self,
|
|
|
challenge_type: schema::AuthChallengeType,
|
|
|
response: &[u8],
|
|
|
) -> Result<bool, UIDCError> {
|
|
|
let ct = challenge_type.into();
|
|
|
let challenge = self
|
|
|
- .user
|
|
|
+ .stored_user()
|
|
|
.auth
|
|
|
.with(schema::AuthChallenge::ChallengeType, &ct)
|
|
|
.first()
|
|
@@ -78,9 +72,8 @@ impl<'a> User<'a> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- pub fn set_new_password(&self, password: &[u8]) -> Result<(), UIDCError> {
|
|
|
- self.user
|
|
|
- .auth
|
|
|
+ fn set_new_password(&self, password: &[u8]) -> Result<(), UIDCError> {
|
|
|
+ self.stored_user().auth
|
|
|
.with(
|
|
|
schema::AuthChallenge::ChallengeType,
|
|
|
&schema::AuthChallengeType::Password.into(),
|
|
@@ -102,8 +95,8 @@ impl<'a> User<'a> {
|
|
|
&mut generated,
|
|
|
);
|
|
|
|
|
|
- self.user.auth.insert(schema::AuthChallenge {
|
|
|
- user_id: self.user.id(),
|
|
|
+ self.stored_user().auth.insert(schema::AuthChallenge {
|
|
|
+ user_id: self.stored_user().id(),
|
|
|
challenge_type: schema::AuthChallengeType::Password.into(),
|
|
|
public: salt.into(),
|
|
|
secret: generated.into(),
|
|
@@ -113,7 +106,7 @@ impl<'a> User<'a> {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
- pub fn generate_totp_with_uri(&self) -> Result<(Vec<u8>, String), UIDCError> {
|
|
|
+ fn generate_totp_with_uri(&self) -> Result<(Vec<u8>, String), UIDCError> {
|
|
|
let rng = ring::rand::SystemRandom::new();
|
|
|
let secret: [u8; 16] = ring::rand::generate(&rng)
|
|
|
.expect("Couldn't generate random secret?")
|
|
@@ -126,16 +119,16 @@ impl<'a> User<'a> {
|
|
|
|
|
|
let uri = format!(
|
|
|
"otpauth://totp/uidc:{username}@uidc?secret={uri_secret}&issuer=uidc",
|
|
|
- username = self.user.username
|
|
|
+ username = self.stored_user().username
|
|
|
);
|
|
|
|
|
|
Ok((secret.into(), uri))
|
|
|
}
|
|
|
|
|
|
- pub fn set_new_totp(&self, secret: &[u8]) -> Result<(), UIDCError> {
|
|
|
+ fn set_new_totp(&self, secret: &[u8]) -> Result<(), UIDCError> {
|
|
|
self.clear_totp()?;
|
|
|
- self.user.auth.insert(schema::AuthChallenge {
|
|
|
- user_id: self.user.id(),
|
|
|
+ self.stored_user().auth.insert(schema::AuthChallenge {
|
|
|
+ user_id: self.stored_user().id(),
|
|
|
challenge_type: schema::AuthChallengeType::TOTP.into(),
|
|
|
public: vec![],
|
|
|
secret: secret.into(),
|
|
@@ -145,9 +138,8 @@ impl<'a> User<'a> {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
- pub fn clear_totp(&self) -> Result<(), UIDCError> {
|
|
|
- self.user
|
|
|
- .auth
|
|
|
+ fn clear_totp(&self) -> Result<(), UIDCError> {
|
|
|
+ self.stored_user().auth
|
|
|
.with(
|
|
|
schema::AuthChallenge::ChallengeType,
|
|
|
&schema::AuthChallengeType::TOTP.into(),
|
|
@@ -157,6 +149,10 @@ impl<'a> User<'a> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+impl UserExt for Stored<schema::User> {
|
|
|
+ fn stored_user(&self) -> &Stored<schema::User> { self }
|
|
|
+}
|
|
|
+
|
|
|
impl schema::AuthChallenge {
|
|
|
pub fn verify_password_challenge(&self, response: &[u8]) -> Result<bool, UIDCError> {
|
|
|
use ring::pbkdf2;
|