1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#![warn(missing_docs)]
//! # `libadmin` database operations
//!
//! Traits and datastructures used in libadmin to interact with database.
//!
//! To use an unsupported database with libadmin, traits present within this crate should be
//! implemented.
//!
//!
//! ## Organisation
//!
//! Database functionallity is divided accross various modules:
//!
//! - [errors](crate::auth): error data structures used in this crate
//! - [ops](crate::ops): meta operations like connection pool creation, migrations and getting
//! connection from pool
pub mod errors;
pub mod ops;
#[cfg(feature = "test")]
pub mod tests;

pub use ops::GetConnection;

pub mod prelude {
    //! useful imports for users working with a supported database

    pub use super::errors::*;
    pub use super::ops::*;
    pub use super::*;
}

pub mod dev {
    //! useful imports for supporting a new database
    pub use super::prelude::*;
    pub use async_trait::async_trait;
}

/// data structure describing credentials of a user
#[derive(Clone, Debug)]
pub struct Creds {
    /// username
    pub username: String,
    /// password
    pub password: String,
}

/// data structure containing only a password field
#[derive(Clone, Debug)]
pub struct Password {
    /// password
    pub password: String,
}

/// payload to register a user with username _and_ email
pub struct EmailRegisterPayload<'a> {
    /// username of new user
    pub username: &'a str,
    /// password of new user
    pub password: &'a str,
    /// password of new user
    pub email: &'a str,
    /// a randomly generated secret associated with an account
    pub secret: &'a str,
}

/// payload to register a user with only username
pub struct UsernameRegisterPayload<'a> {
    /// username provided during registration
    pub username: &'a str,
    /// password of new user
    pub password: &'a str,
    /// a randomly generated secret associated with an account
    pub secret: &'a str,
}

/// payload to update email in the database
#[derive(Clone, Debug)]
pub struct UpdateEmailPayload<'a> {
    /// name of the user who's email is to be updated
    pub username: &'a str,
    /// new email
    pub email: &'a str,
}

/// payload to update a username in database
pub struct UpdateUsernamePayload<'a> {
    /// old usename
    pub old_username: &'a str,
    /// new username
    pub new_username: &'a str,
}

use dev::*;
/// foo
#[async_trait]
pub trait LibAdminDatabase: std::marker::Send + std::marker::Sync {
    /// Update email of specified user in database
    async fn update_email(&self, payload: &UpdateEmailPayload) -> DBResult<()>;
    /// Update password of specified user in database
    async fn update_password(&self, payload: &Creds) -> DBResult<()>;
    /// check if an email exists in the database
    async fn email_exists(&self, email: &str) -> DBResult<bool>;
    /// delete account from database
    async fn delete_account(&self, username: &str) -> DBResult<()>;
    /// check if a username exists in the database
    async fn username_exists(&self, username: &str) -> DBResult<bool>;
    /// update username in database
    async fn update_username(&self, payload: &UpdateUsernamePayload) -> DBResult<()>;
    /// update secret in database
    async fn update_secret(&self, username: &str, secret: &str) -> DBResult<()>;
    /// update secret in database
    async fn get_secret(&self, username: &str) -> DBResult<String>;
    /// login with email as user-identifier
    async fn email_login(&self, email: &str) -> DBResult<Creds>;
    /// login with username as user-identifier
    async fn username_login(&self, username: &str) -> DBResult<Password>;
    /// username _and_ email is available during registration
    async fn email_register(&self, payload: &EmailRegisterPayload) -> DBResult<()>;
    /// register with username
    async fn username_register(&self, payload: &UsernameRegisterPayload) -> DBResult<()>;
}

#[async_trait]
impl<T: LibAdminDatabase + ?Sized> LibAdminDatabase for Box<T> {
    async fn update_email(&self, payload: &UpdateEmailPayload) -> DBResult<()> {
        (**self).update_email(payload).await
    }
    /// Update password of specified user in database
    async fn update_password(&self, payload: &Creds) -> DBResult<()> {
        (**self).update_password(payload).await
    }
    /// check if an email exists in the database
    async fn email_exists(&self, email: &str) -> DBResult<bool> {
        (**self).email_exists(email).await
    }
    /// delete account from database
    async fn delete_account(&self, username: &str) -> DBResult<()> {
        (**self).delete_account(username).await
    }
    /// check if a username exists in the database
    async fn username_exists(&self, username: &str) -> DBResult<bool> {
        (**self).username_exists(username).await
    }
    /// update username in database
    async fn update_username(&self, payload: &UpdateUsernamePayload) -> DBResult<()> {
        (**self).update_username(payload).await
    }
    /// update secret in database
    async fn update_secret(&self, username: &str, secret: &str) -> DBResult<()> {
        (**self).update_secret(username, secret).await
    }
    /// update secret in database
    async fn get_secret(&self, username: &str) -> DBResult<String> {
        (**self).get_secret(username).await
    }
    /// login with email as user-identifier
    async fn email_login(&self, email: &str) -> DBResult<Creds> {
        (**self).email_login(email).await
    }
    /// login with username as user-identifier
    async fn username_login(&self, username: &str) -> DBResult<Password> {
        (**self).username_login(username).await
    }
    /// username _and_ email is available during registration
    async fn email_register(&self, payload: &EmailRegisterPayload) -> DBResult<()> {
        (**self).email_register(payload).await
    }
    /// register with username
    async fn username_register(&self, payload: &UsernameRegisterPayload) -> DBResult<()> {
        (**self).username_register(payload).await
    }
}