LCOV - code coverage report
Current view: top level - src - user.rs (source / functions) Coverage Total Hit
Test: bliki.lcov Lines: 100.0 % 32 32
Test Date: 2025-11-27 15:46:07 Functions: 100.0 % 6 6

            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              : }
        

Generated by: LCOV version 2.0-1