Line data Source code
1 : use password_auth::{generate_hash, verify_password};
2 : use rusqlite::Connection;
3 : use serde::Serialize;
4 :
5 : // pub struct UserId(i64);
6 :
7 : #[derive(Debug, Serialize)]
8 : pub struct User {
9 : pub user_id: i64,
10 : username: String,
11 : }
12 :
13 : /// Adds a user with `username` and `password`.
14 1 : pub fn add_user(db: &Connection, username: String, password: &[u8]) -> rusqlite::Result<i64> {
15 1 : let password_hash = generate_hash(password);
16 1 : let mut stmt =
17 1 : db.prepare("INSERT INTO users (username, password_hash) VALUES (?, ?) RETURNING user_id")?;
18 1 : let user_id: i64 = stmt.query_row([username, password_hash], |row| row.get("user_id"))?;
19 1 : Ok(user_id)
20 1 : }
21 :
22 : /// Checks the user has the `password`.
23 7 : pub fn verify_user(
24 7 : db: &Connection,
25 7 : username: String,
26 7 : password: &[u8],
27 7 : ) -> rusqlite::Result<Option<User>> {
28 7 : let mut stmt =
29 7 : db.prepare("SELECT password_hash, user_id, username FROM users where username = ?")?;
30 7 : let (password_hash, user_id, username): (String, i64, String) =
31 7 : stmt.query_row([username], |row| {
32 7 : let password_hash: String = row.get("password_hash")?;
33 7 : let user_id: i64 = row.get("user_id")?;
34 7 : let username: String = row.get("username")?;
35 7 : Ok((password_hash, user_id, username))
36 7 : })?;
37 :
38 7 : if verify_password(password, &password_hash).is_ok() {
39 5 : Ok(Some(User { user_id, username }))
40 : } else {
41 2 : Ok(None)
42 : }
43 7 : }
44 :
45 3 : pub fn find_by_id(db: &Connection, user_id: i64) -> rusqlite::Result<Option<User>> {
46 3 : let mut stmt = db.prepare("SELECT * FROM users where user_id = ?")?;
47 3 : let user = stmt.query_row([user_id], |row| {
48 3 : Ok(User { user_id: row.get("user_id")?, username: row.get("username")? })
49 3 : })?;
50 3 : Ok(Some(user))
51 3 : }
52 :
53 : #[cfg(test)]
54 : mod tests {
55 : use super::*;
56 : use crate::db::setup_db;
57 : use googletest::prelude::*;
58 :
59 : #[gtest]
60 : fn test_add_user() -> Result<()> {
61 : let db = setup_db(None);
62 : add_user(&db, "janedoe".to_string(), "バッドばつ丸".as_bytes())?;
63 : let ret = verify_user(&db, "janedoe".to_string(), "バッドばつ丸".as_bytes())?;
64 : expect_that!(ret, some(pat!(User { username: "janedoe", .. })));
65 :
66 : let ret = verify_user(&db, "janedoe".to_string(), "ばつpass".as_bytes())?;
67 : assert!(ret.is_none());
68 : Ok(())
69 : }
70 : }
|