implement auth/sign_in

This commit is contained in:
Peter Cai 2020-02-20 20:45:55 +08:00
parent 11b2a272b2
commit 77517147c8
No known key found for this signature in database
GPG Key ID: 71F5FB4E4F3FD54F
5 changed files with 57 additions and 4 deletions

1
Cargo.lock generated
View File

@ -891,6 +891,7 @@ dependencies = [
"jwt",
"rocket",
"rocket_contrib",
"rust-crypto",
"serde",
]

View File

@ -11,4 +11,5 @@ jwt = "0.4.0"
diesel = { version = "1.4.3", features = ["sqlite"] }
diesel_migrations = "1.4.0"
dotenv = "0.9.0"
serde = { version = "1.0.104", features = ["derive"] }
serde = { version = "1.0.104", features = ["derive"] }
rust-crypto = "0.2.36"

View File

@ -3,12 +3,13 @@ use crate::user;
use rocket::http::Status;
use rocket::response::status::Custom;
use rocket_contrib::json::Json;
use serde::Serialize;
use serde::{Serialize, Deserialize};
use std::vec::Vec;
pub fn routes() -> impl Into<Vec<rocket::Route>> {
routes![
auth,
auth_sign_in,
auth_params
]
}
@ -43,8 +44,31 @@ struct AuthResult {
#[post("/auth", format = "json", data = "<new_user>")]
fn auth(db: DbConn, new_user: Json<user::NewUser>) -> Custom<JsonResp<AuthResult>> {
match user::User::create(&db.0, &new_user) {
Ok(_) => success_resp(AuthResult {
token: "aaaa".to_string()
Ok(_) => _sign_in(db, &new_user.email, &new_user.password),
Err(user::UserOpError(e)) =>
error_resp(Status::InternalServerError, vec![e])
}
}
#[derive(Deserialize)]
struct SignInParams {
email: String,
password: String
}
#[post("/auth/sign_in", format = "json", data = "<params>")]
fn auth_sign_in(db: DbConn, params: Json<SignInParams>) -> Custom<JsonResp<AuthResult>> {
_sign_in(db, &params.email, &params.password)
}
// Shared logic for all interfaces that needs to do an automatic sign-in
fn _sign_in(db: DbConn, mail: &str, passwd: &str) -> Custom<JsonResp<AuthResult>> {
// Try to find the user first
let res = user::User::find_user_by_email(&db, mail)
.and_then(|u| u.create_token(passwd));
match res {
Ok(token) => success_resp(AuthResult {
token
}),
Err(user::UserOpError(e)) =>
error_resp(Status::InternalServerError, vec![e])

View File

@ -11,6 +11,7 @@ extern crate diesel_migrations;
extern crate dotenv;
#[macro_use]
extern crate serde;
extern crate crypto;
mod schema;
mod api;

View File

@ -3,6 +3,8 @@ use crate::schema::users::dsl::*;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;
use serde::Deserialize;
use std::env;
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug)]
pub struct UserOpError(pub String);
@ -56,4 +58,28 @@ impl User {
Result::Ok(results.remove(0)) // Take ownership, kill the stupid Vec
}
}
// Create a JWT token for the current user if password matches
pub fn create_token(&self, passwd: &str) -> Result<String, UserOpError> {
if passwd != self.password {
Err(UserOpError::new("Password mismatch"))
} else {
jwt::Token::new(
jwt::Header::default(),
jwt::Claims::new(jwt::Registered {
iss: None,
sub: Some(self.email.clone()),
exp: None,
aud: None,
nbf: Some(SystemTime::now().duration_since(UNIX_EPOCH)
.expect("wtf????").as_secs()),
iat: None,
jti: None
})
).signed(env::var("SFRS_JWT_SECRET")
.expect("Please have SFRS_JWT_SECRET set")
.as_bytes(), crypto::sha2::Sha256::new())
.map_err(|_| UserOpError::new("Failed to generate token"))
}
}
}