Made application monouser
This commit is contained in:
parent
1c1a9589b7
commit
d2a020b226
17 changed files with 165 additions and 856 deletions
|
|
@ -1,4 +1,3 @@
|
|||
pub mod routes;
|
||||
pub mod server;
|
||||
pub mod static_values;
|
||||
pub mod users;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
mod routes;
|
||||
mod server;
|
||||
mod static_values;
|
||||
mod users;
|
||||
|
||||
const DB_URL: &str = "sqlite://sqlite.db";
|
||||
|
||||
|
|
@ -9,7 +8,7 @@ const DB_URL: &str = "sqlite://sqlite.db";
|
|||
async fn main() {
|
||||
let server = server::start_server("127.0.0.1:3000", DB_URL);
|
||||
|
||||
/*let wv_task = tokio::task::spawn_blocking(|| {
|
||||
let wv_task = tokio::task::spawn_blocking(|| {
|
||||
web_view::builder()
|
||||
.title("Test")
|
||||
.content(web_view::Content::Url("http://localhost:3000"))
|
||||
|
|
@ -27,6 +26,5 @@ async fn main() {
|
|||
e = server => {
|
||||
println!("Axum finished with result {e:?}");
|
||||
}
|
||||
}*/
|
||||
server.await.unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,30 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::extract::{Json, Path, State};
|
||||
use hyper::StatusCode;
|
||||
use axum::{
|
||||
extract::{Json, Path, State},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use hyper::{header::CONTENT_TYPE, StatusCode};
|
||||
use serde::Deserialize;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use crate::users::UserToken;
|
||||
use accounters::models::account::Account;
|
||||
|
||||
pub async fn account_get(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Path(id): Path<i32>,
|
||||
) -> (StatusCode, String) {
|
||||
) -> impl IntoResponse {
|
||||
match Account::get_by_id(db.as_ref(), id).await {
|
||||
Ok(a) => {
|
||||
if a.get_user() == uid.user_id {
|
||||
(StatusCode::OK, serde_json::to_string(&a).unwrap())
|
||||
} else {
|
||||
(StatusCode::UNAUTHORIZED, String::new())
|
||||
}
|
||||
}
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e}")),
|
||||
Ok(a) => (
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "application/json")],
|
||||
serde_json::to_string(&a).unwrap(),
|
||||
),
|
||||
Err(e) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
[(CONTENT_TYPE, "plain/text")],
|
||||
format!("{e}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,37 +35,53 @@ pub struct AccountRequestCreate {
|
|||
|
||||
pub async fn account_create(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Json(account): Json<AccountRequestCreate>,
|
||||
) -> (StatusCode, String) {
|
||||
match Account::new(db.as_ref(), uid.user_id, &account.name).await {
|
||||
Ok(a) => (StatusCode::OK, serde_json::to_string(&a).unwrap()),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e}")),
|
||||
) -> impl IntoResponse {
|
||||
match Account::new(db.as_ref(), &account.name).await {
|
||||
Ok(a) => (
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "application/json")],
|
||||
serde_json::to_string(&a).unwrap(),
|
||||
),
|
||||
Err(e) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
format!("{e}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn account_list(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
) -> (StatusCode, String) {
|
||||
match Account::list(db.as_ref(), uid.user_id).await {
|
||||
Ok(a) => (StatusCode::OK, serde_json::to_string(&a).unwrap()),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e}")),
|
||||
pub async fn account_list(State(db): State<Arc<SqlitePool>>) -> impl IntoResponse {
|
||||
match Account::list(db.as_ref()).await {
|
||||
Ok(a) => (
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "application/json")],
|
||||
serde_json::to_string(&a).unwrap(),
|
||||
),
|
||||
Err(e) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
format!("{e}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn recategorize(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Path(account): Path<i32>,
|
||||
) -> (StatusCode, String) {
|
||||
) -> impl IntoResponse {
|
||||
let account = Account::get_by_id(db.as_ref(), account).await.unwrap();
|
||||
if account.get_user() != uid.user_id {
|
||||
return (StatusCode::UNAUTHORIZED, String::new());
|
||||
}
|
||||
|
||||
match account.recategorize_transactions(db.as_ref()).await {
|
||||
Ok(_) => (StatusCode::OK, String::new()),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e}")),
|
||||
Ok(_) => (
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
String::new(),
|
||||
),
|
||||
Err(e) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
format!("{e}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::{extract::State, Json};
|
||||
use hyper::StatusCode;
|
||||
use axum::{extract::State, response::IntoResponse, Json};
|
||||
use hyper::{header::CONTENT_TYPE, StatusCode};
|
||||
use serde::Deserialize;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use crate::users::UserToken;
|
||||
use accounters::models::categories::Category;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
|
@ -16,18 +15,25 @@ pub struct CategoryCreateRequest {
|
|||
|
||||
pub async fn create(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Json(new_category): Json<CategoryCreateRequest>,
|
||||
) -> (StatusCode, String) {
|
||||
) -> impl IntoResponse {
|
||||
match Category::new(db.as_ref(), &new_category.name, &new_category.description).await {
|
||||
Ok(_) => (StatusCode::OK, String::new()),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list(State(db): State<Arc<SqlitePool>>, uid: UserToken) -> (StatusCode, String) {
|
||||
pub async fn list(State(db): State<Arc<SqlitePool>>) -> impl IntoResponse {
|
||||
match Category::list(db.as_ref()).await {
|
||||
Ok(c) => (StatusCode::OK, serde_json::to_string(&c).unwrap()),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")),
|
||||
Ok(c) => (
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "application/json")],
|
||||
serde_json::to_string(&c).unwrap(),
|
||||
),
|
||||
Err(e) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
format!("{e:?}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::extract::{Json, State};
|
||||
use hyper::StatusCode;
|
||||
use axum::{
|
||||
extract::{Json, State},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use hyper::{header::CONTENT_TYPE, StatusCode};
|
||||
use serde::Deserialize;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use crate::users::UserToken;
|
||||
use accounters::models::rules::Rule;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
|
@ -16,18 +18,33 @@ pub struct RuleCreateRequest {
|
|||
|
||||
pub async fn create(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Json(rule): Json<RuleCreateRequest>,
|
||||
) -> (StatusCode, String) {
|
||||
match Rule::new(db.as_ref(), uid.user_id, rule.regex, rule.category).await {
|
||||
Ok(r) => (StatusCode::OK, serde_json::to_string(&r).unwrap()),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")),
|
||||
) -> impl IntoResponse {
|
||||
match Rule::new(db.as_ref(), rule.regex, rule.category).await {
|
||||
Ok(r) => (
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "application/json")],
|
||||
serde_json::to_string(&r).unwrap(),
|
||||
),
|
||||
Err(e) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
format!("{e:?}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list(State(db): State<Arc<SqlitePool>>, uid: UserToken) -> (StatusCode, String) {
|
||||
match Rule::list_by_user(db.as_ref(), uid.user_id).await {
|
||||
Ok(rule_list) => (StatusCode::OK, serde_json::to_string(&rule_list).unwrap()),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")),
|
||||
pub async fn list(State(db): State<Arc<SqlitePool>>) -> impl IntoResponse {
|
||||
match Rule::list(db.as_ref()).await {
|
||||
Ok(rule_list) => (
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "application/json")],
|
||||
serde_json::to_string(&rule_list).unwrap(),
|
||||
),
|
||||
Err(e) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
format!("{e:?}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ pub async fn list(
|
|||
Path(account): Path<i32>,
|
||||
Query(pagination): Query<PaginationOptions>,
|
||||
) -> (StatusCode, String) {
|
||||
match Transaction::list(
|
||||
match Transaction::list_by_account(
|
||||
db.as_ref(),
|
||||
account,
|
||||
pagination.limit.unwrap_or(100),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use serde::Serialize;
|
|||
use sqlx::SqlitePool;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
use crate::users::UserToken;
|
||||
use accounters::models::{account::Account, categories::Category, transaction::Transaction};
|
||||
|
||||
pub mod account;
|
||||
|
|
@ -23,7 +22,7 @@ struct AccountRender {
|
|||
|
||||
impl AccountRender {
|
||||
async fn from_account(pool: &SqlitePool, acc: Account) -> Self {
|
||||
let last_acc = Transaction::list(pool, acc.get_id(), 1, 0, false)
|
||||
let last_acc = Transaction::list_by_account(pool, acc.get_id(), 1, 0, false)
|
||||
.await
|
||||
.map_or(0.0, |x| {
|
||||
x.get(0)
|
||||
|
|
@ -54,11 +53,10 @@ fn hm_sort(hm: HashMap<i32, i64>, collapse: usize) -> Vec<(i32, i64)> {
|
|||
pub async fn index(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
State(tmpls): State<Arc<Tera>>,
|
||||
uid: UserToken,
|
||||
) -> impl IntoResponse {
|
||||
let mut ctx = Context::new();
|
||||
|
||||
let accounts = Account::list(db.as_ref(), uid.user_id).await.unwrap();
|
||||
let accounts = Account::list(db.as_ref()).await.unwrap();
|
||||
let mut acc_render = Vec::new();
|
||||
|
||||
for acc in accounts.into_iter() {
|
||||
|
|
@ -69,7 +67,7 @@ pub async fn index(
|
|||
|
||||
let last_month = Transaction::list_by_date(
|
||||
db.as_ref(),
|
||||
uid.user_id,
|
||||
None,
|
||||
Some(Utc::now() - chrono::Duration::days(30)),
|
||||
Some(Utc::now()),
|
||||
None,
|
||||
|
|
@ -119,9 +117,7 @@ pub async fn index(
|
|||
|
||||
ctx.insert("colors", &colors);
|
||||
|
||||
let transactions = Transaction::list_by_user(db.as_ref(), uid.user_id, 10, 0, false)
|
||||
.await
|
||||
.unwrap();
|
||||
let transactions = Transaction::list(db.as_ref(), 10, 0, false).await.unwrap();
|
||||
ctx.insert("transactions", &transactions);
|
||||
|
||||
match tmpls.render("index.html", &ctx) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ use serde::Deserialize;
|
|||
use sqlx::SqlitePool;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
use crate::users::UserToken;
|
||||
use accounters::models::{account::Account, categories::Category, transaction::Transaction};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
|
@ -31,7 +30,6 @@ fn parse_date(s: &str) -> Option<DateTime<Utc>> {
|
|||
pub async fn show(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
State(tmpls): State<Arc<Tera>>,
|
||||
uid: UserToken,
|
||||
Path(account_id): Path<i32>,
|
||||
Query(AccountViewParams { from, to }): Query<AccountViewParams>,
|
||||
) -> impl IntoResponse {
|
||||
|
|
@ -48,14 +46,6 @@ pub async fn show(
|
|||
}
|
||||
};
|
||||
|
||||
if account.get_user() != uid.user_id {
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
String::from("You cannot access this resource"),
|
||||
);
|
||||
}
|
||||
|
||||
let from = from
|
||||
.and_then(|x| parse_date(&x))
|
||||
.unwrap_or(Utc::now().duration_trunc(Duration::days(1)).unwrap() - Duration::days(30));
|
||||
|
|
@ -80,7 +70,8 @@ pub async fn show(
|
|||
.collect();
|
||||
ctx.insert("categories", &categories);
|
||||
|
||||
let txs = match Transaction::list(db.as_ref(), account.get_id(), 10, 0, false).await {
|
||||
let txs = match Transaction::list_by_account(db.as_ref(), account.get_id(), 10, 0, false).await
|
||||
{
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
return (
|
||||
|
|
@ -109,7 +100,6 @@ pub struct AccountTxListParams {
|
|||
pub async fn list_transactions(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
State(tmpls): State<Arc<Tera>>,
|
||||
uid: UserToken,
|
||||
Path(account_id): Path<i32>,
|
||||
Query(AccountTxListParams { entries, page }): Query<AccountTxListParams>,
|
||||
) -> impl IntoResponse {
|
||||
|
|
@ -126,14 +116,6 @@ pub async fn list_transactions(
|
|||
}
|
||||
};
|
||||
|
||||
if account.get_user() != uid.user_id {
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
String::from("You cannot access this resource"),
|
||||
);
|
||||
}
|
||||
|
||||
let categories: HashMap<i32, String> = Category::list(db.as_ref())
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
@ -145,7 +127,7 @@ pub async fn list_transactions(
|
|||
let n_entries = entries.unwrap_or(10).max(10);
|
||||
let page = page.unwrap_or(0).max(0);
|
||||
|
||||
let txs = match Transaction::list(
|
||||
let txs = match Transaction::list_by_account(
|
||||
db.as_ref(),
|
||||
account.get_id(),
|
||||
n_entries,
|
||||
|
|
@ -181,7 +163,6 @@ pub async fn list_transactions(
|
|||
pub async fn add_transactions_view(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
State(tmpls): State<Arc<Tera>>,
|
||||
uid: UserToken,
|
||||
Path(account_id): Path<i32>,
|
||||
) -> impl IntoResponse {
|
||||
let mut ctxt = Context::new();
|
||||
|
|
@ -198,14 +179,6 @@ pub async fn add_transactions_view(
|
|||
}
|
||||
};
|
||||
|
||||
if account.get_user() != uid.user_id {
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
[(CONTENT_TYPE, "text/plain")],
|
||||
String::from("You cannot access this resource"),
|
||||
);
|
||||
}
|
||||
|
||||
ctxt.insert("account", &account);
|
||||
|
||||
(
|
||||
|
|
@ -224,11 +197,9 @@ pub struct CreateTransactionRequest {
|
|||
|
||||
pub async fn add_transactions_action(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Path(account_id): Path<i32>,
|
||||
Json(body): Json<Vec<CreateTransactionRequest>>,
|
||||
) -> impl IntoResponse {
|
||||
// TODO missing user id check
|
||||
for tx in body.iter() {
|
||||
if let Err(e) = Transaction::new(
|
||||
db.as_ref(),
|
||||
|
|
|
|||
|
|
@ -13,14 +13,11 @@ use serde::Deserialize;
|
|||
use sqlx::SqlitePool;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
use crate::users::UserToken;
|
||||
|
||||
pub async fn view_classifiers(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
State(tmpls): State<Arc<Tera>>,
|
||||
uid: UserToken,
|
||||
) -> impl IntoResponse {
|
||||
let rules = match Rule::list_by_user(db.as_ref(), uid.user_id).await {
|
||||
let rules = match Rule::list(db.as_ref()).await {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
return (
|
||||
|
|
@ -57,7 +54,6 @@ pub async fn view_classifiers(
|
|||
pub async fn rules_new_view(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
State(tmpls): State<Arc<Tera>>,
|
||||
uid: UserToken,
|
||||
) -> impl IntoResponse {
|
||||
let categories = Category::list(db.as_ref()).await.unwrap();
|
||||
let mut ctx = Context::new();
|
||||
|
|
@ -78,10 +74,9 @@ pub struct NewRuleParams {
|
|||
|
||||
pub async fn rules_new_action(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Form(params): Form<NewRuleParams>,
|
||||
) -> impl IntoResponse {
|
||||
match Rule::new(db.as_ref(), uid.user_id, params.regex, params.category).await {
|
||||
match Rule::new(db.as_ref(), params.regex, params.category).await {
|
||||
Ok(_) => (
|
||||
StatusCode::MOVED_PERMANENTLY,
|
||||
[(LOCATION, "/classifiers")],
|
||||
|
|
@ -95,7 +90,7 @@ pub async fn rules_new_action(
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn category_new_view(State(tmpl): State<Arc<Tera>>, uid: UserToken) -> impl IntoResponse {
|
||||
pub async fn category_new_view(State(tmpl): State<Arc<Tera>>) -> impl IntoResponse {
|
||||
(
|
||||
StatusCode::OK,
|
||||
[(CONTENT_TYPE, "text/html;charset=utf-8")],
|
||||
|
|
@ -111,7 +106,6 @@ pub struct CategoryNewRuleParams {
|
|||
|
||||
pub async fn category_new_action(
|
||||
State(db): State<Arc<SqlitePool>>,
|
||||
uid: UserToken,
|
||||
Form(params): Form<CategoryNewRuleParams>,
|
||||
) -> impl IntoResponse {
|
||||
match Category::new(db.as_ref(), ¶ms.name, ¶ms.description).await {
|
||||
|
|
|
|||
|
|
@ -12,12 +12,9 @@ use serde::{Deserialize, Deserializer};
|
|||
use sqlx::SqlitePool;
|
||||
use tera::Tera;
|
||||
|
||||
use crate::users::UserToken;
|
||||
|
||||
pub async fn view(
|
||||
db: State<Arc<SqlitePool>>,
|
||||
tmpl: State<Arc<Tera>>,
|
||||
user: UserToken,
|
||||
Path(id): Path<i32>,
|
||||
) -> impl IntoResponse {
|
||||
let tx = Transaction::get_by_id(db.as_ref(), id).await.unwrap();
|
||||
|
|
@ -58,8 +55,6 @@ pub struct TxUpdateRequest {
|
|||
|
||||
pub async fn update(
|
||||
db: State<Arc<SqlitePool>>,
|
||||
tmpl: State<Arc<Tera>>,
|
||||
user: UserToken,
|
||||
Path(id): Path<i32>,
|
||||
Form(req): Form<TxUpdateRequest>,
|
||||
) -> impl IntoResponse {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::net::{AddrParseError, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::headers::ContentType;
|
||||
use hyper::{header, StatusCode};
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
use accounters::models::users::User;
|
||||
use axum::{
|
||||
async_trait,
|
||||
extract::{FromRef, FromRequestParts},
|
||||
headers::authorization::{Basic, Bearer},
|
||||
headers::Authorization,
|
||||
http::request::Parts,
|
||||
response::{IntoResponse, Redirect},
|
||||
RequestPartsExt, TypedHeader,
|
||||
};
|
||||
use hyper::StatusCode;
|
||||
|
||||
use crate::server::AppState;
|
||||
|
||||
pub struct AuthRedirect;
|
||||
|
||||
impl IntoResponse for AuthRedirect {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
Redirect::temporary("/login").into_response()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UserToken {
|
||||
pub user_id: i32,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S> FromRequestParts<S> for UserToken
|
||||
where
|
||||
AppState: FromRef<S>,
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = (StatusCode, [(&'static str, &'static str); 1]);
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
||||
match parts.extract::<TypedHeader<Authorization<Bearer>>>().await {
|
||||
Ok(auth) => Ok(UserToken {
|
||||
user_id: auth.0 .0.token().parse().unwrap(),
|
||||
}),
|
||||
Err(_) => match parts.extract::<TypedHeader<Authorization<Basic>>>().await {
|
||||
Ok(auth) => {
|
||||
let state = AppState::from_ref(state);
|
||||
let user = User::get_user(state.db.as_ref(), auth.username())
|
||||
.await
|
||||
.unwrap();
|
||||
if user.check_pass(auth.password()) {
|
||||
Ok(UserToken {
|
||||
user_id: user.get_id(),
|
||||
})
|
||||
} else {
|
||||
Err((StatusCode::UNAUTHORIZED, [("", "")]))
|
||||
}
|
||||
}
|
||||
Err(_) => Err((
|
||||
StatusCode::UNAUTHORIZED,
|
||||
[("WWW-Authenticate", "Basic realm=\"Access\"")],
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue