forked from alemi/upub
feat: login tells you who you are
This commit is contained in:
parent
2dabd308cc
commit
3cf401467e
1 changed files with 19 additions and 12 deletions
|
@ -2,7 +2,7 @@ use axum::{http::StatusCode, extract::State, Json};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter};
|
use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter};
|
||||||
|
|
||||||
use crate::{model, server::Context};
|
use crate::{errors::UpubError, model, server::Context};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Deserialize)]
|
||||||
|
@ -11,7 +11,14 @@ pub struct LoginForm {
|
||||||
password: String,
|
password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login(State(ctx): State<Context>, Json(login): Json<LoginForm>) -> Result<Json<serde_json::Value>, StatusCode> {
|
#[derive(Debug, Clone, serde::Serialize)]
|
||||||
|
pub struct AuthSuccess {
|
||||||
|
token: String,
|
||||||
|
user: String,
|
||||||
|
expires: chrono::DateTime<chrono::Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn login(State(ctx): State<Context>, Json(login): Json<LoginForm>) -> crate::Result<Json<AuthSuccess>> {
|
||||||
// TODO salt the pwd
|
// TODO salt the pwd
|
||||||
match model::credential::Entity::find()
|
match model::credential::Entity::find()
|
||||||
.filter(Condition::all()
|
.filter(Condition::all()
|
||||||
|
@ -19,30 +26,30 @@ pub async fn login(State(ctx): State<Context>, Json(login): Json<LoginForm>) ->
|
||||||
.add(model::credential::Column::Password.eq(sha256::digest(login.password)))
|
.add(model::credential::Column::Password.eq(sha256::digest(login.password)))
|
||||||
)
|
)
|
||||||
.one(ctx.db())
|
.one(ctx.db())
|
||||||
.await
|
.await?
|
||||||
{
|
{
|
||||||
Ok(Some(x)) => {
|
Some(x) => {
|
||||||
// TODO should probably use crypto-safe rng
|
// TODO should probably use crypto-safe rng
|
||||||
let token : String = rand::thread_rng()
|
let token : String = rand::thread_rng()
|
||||||
.sample_iter(&rand::distributions::Alphanumeric)
|
.sample_iter(&rand::distributions::Alphanumeric)
|
||||||
.take(128)
|
.take(128)
|
||||||
.map(char::from)
|
.map(char::from)
|
||||||
.collect();
|
.collect();
|
||||||
|
let expires = chrono::Utc::now() + std::time::Duration::from_secs(3600 * 6);
|
||||||
model::session::Entity::insert(
|
model::session::Entity::insert(
|
||||||
model::session::ActiveModel {
|
model::session::ActiveModel {
|
||||||
id: sea_orm::ActiveValue::Set(token.clone()),
|
id: sea_orm::ActiveValue::Set(token.clone()),
|
||||||
actor: sea_orm::ActiveValue::Set(x.id),
|
actor: sea_orm::ActiveValue::Set(x.id.clone()),
|
||||||
expires: sea_orm::ActiveValue::Set(chrono::Utc::now() + std::time::Duration::from_secs(3600 * 6)),
|
expires: sea_orm::ActiveValue::Set(expires),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.exec(ctx.db())
|
.exec(ctx.db())
|
||||||
.await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
.await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
Ok(Json(serde_json::Value::String(token)))
|
Ok(Json(AuthSuccess {
|
||||||
|
token, expires,
|
||||||
|
user: x.id
|
||||||
|
}))
|
||||||
},
|
},
|
||||||
Ok(None) => Err(StatusCode::UNAUTHORIZED),
|
None => Err(UpubError::unauthorized()),
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("error querying db for user credentials: {e}");
|
|
||||||
Err(StatusCode::INTERNAL_SERVER_ERROR)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue