cleaning up

This commit is contained in:
Hamcha 2023-06-30 17:39:31 +02:00
parent 1d6270c551
commit 50e85f7de9
Signed by: hamcha
GPG Key ID: 1669C533B8CF6D89
4 changed files with 64 additions and 18 deletions

View File

@ -23,7 +23,7 @@ pub struct User {
pub email: Option<String>,
/// Hashed password
pub password: Option<Vec<u8>>,
pub password: Option<String>,
/// User's chosen displayed name
pub display_name: Option<String>,
@ -43,6 +43,55 @@ pub struct User {
pub deleted_at: Option<DateTime<Utc>>,
}
impl Default for User {
fn default() -> Self {
Self {
id: Uuid::nil(),
name: Default::default(),
email: Default::default(),
password: Default::default(),
display_name: Default::default(),
bio: Default::default(),
roles: Default::default(),
created_at: Default::default(),
modified_at: Default::default(),
deleted_at: Default::default(),
}
}
}
impl User {
pub async fn create(
pool: &Pool<Postgres>,
username: &str,
password: &str,
roles: &Vec<Uuid>,
) -> Result<Self> {
let result = sqlx::query!(
r#"INSERT INTO users ( name, password, roles ) VALUES ( $1,$2,$3 ) RETURNING id, created_at"#,
username,
hash(&password)?,
roles,
)
.fetch_one(pool)
.await?;
Ok(Self {
id: result.id,
name: username.to_owned(),
roles: roles.to_owned(),
created_at: result.created_at.and_utc(),
..Default::default()
})
}
pub async fn find(pool: &Pool<Postgres>, name: &str) -> Result<Option<Self>> {
Ok(sqlx::query_as("SELECT * FROM users WHERE name = $1")
.bind(name)
.fetch_optional(pool)
.await?)
}
}
#[derive(Deserialize, Serialize, FromRow)]
pub struct Role {
/// Role ID
@ -137,7 +186,7 @@ pub fn random() -> String {
SaltString::generate(&mut OsRng).to_string()
}
pub fn hash(plaintext: &String) -> Result<String> {
pub fn hash(plaintext: &str) -> Result<String> {
let salt = SaltString::generate(&mut OsRng);
let hashed = Argon2::default()
.hash_password(plaintext.as_bytes(), &salt)
@ -146,7 +195,7 @@ pub fn hash(plaintext: &String) -> Result<String> {
Ok(hashed)
}
pub fn verify(plaintext: &String, hash: &String) -> Result<bool> {
pub fn verify(plaintext: &str, hash: &str) -> Result<bool> {
let parsed_hash = PasswordHash::new(hash).map_err(|err| anyhow!(err))?;
Ok(Argon2::default()
.verify_password(plaintext.as_bytes(), &parsed_hash)

View File

@ -4,7 +4,7 @@ use axum::Json;
use serde_json::{json, Value};
use std::sync::Arc;
use crate::auth::{hash, random};
use crate::auth::{random, User};
use crate::error::AppError;
use crate::roles::ROLE_SUPERADMIN;
use crate::state::AppState;
@ -29,15 +29,13 @@ pub async fn bootstrap(State(state): State<Arc<AppState>>) -> Result<Json<Value>
let username = "admin";
let password = random();
sqlx::query!(
r#"INSERT INTO users ( name, display_name, password, roles ) VALUES ( $1, $2, $3, $4 ) RETURNING id"#,
username,
"Administrator",
hash(&password)?,
&[ROLE_SUPERADMIN],
)
.fetch_one(&state.database)
.await?;
User::create(
&state.database,
&username,
&password,
&[ROLE_SUPERADMIN].to_vec(),
)
.await?;
Ok(Json(json!({"username": username, "password": password})))
}

View File

@ -5,7 +5,7 @@ use serde_json::{json, Value};
use std::sync::Arc;
use crate::{
auth::{verify, Session},
auth::{verify, Session, User},
error::AppError,
state::AppState,
};
@ -20,9 +20,7 @@ pub async fn login(
State(state): State<Arc<AppState>>,
Json(payload): Json<LoginRequest>,
) -> Result<Json<Value>, AppError> {
let user = sqlx::query!("SELECT * FROM users WHERE name = $1", payload.username)
.fetch_optional(&state.database)
.await?;
let user = User::find(&state.database, payload.username.as_str()).await?;
let invalid = || -> AppError {
AppError::ClientError {

View File

@ -1,7 +1,8 @@
use crate::{content::Page, error::AppError, state::AppState};
use axum::extract::{Path, State};
use std::sync::Arc;
use crate::{content::Page, error::AppError, state::AppState};
pub async fn page(
State(state): State<Arc<AppState>>,
Path((site, slug)): Path<(String, String)>,