use forbidden::forms::UserPassForm; use forbidden::prelude::*; use forbidden::users::UserPass; use sqlite3; const TEST_PWD: &str = "1"; const USER_1: &str = "user1"; const USER_2: &str = "user2"; const TABLES: &str = " CREATE TABLE users (name TEXT, role TEXT, pwd TEXT); "; // Assert the password is safe, I promise! struct ByPass {} impl PasswordIsSafe for ByPass { fn is_safe(&self, _raw: &str) -> ResultPwd<()> { Ok(()) } } fn to_err(err: sqlite3::Error) -> AuthError { AuthError::Other(Box::new(err)) } struct SqliteProvider { db: sqlite3::Connection, } impl SqliteProvider { pub fn new() -> Result { let p = Password::hash(TEST_PWD, ByPass {}).unwrap(); let db = sqlite3::open(":memory:")?; db.execute(TABLES)?; for x in [USER_1, USER_2] { db.execute(format!( "INSERT INTO users(name, role , pwd) VALUES ('{}', '{}', '{}')", x, "admin", &p.phc ))?; } Ok(SqliteProvider { db }) } } impl IdentityProvider for SqliteProvider { type Identity = UserPass; fn find(&self, id: &str) -> ResultAuth> { let mut cursor = self .db .prepare("SELECT name, pwd FROM users WHERE name = ?") .map_err(to_err)? .cursor(); cursor .bind(&[sqlite3::Value::String(id.into())]) .map_err(to_err)?; while let Some(row) = cursor.next().unwrap() { let pwd = Password::new(&row[1].as_string().unwrap_or_default())?; return Ok(Some(UserPass::new(&row[0].as_string().unwrap(), pwd))); } Ok(None) } fn find_by_token(&self, _token: &String) -> ResultAuth> { todo!() } fn logout(&self, _token: &String) -> ResultAuth { Ok(true) } } impl IdentityProviderUserPwd for SqliteProvider { fn verify_password(&self, credentials: &UserPassForm) -> ResultAuth { if let Some(user) = self.find(&credentials.username)? { user.pwd.validate_password(&credentials.pwd)?; Ok(credentials.username.clone()) } else { Err(AuthError::UserNotFound { named: credentials.username.clone(), }) } } } fn main() -> ResultAuth<()> { let idp = SqliteProvider::new().unwrap(); assert!(idp.find(USER_1)?.is_some()); let mut form = UserPassForm::new(USER_1, "wrong"); assert!(idp.login(&form).is_err()); form.pwd = TEST_PWD.into(); assert!(idp.login(&form).is_ok()); Ok(()) }