Start register logic
This commit is contained in:
parent
0e2cc62c30
commit
b157d718c7
@ -35,3 +35,13 @@
|
||||
display: block;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
#register .error > p {
|
||||
line-height: 1.4285;
|
||||
color: var(--danger);
|
||||
font-family: var(--font-medium);
|
||||
text-align: center;
|
||||
font-size: 14.5px;
|
||||
border-top: 1px solid var(--danger);
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
@ -142,6 +142,9 @@ pub enum Msg {
|
||||
SignInRequest,
|
||||
BindClientRequest,
|
||||
|
||||
// sign up
|
||||
SignUpRequest,
|
||||
|
||||
StyledSelectChanged(FieldId, StyledSelectChange),
|
||||
|
||||
ChangePage(model::Page),
|
||||
|
@ -236,6 +236,7 @@ pub struct SignUpPage {
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
pub sign_up_success: bool,
|
||||
pub error: String,
|
||||
// touched
|
||||
pub username_touched: bool,
|
||||
pub email_touched: bool,
|
||||
|
@ -27,6 +27,7 @@ impl StyledLinkBuilder {
|
||||
self.children.push(child);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_class<S>(mut self, name: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
@ -43,13 +44,12 @@ impl StyledLinkBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn text<S>(mut self, s: S) -> Self
|
||||
pub fn text<S>(self, s: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
let text: String = s.into();
|
||||
self.children.push(span![text]);
|
||||
self
|
||||
self.add_child(span![text])
|
||||
}
|
||||
|
||||
pub fn build(self) -> StyledLink {
|
||||
|
@ -121,6 +121,7 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
let register_link = StyledLink::build()
|
||||
.text("Register")
|
||||
.href("/register")
|
||||
.add_class("signUpLink")
|
||||
.build()
|
||||
.into_node();
|
||||
let submit_field = StyledField::build()
|
||||
|
@ -2,6 +2,7 @@ use seed::{prelude::*, *};
|
||||
|
||||
use jirs_data::{SignUpFieldId, WsMsg};
|
||||
|
||||
use crate::api::send_ws_msg;
|
||||
use crate::model::{Page, PageContent, SignUpPage};
|
||||
use crate::shared::styled_button::StyledButton;
|
||||
use crate::shared::styled_field::StyledField;
|
||||
@ -37,9 +38,18 @@ pub fn update(msg: Msg, model: &mut model::Model, _orders: &mut impl Orders<Msg>
|
||||
page.email = value;
|
||||
page.email_touched = true;
|
||||
}
|
||||
Msg::SignUpRequest => {
|
||||
send_ws_msg(WsMsg::SignUpRequest(
|
||||
page.email.clone(),
|
||||
page.username.clone(),
|
||||
));
|
||||
}
|
||||
Msg::WsMsg(WsMsg::SignUpSuccess) => {
|
||||
page.sign_up_success = true;
|
||||
}
|
||||
Msg::WsMsg(WsMsg::SignUpPairTaken) => {
|
||||
page.error = "Pair you give is either taken or is not matching".to_string();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -80,7 +90,7 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
StyledButton::build()
|
||||
.primary()
|
||||
.text("Register")
|
||||
.on_click(mouse_ev(Ev::Click, |_| Msg::SignInRequest))
|
||||
.on_click(mouse_ev(Ev::Click, |_| Msg::SignUpRequest))
|
||||
}
|
||||
.build()
|
||||
.into_node();
|
||||
@ -88,6 +98,7 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
let sign_in_link = StyledLink::build()
|
||||
.text("Sign In")
|
||||
.href("/login")
|
||||
.add_class("signInLink")
|
||||
.build()
|
||||
.into_node();
|
||||
|
||||
@ -109,17 +120,24 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
span!["Why I don't see password?"]
|
||||
];
|
||||
|
||||
let error_row = if page.error.is_empty() {
|
||||
empty![]
|
||||
} else {
|
||||
div![class!["error"], p![page.error]]
|
||||
};
|
||||
|
||||
let sign_up_form = StyledForm::build()
|
||||
.heading("Sign In to your account")
|
||||
.on_submit(ev(Ev::Submit, |ev| {
|
||||
ev.stop_propagation();
|
||||
ev.prevent_default();
|
||||
Msg::SignInRequest
|
||||
Msg::SignUpRequest
|
||||
}))
|
||||
.add_field(username_field)
|
||||
.add_field(email_field)
|
||||
.add_field(submit_field)
|
||||
.add_field(no_pass_section)
|
||||
.add_field(error_row)
|
||||
.build()
|
||||
.into_node();
|
||||
let children = vec![sign_up_form];
|
||||
|
@ -530,7 +530,11 @@ pub enum WsMsg {
|
||||
BindTokenCheck(Uuid),
|
||||
BindTokenBad,
|
||||
BindTokenOk(Uuid),
|
||||
|
||||
// Sign up
|
||||
SignUpRequest(EmailString, UsernameString),
|
||||
SignUpSuccess,
|
||||
SignUpPairTaken,
|
||||
|
||||
// project page
|
||||
ProjectRequest,
|
||||
|
@ -99,3 +99,49 @@ impl Handler<LoadIssueAssignees> for DbExecutor {
|
||||
Ok(vec)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Register {
|
||||
pub name: String,
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
impl Message for Register {
|
||||
type Result = Result<(), ServiceErrors>;
|
||||
}
|
||||
|
||||
impl Handler<Register> for DbExecutor {
|
||||
type Result = Result<(), ServiceErrors>;
|
||||
|
||||
fn handle(&mut self, msg: Register, _ctx: &mut Self::Context) -> Self::Result {
|
||||
use crate::schema::users::dsl::*;
|
||||
|
||||
let conn = &self
|
||||
.pool
|
||||
.get()
|
||||
.map_err(|_| ServiceErrors::DatabaseConnectionLost)?;
|
||||
|
||||
let query = users
|
||||
.filter(
|
||||
email
|
||||
.eq(msg.email.as_str())
|
||||
.and(name.ne(msg.name.as_str()))
|
||||
.or(email.ne(msg.email.as_str()).and(name.eq(msg.name.as_str())))
|
||||
.or(email.eq(msg.email.as_str()).and(name.eq(msg.name.as_str()))),
|
||||
)
|
||||
.count();
|
||||
|
||||
info!(
|
||||
"{}",
|
||||
diesel::debug_query::<diesel::pg::Pg, _>(&query).to_string()
|
||||
);
|
||||
|
||||
let matching: i64 = query.get_result(conn).unwrap_or(1);
|
||||
|
||||
if matching > 0 {
|
||||
return Err(ServiceErrors::RegisterCollision);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ pub enum ServiceErrors {
|
||||
DatabaseConnectionLost,
|
||||
DatabaseQueryFailed(String),
|
||||
RecordNotFound(String),
|
||||
RegisterCollision,
|
||||
}
|
||||
|
||||
impl ServiceErrors {
|
||||
@ -40,6 +41,9 @@ impl Into<HttpResponse> for ServiceErrors {
|
||||
errors: vec![format!("Resource not found {}", resource_name)],
|
||||
})
|
||||
}
|
||||
ServiceErrors::RegisterCollision => HttpResponse::Unauthorized().json(ErrorResponse {
|
||||
errors: vec!["Register collision".to_string()],
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,11 @@ impl WebSocketActor {
|
||||
block_on(auth::authenticate(&self.db, &self.mail, name, email))?
|
||||
}
|
||||
|
||||
// register
|
||||
WsMsg::SignUpRequest(email, username) => {
|
||||
block_on(users::register(&self.db, &self.mail, username, email))?
|
||||
}
|
||||
|
||||
// users
|
||||
WsMsg::ProjectUsersRequest => {
|
||||
block_on(users::load_project_users(&self.db, &self.current_user))?
|
||||
|
@ -3,8 +3,9 @@ use actix_web::web::Data;
|
||||
|
||||
use jirs_data::WsMsg;
|
||||
|
||||
use crate::db::users::LoadProjectUsers;
|
||||
use crate::db::users::{LoadProjectUsers, Register};
|
||||
use crate::db::DbExecutor;
|
||||
use crate::mail::MailExecutor;
|
||||
use crate::ws::{current_user, WsResult};
|
||||
|
||||
pub async fn load_project_users(
|
||||
@ -20,3 +21,17 @@ pub async fn load_project_users(
|
||||
};
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
pub async fn register(
|
||||
db: &Data<Addr<DbExecutor>>,
|
||||
_mail: &Data<Addr<MailExecutor>>,
|
||||
name: String,
|
||||
email: String,
|
||||
) -> WsResult {
|
||||
let msg = match db.send(Register { name, email }).await {
|
||||
Ok(Ok(_)) => Some(WsMsg::SignUpSuccess),
|
||||
Ok(Err(_)) => Some(WsMsg::SignUpPairTaken),
|
||||
_ => None,
|
||||
};
|
||||
Ok(msg)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user