User passwords
This commit is contained in:
parent
348d37d26e
commit
22edb9aac9
@ -1,10 +1,10 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n SELECT \n id as \"id: Uuid\",\n username,\n email,\n display_name,\n created_at as \"created_at: chrono::DateTime<chrono::Utc>\"\n FROM users\n ",
|
||||
"query": "\n SELECT \n id as \"id: String\",\n username,\n password_hash,\n email,\n display_name,\n created_at as \"created_at: chrono::DateTime<chrono::Utc>\"\n FROM users\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id: Uuid",
|
||||
"name": "id: String",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
},
|
||||
@ -14,25 +14,31 @@
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"name": "password_hash",
|
||||
"ordinal": 2,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "display_name",
|
||||
"name": "email",
|
||||
"ordinal": 3,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"name": "display_name",
|
||||
"ordinal": 4,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 0
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
@ -40,5 +46,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "3577e56d051f360866f893491584cccae7d2e985742ca78be06011e6c6640fc2"
|
||||
"hash": "d04ca7e16ebbeb1213fc829a4ff1337427c6875e750c6d3570a314fe3136d36f"
|
||||
}
|
55
Cargo.lock
generated
55
Cargo.lock
generated
@ -169,12 +169,31 @@ version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"blowfish",
|
||||
"getrandom 0.2.15",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binascii"
|
||||
version = "0.1.4"
|
||||
@ -214,6 +233,16 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blowfish"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.11.3"
|
||||
@ -300,6 +329,16 @@ dependencies = [
|
||||
"phf_codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
@ -1247,6 +1286,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.15"
|
||||
@ -2144,6 +2192,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"atom_syndication",
|
||||
"bcrypt",
|
||||
"chrono",
|
||||
"rocket",
|
||||
"rocket_db_pools",
|
||||
@ -2189,7 +2238,7 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2515,7 +2564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.8.0",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
@ -2559,7 +2608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.8.0",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
|
@ -13,3 +13,4 @@ rocket_dyn_templates = { version = "0.2.0", features = ["tera"] }
|
||||
rss = "2.0.11"
|
||||
sqlx = { version = "0.7", features = ["runtime-tokio", "sqlite", "chrono", "uuid"] }
|
||||
uuid = { version = "1.7.0", features = ["v4", "serde"] }
|
||||
bcrypt = "0.15"
|
||||
|
1
migrations/20240320000000_add_password_hash.sql
Normal file
1
migrations/20240320000000_add_password_hash.sql
Normal file
@ -0,0 +1 @@
|
||||
|
2
migrations/20240320000001_add_password_hash.sql
Normal file
2
migrations/20240320000001_add_password_hash.sql
Normal file
@ -0,0 +1,2 @@
|
||||
-- Add password_hash column
|
||||
ALTER TABLE users ADD COLUMN password_hash TEXT NOT NULL DEFAULT '';
|
25
src/main.rs
25
src/main.rs
@ -7,6 +7,7 @@ use rocket::serde::{json::Json, Deserialize, Serialize};
|
||||
use rocket_db_pools::{sqlx, Connection, Database};
|
||||
use rocket_dyn_templates::{context, Template};
|
||||
use uuid::Uuid;
|
||||
use bcrypt;
|
||||
|
||||
#[derive(Database)]
|
||||
#[database("rss_data")]
|
||||
@ -24,16 +25,18 @@ struct Message {
|
||||
struct User {
|
||||
id: Uuid,
|
||||
username: String,
|
||||
password_hash: String,
|
||||
email: Option<String>,
|
||||
display_name: Option<String>,
|
||||
created_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
|
||||
impl User {
|
||||
fn new(username: String, email: Option<String>, display_name: Option<String>) -> Self {
|
||||
fn new(username: String, password_hash: String, email: Option<String>, display_name: Option<String>) -> Self {
|
||||
User {
|
||||
id: Uuid::new_v4(),
|
||||
username,
|
||||
password_hash,
|
||||
email,
|
||||
display_name,
|
||||
created_at: chrono::Utc::now(),
|
||||
@ -45,6 +48,7 @@ impl User {
|
||||
#[serde(crate = "rocket::serde")]
|
||||
struct NewUser {
|
||||
username: String,
|
||||
password: String,
|
||||
email: Option<String>,
|
||||
display_name: Option<String>,
|
||||
}
|
||||
@ -68,11 +72,24 @@ async fn create_user(
|
||||
new_user: Json<NewUser>,
|
||||
) -> Result<Json<User>, Status> {
|
||||
let new_user = new_user.into_inner();
|
||||
let user = User::new(new_user.username, new_user.email, new_user.display_name);
|
||||
|
||||
// Hash the password - we'll use bcrypt
|
||||
let password_hash = bcrypt::hash(new_user.password.as_bytes(), bcrypt::DEFAULT_COST)
|
||||
.map_err(|_| Status::InternalServerError)?;
|
||||
|
||||
let user = User::new(
|
||||
new_user.username,
|
||||
password_hash,
|
||||
new_user.email,
|
||||
new_user.display_name
|
||||
);
|
||||
|
||||
let query = sqlx::query("INSERT INTO users (id, username, email, display_name, created_at) VALUES (?1, ?2, ?3, ?4, ?5)")
|
||||
let query = sqlx::query(
|
||||
"INSERT INTO users (id, username, password_hash, email, display_name, created_at) VALUES (?1, ?2, ?3, ?4, ?5, ?6)"
|
||||
)
|
||||
.bind(user.id.to_string())
|
||||
.bind(user.username.as_str())
|
||||
.bind(user.password_hash.as_str())
|
||||
.bind(user.email.as_ref())
|
||||
.bind(user.display_name.as_ref())
|
||||
.bind(user.created_at.to_rfc3339())
|
||||
@ -99,6 +116,7 @@ async fn get_users(mut db: Connection<Db>) -> Result<Json<Vec<User>>, Status> {
|
||||
SELECT
|
||||
id as "id: String",
|
||||
username,
|
||||
password_hash,
|
||||
email,
|
||||
display_name,
|
||||
created_at as "created_at: chrono::DateTime<chrono::Utc>"
|
||||
@ -118,6 +136,7 @@ async fn get_users(mut db: Connection<Db>) -> Result<Json<Vec<User>>, Status> {
|
||||
.map(|row| User {
|
||||
id: Uuid::parse_str(&row.id).unwrap(),
|
||||
username: row.username,
|
||||
password_hash: row.password_hash,
|
||||
email: row.email,
|
||||
display_name: row.display_name,
|
||||
created_at: row.created_at,
|
||||
|
Loading…
Reference in New Issue
Block a user