fix errors, move password hashing into User add sqlx offline checks
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Patrick Michl 2022-04-28 21:55:52 +02:00
parent 601b2d4f42
commit 304f82baa4
7 changed files with 219 additions and 13 deletions

View File

@ -5,5 +5,7 @@ name: check
steps: steps:
- name: cargo check - name: cargo check
image: rust:latest image: rust:latest
environment:
SQLX_OFFLINE: 'true'
commands: commands:
- cargo check - cargo check

7
Cargo.lock generated
View File

@ -252,6 +252,9 @@ name = "either"
version = "1.6.1" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "event-listener" name = "event-listener"
@ -1078,6 +1081,7 @@ dependencies = [
"paste", "paste",
"percent-encoding", "percent-encoding",
"rustls", "rustls",
"serde",
"sha2", "sha2",
"smallvec", "smallvec",
"sqlformat", "sqlformat",
@ -1099,9 +1103,12 @@ dependencies = [
"dotenv", "dotenv",
"either", "either",
"heck", "heck",
"hex",
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde",
"serde_json",
"sha2", "sha2",
"sqlx-core", "sqlx-core",
"sqlx-rt", "sqlx-rt",

View File

@ -12,8 +12,8 @@ tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] }
serde = {version = "1.0", features = ["derive"] } serde = {version = "1.0", features = ["derive"] }
tower-http = { version = "0.2", features = ["cors", "trace"]} tower-http = { version = "0.2", features = ["cors", "trace"]}
sqlx = { version = "0.5", features = ["sqlite", "macros", "runtime-tokio-rustls"] } sqlx = { version = "0.5", features = ["sqlite", "macros", "runtime-tokio-rustls", "offline"] }
anyhow = "1.0" anyhow = "1.0"
thiserror = "1.0" thiserror = "1.0"
argon2 = "0.4" argon2 = { version = "0.4", features = ["std"] }
rand_core = { version = "0.6", features = ["std"] } rand_core = { version = "0.6", features = ["std"] }

195
sqlx-data.json Normal file
View File

@ -0,0 +1,195 @@
{
"db": "SQLite",
"22e18063d81e86afceca0e0c74c9070a8b21a406cba7cf7c01a966a869a9dad8": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "user_id",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "display_name",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "password",
"ordinal": 3,
"type_info": "Text"
}
],
"nullable": [
false,
false,
false,
false
],
"parameters": {
"Right": 1
}
},
"query": "select id, user_id, display_name, password from users where user_id = ?"
},
"58d27b1d424297504f1da2e3b9b4020121251c1155fbf5dc870dafbef97659f3": {
"describe": {
"columns": [
{
"name": "user_id",
"ordinal": 0,
"type_info": "Text"
}
],
"nullable": [
false
],
"parameters": {
"Right": 1
}
},
"query": "select user_id from users where user_id = ?"
},
"87395ffa7fe0382080056bdf67805044fbe89770ef366b4553d9797059034e44": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "user_id",
"ordinal": 1,
"type_info": "Int64"
},
{
"name": "device_id",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "display_name",
"ordinal": 3,
"type_info": "Text"
}
],
"nullable": [
false,
false,
false,
false
],
"parameters": {
"Right": 3
}
},
"query": "insert into devices(user_id, device_id, display_name) values(?, ?, ?) returning id, user_id, device_id, display_name"
},
"9a092e024bfe2854631e0572880f761125a2261a973b46d721db2e1401ce9aec": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "user_id",
"ordinal": 1,
"type_info": "Int64"
},
{
"name": "device_id",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "display_name",
"ordinal": 3,
"type_info": "Text"
}
],
"nullable": [
false,
false,
false,
false
],
"parameters": {
"Right": 1
}
},
"query": "select id, user_id, device_id, display_name from devices where user_id = ?"
},
"bb4e2386cf2987aa86f2c4dcac1159687b7220c770542bf52485e7e16f9ce987": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "user_id",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "display_name",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "password",
"ordinal": 3,
"type_info": "Text"
}
],
"nullable": [
false,
false,
false,
false
],
"parameters": {
"Right": 3
}
},
"query": "insert into users(user_id, display_name, password) values (?, ?, ?) returning id, user_id, display_name, password"
},
"cd7c9d3ae02f9553d4b7c4e8d98f63c6f556ac230a339683fe25025592812033": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "device_id",
"ordinal": 1,
"type_info": "Int64"
},
{
"name": "value",
"ordinal": 2,
"type_info": "Text"
}
],
"nullable": [
false,
false,
false
],
"parameters": {
"Right": 2
}
},
"query": "insert into sessions(device_id, value) values(?, ?) returning id, device_id, value"
}
}

View File

@ -33,8 +33,8 @@ pub fn routes() -> axum::Router {
} }
#[tracing::instrument] #[tracing::instrument]
async fn get_login() -> Json<Flows> { async fn get_login() -> Result<Json<Flows>, ApiError> {
Json(Flows::new()) Ok(Json(Flows::new()))
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
@ -81,18 +81,12 @@ async fn post_register(
.then(|| ()) .then(|| ())
.ok_or(RegistrationError::UserIdTaken)?; .ok_or(RegistrationError::UserIdTaken)?;
let salt = SaltString::generate(OsRng);
let argon2 = Argon2::default();
let pw_hash = argon2
.hash_password(auth_data.password().as_bytes(), &salt)?
.to_string();
let display_name = match body.initial_device_display_name() { let display_name = match body.initial_device_display_name() {
Some(display_name) => display_name.as_ref(), Some(display_name) => display_name.as_ref(),
None => "Random displayname", None => "Random displayname",
}; };
let user = User::create(&db, &user_id, &user_id.to_string(), &pw_hash).await?; let user = User::create(&db, &user_id, &user_id.to_string(), auth_data.password()).await?;
let device = Device::create(&db, &user, "test", display_name).await?; let device = Device::create(&db, &user, "test", display_name).await?;
(user, device) (user, device)

View File

@ -45,7 +45,7 @@ pub enum ApiError {
DBError(#[from] sqlx::Error), DBError(#[from] sqlx::Error),
#[error("Generic Error")] #[error("Generic Error")]
Generic(anyhow::Error), Generic(anyhow::Error)
} }
impl From<anyhow::Error> for ApiError { impl From<anyhow::Error> for ApiError {

View File

@ -1,3 +1,5 @@
use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
use rand_core::OsRng;
use sqlx::SqlitePool; use sqlx::SqlitePool;
use crate::types::user_id::UserId; use crate::types::user_id::UserId;
@ -25,7 +27,13 @@ impl User {
display_name: &str, display_name: &str,
password: &str, password: &str,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(Self, "insert into users(user_id, display_name, password) values (?, ?, ?) returning id, user_id, display_name, password", user_id, display_name, password).fetch_one(conn).await?) let salt = SaltString::generate(OsRng);
let argon2 = Argon2::default();
let pw_hash = argon2
.hash_password(password.as_bytes(), &salt)?
.to_string();
Ok(sqlx::query_as!(Self, "insert into users(user_id, display_name, password) values (?, ?, ?) returning id, user_id, display_name, password", user_id, display_name, pw_hash).fetch_one(conn).await?)
} }
pub async fn by_user_id(conn: &SqlitePool, user_id: &UserId) -> anyhow::Result<Self> { pub async fn by_user_id(conn: &SqlitePool, user_id: &UserId) -> anyhow::Result<Self> {