Fix login

This commit is contained in:
eraden 2022-07-18 08:23:20 +02:00
parent f9d71754e7
commit 883aa37e7c
6 changed files with 143 additions and 62 deletions

View File

@ -8,17 +8,17 @@ customElements.define('login-form', class extends Component {
* { font-family: 'Noto Sans', sans-serif; }
${ FORM_STYLE }
</style>
<form>
<form action="/login" method="post">
<div>
<label>Login</label>
<input name="login" placeholder="Login" type="text" required />
<input name="email" placeholder="E-Mail" type="email" required />
</div>
<div>
<label>Hasło</label>
<input name="pass" placeholder="Hasło" type="password" required />
<input name="password" placeholder="Hasło" type="password" required />
</div>
<div>
<input type="button" value="Zaloguj" />
<input type="submit" value="Zaloguj" />
</div>
</form>
`);

View File

@ -49,6 +49,11 @@ customElements.define('account-view', class extends Component {
<label>Powiązane konto Facebook</label>
<input id="facebook_id" name="facebook_id" readonly />
</div>
<div>
<form action="/logout" method="post">
<input value="Wyloguj" type="submit" />
</form>
</div>
`);
this.addEventListener('facebook:available', ev => {
ev.preventDefault();

View File

@ -60,7 +60,7 @@ customElements.define('register-user-form', class extends Component {
</svg>
<form id="form" method="post" action="/register">
<input type="hidden" id="account_type" name="account_type">
<input type="hidden" id="account_type" name="account_type" value="User">
<input type="hidden" id="facebook_id" name="facebook_id">
<div>
<label>E-Mail</label>

View File

@ -200,3 +200,12 @@ pub struct UpdateContactInput {
pub contact_type: String,
pub content: String,
}
#[derive(Debug)]
pub struct CreateAccountInput {
pub login: String,
pub email: String,
pub pass: String,
pub facebook_id: Option<String>,
pub account_type: AccountType,
}

View File

@ -3,7 +3,7 @@ use std::cmp::Ordering;
use tracing::error;
use crate::model::db;
use crate::model::db::NewsArticle;
use crate::model::db::{LocalBusiness, NewsArticle};
#[derive(Debug)]
pub enum Error {
@ -12,6 +12,11 @@ pub enum Error {
item_id: i32,
idx: i32,
},
CreateLocalBusiness {
name: String,
description: String,
owner_id: i32,
},
UpdateBusiness {
input: db::UpdateLocalBusinessInput,
},
@ -40,6 +45,12 @@ pub enum Error {
AccountByEmail {
email: String,
},
CreateAccount {
input: db::CreateAccountInput,
},
AccountTaken {
input: db::CreateAccountInput,
},
Item {
item_id: i32,
},
@ -904,3 +915,67 @@ RETURNING
Error::DeleteContact { id }
})
}
#[tracing::instrument]
pub async fn create_local_business(
t: &mut T<'_>,
name: String,
owner_id: i32,
description: String,
) -> Result<LocalBusiness> {
sqlx::query_as(
r#"
INSERT INTO local_businesses (name, owner_id, description)
VALUES ($1, $2, $3)
RETURNING id, owner_id, name, description, state
"#,
)
.bind(&name)
.bind(owner_id)
.bind(&description)
.fetch_one(t)
.await
.map_err(|e| {
error!("{e}");
dbg!(e);
Error::CreateLocalBusiness {
name,
description,
owner_id,
}
})
}
#[tracing::instrument]
pub async fn create_account(t: &mut T<'_>, input: db::CreateAccountInput) -> Result<db::Account> {
sqlx::query_as(
r#"
INSERT INTO accounts (login, email, pass, facebook_id, account_type)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, login, email, pass, facebook_id, account_type
"#,
)
.bind(&input.login)
.bind(&input.email)
.bind(&input.pass)
.bind(&input.facebook_id)
.bind(input.account_type)
.fetch_one(t)
.await
.map_err(|e| {
error!("{e}");
dbg!(&e);
match e {
sqlx::Error::Database(e) => {
if e.message()
== "duplicate key value violates unique constraint \"accounts_email_key\""
{
Error::AccountTaken { input }
} else {
Error::CreateAccount { input }
}
}
_ => Error::CreateAccount { input },
}
})
}

View File

@ -14,6 +14,32 @@ use crate::routes::{Identity, JsonResult, Result};
use crate::view::Helper;
use crate::{not_xss, queries, routes, utils};
#[derive(Default, Template)]
#[template(path = "account.html")]
struct AccountTemplate {
account: Option<db::Account>,
error: Option<String>,
page: Page,
h: Helper,
}
impl AccountTemplate {
pub fn error<Error: Into<String>>(error: Error, page: Page) -> Self {
AccountTemplate {
error: Some(error.into()),
page,
..Default::default()
}
}
pub fn bad_request<Error: Into<String>>(
error: Error,
page: Page,
) -> routes::Result<HttpResponse> {
Ok(HttpResponse::BadRequest().body(AccountTemplate::error(error, page).render().unwrap()))
}
}
#[post("/register")]
#[tracing::instrument]
async fn register(
@ -35,53 +61,39 @@ async fn register(
let pass = match utils::encrypt(&form.password) {
Ok(pass) => pass,
Err(e) => {
tracing::error!("{:?}", e);
error!("{:?}", e);
dbg!(e);
t.rollback().await.unwrap();
return Ok(HttpResponse::BadRequest().body(
AccountTemplate {
error: Some("Zapisanie hasła nie powiodło się".into()),
page: Page::Register,
..Default::default()
}
.render()
.unwrap(),
));
return AccountTemplate::bad_request(
"Zapisanie hasła nie powiodło się",
Page::Register,
);
}
};
let res: sqlx::Result<db::Account> = sqlx::query_as(
r#"
INSERT INTO accounts (login, email, pass, facebook_id, account_type)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, login, email, pass, facebook_id, account_type
"#,
let res = queries::create_account(
&mut t,
db::CreateAccountInput {
login: form.login,
email: form.email,
pass,
facebook_id: form.facebook_id,
account_type: form.account_type,
},
)
.bind(form.login)
.bind(form.email)
.bind(pass)
.bind(form.facebook_id)
.bind(form.account_type)
.fetch_one(&mut t)
.await;
let account = match res {
Ok(res) => {
id.remember(format!("{}", res.id));
res
}
Err(queries::Error::AccountTaken { .. }) => {
return AccountTemplate::bad_request("Adres e-mail jest zajęty", Page::Register);
}
Err(e) => {
tracing::error!("{e}");
dbg!(e);
t.rollback().await.unwrap();
return Ok(HttpResponse::BadRequest().body(
AccountTemplate {
error: Some("Problem z utworzeniem konta".into()),
page: Page::Register,
..Default::default()
}
.render()
.unwrap(),
));
return AccountTemplate::bad_request("Problem z utworzeniem konta", Page::Register);
}
};
@ -93,22 +105,11 @@ RETURNING id, login, email, pass, facebook_id, account_type
not_xss!(name, t);
not_xss!(description, t);
let res: sqlx::Result<db::LocalBusiness> = sqlx::query_as(
r#"
INSERT INTO local_businesses (name, owner_id, description)
VALUES ($1, $2, $3)
RETURNING id, owner_id, name, description, state
"#,
)
.bind(name)
.bind(owner_id)
.bind(description)
.fetch_one(&mut t)
.await;
let res =
queries::create_local_business(&mut t, name.into(), owner_id, description.into()).await;
let business = match res {
Ok(business) => business,
Err(e) => {
tracing::error!("{e}");
dbg!(e);
t.rollback().await.unwrap();
return Ok(HttpResponse::BadRequest().body(
@ -249,7 +250,7 @@ async fn login(form: web::Form<LoginForm>, db: Data<PgPool>, id: Identity) -> Re
let record: db::Account = match queries::account_by_email(&mut t, form.email).await {
Ok(record) => record,
Err(e) => {
tracing::error!("{e:?}");
error!("{e:?}");
dbg!(e);
t.rollback().await.ok();
return Ok(HttpResponse::Ok().body(
@ -264,7 +265,7 @@ async fn login(form: web::Form<LoginForm>, db: Data<PgPool>, id: Identity) -> Re
}
};
if let Err(e) = utils::validate(&form.password, &record.pass) {
tracing::error!("{e}");
error!("{e}");
dbg!(e);
t.rollback().await.ok();
return Ok(HttpResponse::BadRequest().body(
@ -308,15 +309,6 @@ async fn upload(
routes::uploads::hande_upload(payload, id, "accounts").await
}
#[derive(Default, Template)]
#[template(path = "account.html")]
struct AccountTemplate {
account: Option<db::Account>,
error: Option<String>,
page: Page,
h: Helper,
}
#[get("/account")]
#[tracing::instrument]
async fn account_page(id: Identity, db: Data<PgPool>) -> Result<HttpResponse> {