Register works, login almost

This commit is contained in:
Marko Korhonen 2020-04-09 11:52:31 +03:00
parent 12b865bf17
commit c85bb0ef72
No known key found for this signature in database
GPG key ID: 911B85FBC6003FE5
6 changed files with 79 additions and 41 deletions

View file

@ -1 +1,49 @@
pub fn login() {}
use crate::{
db_connection::DbPool,
errors::CustomError,
handlers::pool_handler,
models::user::{AuthUser, RegisterUser, User},
utils::jwt::*,
};
use actix_identity::Identity;
use actix_web::{post, web, HttpResponse, Responder};
#[post("/auth/register")]
pub async fn register(
new_user: web::Json<RegisterUser>,
pool: web::Data<DbPool>,
) -> impl Responder {
let connection = pool_handler(pool)?;
let register_user = new_user
.into_inner()
.validation()
.map_err(|e| HttpResponse::InternalServerError().json(e.to_string()))?;
User::create(register_user, &connection)
.map(|user| HttpResponse::Ok().json(user))
.map_err(|e| HttpResponse::InternalServerError().json(e.to_string()))
}
#[post("auth/login")]
pub async fn login(
id: Identity,
auth_user: web::Json<AuthUser>,
pool: web::Data<DbPool>,
) -> impl Responder {
let connection = pool_handler(pool)?;
let user = auth_user.login(&connection).map_err(|e| match e {
CustomError::DBError(diesel::result::Error::NotFound) => {
HttpResponse::NotFound().json(e.to_string())
}
_ => HttpResponse::InternalServerError().json(e.to_string()),
})?;
let token = new_token(user.id, &user.username, &user.admin).map_err(|e| match e {
_ => HttpResponse::InternalServerError().finish(),
})?;
id.remember(token);
Ok(HttpResponse::Ok().json(token))
}

View file

@ -1,5 +1,4 @@
pub mod authentication;
pub mod register;
use crate::db_connection::{DbPool, MyPooledConnection};
use actix_web::{web, HttpResponse};

View file

@ -1,19 +0,0 @@
use crate::db_connection::DbPool;
use crate::handlers::pool_handler;
use crate::models::user::{RegisterUser, User};
use actix_web::{web, HttpResponse};
pub fn register(
new_user: web::Json<RegisterUser>,
pool: web::Data<DbPool>,
) -> Result<HttpResponse, HttpResponse> {
let my_pool = pool_handler(pool)?;
let register_user = new_user
.into_inner()
.validation()
.map_err(|e| HttpResponse::InternalServerError().json(e.to_string()))?;
User::create(register_user, &my_pool)
.map(|user| HttpResponse::Ok().json(user))
.map_err(|e| HttpResponse::InternalServerError().json(e.to_string()))
}

View file

@ -1,26 +1,28 @@
#[macro_use]
extern crate diesel;
extern crate csrf;
extern crate dotenv;
#[macro_use]
extern crate dotenv_codegen;
pub mod db_connection;
pub mod errors;
pub mod handlers;
pub mod models;
pub mod schema;
pub mod utils;
use actix_cors::Cors;
use actix_identity::{CookieIdentityPolicy, IdentityService};
use actix_web::{http::header, middleware::Logger, web, App, HttpServer};
use actix_web::{http::header, middleware::Logger, App, HttpServer};
use chrono::Duration;
use db_connection::get_pool;
use dotenv::dotenv;
use handlers::authentication;
use std::env;
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix_web=debug,diesel=debug");
env_logger::init();
dotenv().ok();
let bind = "localhost:8080";
println!("Starting server at: http://{}", &bind);
@ -30,7 +32,7 @@ async fn main() -> std::io::Result<()> {
.wrap(Logger::default())
.wrap(
Cors::new()
.allowed_origin(dotenv!("ALLOWED_ORIGIN"))
.allowed_origin(env::var("ALLOWED_ORIGIN").expect("ALLOWED_ORIGIN").as_str())
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
.allowed_headers(vec![
header::AUTHORIZATION,
@ -41,15 +43,16 @@ async fn main() -> std::io::Result<()> {
.finish(),
)
.wrap(IdentityService::new(
CookieIdentityPolicy::new(dotenv!("SECRET").as_bytes())
.domain(dotenv!("DOMAIN"))
CookieIdentityPolicy::new(env::var("SECRET").expect("SECRET").as_bytes())
.domain(env::var("DOMAIN").expect("DOMAIN"))
.name("thesis")
.path("/")
.max_age(Duration::days(1).num_seconds())
.secure(dotenv!("COOKIE_SECURE").parse().unwrap()),
.secure(false),
))
.data(get_pool())
.service(web::resource("/register").route(web::post().to(handlers::register::register)))
.service(authentication::register)
.service(authentication::login)
})
.bind(&bind)?
.run()

View file

@ -1,5 +1,4 @@
use crate::errors::CustomError;
use crate::schema::users;
use crate::{errors::CustomError, schema::users};
use bcrypt::{hash, verify, DEFAULT_COST};
use chrono::{Local, NaiveDateTime};
use diesel::prelude::*;

View file

@ -1,17 +1,21 @@
extern crate bcrypt;
extern crate jsonwebtoken;
use actix_web::HttpResponse;
use chrono::{Duration, Local};
use jwt::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use jsonwebtoken::{decode, encode, Header, Validation};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
sub: i32,
name: String,
admin: bool,
exp: usize,
}
pub struct UserWithToken {
pub id: i32,
pub username: String,
pub admin: bool,
}
@ -19,27 +23,31 @@ pub struct UserWithToken {
impl From<Claims> for UserWithToken {
fn from(claims: Claims) -> Self {
UserWithToken {
username: claims.sub,
id: claims.sub,
username: claims.name,
admin: claims.admin,
}
}
}
impl Claims {
fn with_username(username: &str, admin: &bool) -> Self {
fn with_username(id: i32, username: &str, admin: bool) -> Self {
Claims {
sub: email.into(),
admin: admin.into(),
sub: id,
name: username.into(),
admin,
exp: (Local::now() + Duration::hours(24)).timestamp() as usize,
}
}
}
pub fn new_token(username: &str) -> Result<String, HttpResponse> {
let secret = dotenv!("JWT_SECRET").as_bytes();
fn get_secret() -> [u8] {
std::env::var("JWT_SECRET").expect("JWT_SECRET").as_bytes()
}
pub fn new_token(id: i32, username: &str, admin: &bool) -> Result<String, HttpResponse> {
let claims = Claims::with_username(username, admin);
encode(&Header::default(), &claims, secret)
encode(&Header::default(), &claims, get_secret())
.map_err(|e| HttpResponse::InternalServerError().json(e.to_string()))
}