1
0
mirror of https://github.com/actix/examples synced 2025-06-28 18:00:37 +02:00

update more examples and rustfmt

This commit is contained in:
Nikolay Kim
2019-03-09 18:03:09 -08:00
parent f39a53ea3a
commit e2945b9b39
48 changed files with 485 additions and 801 deletions

View File

@ -14,8 +14,10 @@ pub struct AppState {
/// creates and returns the app after mounting all routes/resources
pub fn create_app(db: Addr<DbExecutor>) -> App<AppState> {
// secret is a random minimum 32 bytes long base 64 string
let secret: String = std::env::var("SECRET_KEY").unwrap_or_else(|_| "0123".repeat(8));
let domain: String = std::env::var("DOMAIN").unwrap_or_else(|_| "localhost".to_string());
let secret: String =
std::env::var("SECRET_KEY").unwrap_or_else(|_| "0123".repeat(8));
let domain: String =
std::env::var("DOMAIN").unwrap_or_else(|_| "localhost".to_string());
App::with_state(AppState { db })
.middleware(Logger::default())

View File

@ -1,9 +1,9 @@
use actix::{Handler, Message};
use actix_web::{middleware::identity::RequestIdentity, FromRequest, HttpRequest};
use bcrypt::verify;
use diesel::prelude::*;
use errors::ServiceError;
use models::{DbExecutor, User, SlimUser};
use bcrypt::verify;
use actix_web::{FromRequest, HttpRequest, middleware::identity::RequestIdentity};
use models::{DbExecutor, SlimUser, User};
use utils::decode_token;
#[derive(Debug, Deserialize)]
@ -19,22 +19,24 @@ impl Message for AuthData {
impl Handler<AuthData> for DbExecutor {
type Result = Result<SlimUser, ServiceError>;
fn handle(&mut self, msg: AuthData, _: &mut Self::Context) -> Self::Result {
use schema::users::dsl::{users, email};
use schema::users::dsl::{email, users};
let conn: &PgConnection = &self.0.get().unwrap();
let mut items = users
.filter(email.eq(&msg.email))
.load::<User>(conn)?;
let mut items = users.filter(email.eq(&msg.email)).load::<User>(conn)?;
if let Some(user) = items.pop() {
match verify(&msg.password, &user.password) {
Ok(matching) => if matching {
Ok(matching) => {
if matching {
return Ok(user.into());
},
}
}
Err(_) => (),
}
}
Err(ServiceError::BadRequest("Username and Password don't match".into()))
Err(ServiceError::BadRequest(
"Username and Password don't match".into(),
))
}
}

View File

@ -1,13 +1,16 @@
use actix_web::{AsyncResponder, FutureResponse, HttpResponse, HttpRequest, ResponseError, Json};
use actix_web::middleware::identity::RequestIdentity;
use actix_web::{
AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Json, ResponseError,
};
use futures::future::Future;
use utils::create_token;
use app::AppState;
use auth_handler::{AuthData, LoggedUser};
pub fn login((auth_data, req): (Json<AuthData>, HttpRequest<AppState>))
-> FutureResponse<HttpResponse> {
pub fn login(
(auth_data, req): (Json<AuthData>, HttpRequest<AppState>),
) -> FutureResponse<HttpResponse> {
req.state()
.db
.send(auth_data.into_inner())
@ -19,7 +22,8 @@ pub fn login((auth_data, req): (Json<AuthData>, HttpRequest<AppState>))
Ok(HttpResponse::Ok().into())
}
Err(err) => Ok(err.error_response()),
}).responder()
})
.responder()
}
pub fn logout(req: HttpRequest<AppState>) -> HttpResponse {

View File

@ -9,8 +9,8 @@ fn get_api_key() -> String {
pub fn send_invitation(invitation: &Invitation) {
let tm = Transmission::new_eu(get_api_key());
let sending_email =
std::env::var("SENDING_EMAIL_ADDRESS").expect("SENDING_EMAIL_ADDRESS must be set");
let sending_email = std::env::var("SENDING_EMAIL_ADDRESS")
.expect("SENDING_EMAIL_ADDRESS must be set");
// new email message with sender name and email
let mut email = Message::new(EmailAddress::new(sending_email, "Let's Organise"));
@ -39,7 +39,6 @@ pub fn send_invitation(invitation: &Invitation) {
.to_string()
);
// complete the email message with details
email
.add_recipient(recipient)
@ -51,16 +50,14 @@ pub fn send_invitation(invitation: &Invitation) {
// Note that we only print out the error response from email api
match result {
Ok(res) => {
match res {
TransmissionResponse::ApiResponse(api_res) => {
println!("API Response: \n {:#?}", api_res);
}
TransmissionResponse::ApiError(errors) => {
println!("Response Errors: \n {:#?}", &errors);
}
Ok(res) => match res {
TransmissionResponse::ApiResponse(api_res) => {
println!("API Response: \n {:#?}", api_res);
}
}
TransmissionResponse::ApiError(errors) => {
println!("Response Errors: \n {:#?}", &errors);
}
},
Err(error) => {
println!("error \n {:#?}", error);
}

View File

@ -1,9 +1,8 @@
use actix_web::{error::ResponseError, HttpResponse};
use std::convert::From;
use diesel::result::{DatabaseErrorKind, Error};
use std::convert::From;
use uuid::ParseError;
#[derive(Fail, Debug)]
pub enum ServiceError {
#[fail(display = "Internal Server Error")]
@ -20,9 +19,14 @@ pub enum ServiceError {
impl ResponseError for ServiceError {
fn error_response(&self) -> HttpResponse {
match *self {
ServiceError::InternalServerError => HttpResponse::InternalServerError().json("Internal Server Error, Please try later"),
ServiceError::BadRequest(ref message) => HttpResponse::BadRequest().json(message),
ServiceError::Unauthorized => HttpResponse::Unauthorized().json("Unauthorized")
ServiceError::InternalServerError => HttpResponse::InternalServerError()
.json("Internal Server Error, Please try later"),
ServiceError::BadRequest(ref message) => {
HttpResponse::BadRequest().json(message)
}
ServiceError::Unauthorized => {
HttpResponse::Unauthorized().json("Unauthorized")
}
}
}
}
@ -42,12 +46,13 @@ impl From<Error> for ServiceError {
match error {
Error::DatabaseError(kind, info) => {
if let DatabaseErrorKind::UniqueViolation = kind {
let message = info.details().unwrap_or_else(|| info.message()).to_string();
let message =
info.details().unwrap_or_else(|| info.message()).to_string();
return ServiceError::BadRequest(message);
}
ServiceError::InternalServerError
}
_ => ServiceError::InternalServerError
_ => ServiceError::InternalServerError,
}
}
}

View File

@ -35,5 +35,3 @@ impl Handler<CreateInvitation> for DbExecutor {
Ok(inserted_invitation)
}
}

View File

@ -1,4 +1,6 @@
use actix_web::{AsyncResponder, FutureResponse, HttpResponse, Json, ResponseError, State};
use actix_web::{
AsyncResponder, FutureResponse, HttpResponse, Json, ResponseError, State,
};
use futures::future::Future;
use app::AppState;
@ -18,5 +20,6 @@ pub fn register_email(
Ok(HttpResponse::Ok().into())
}
Err(err) => Ok(err.error_response()),
}).responder()
})
.responder()
}

View File

@ -1,18 +1,18 @@
// to avoid the warning from diesel macros
#![allow(proc_macro_derive_resolution_fallback)]
extern crate bcrypt;
extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate serde;
extern crate bcrypt;
extern crate chrono;
extern crate dotenv;
extern crate env_logger;
extern crate futures;
extern crate r2d2;
extern crate uuid;
extern crate jsonwebtoken as jwt;
extern crate r2d2;
extern crate serde;
extern crate sparkpost;
extern crate uuid;
#[macro_use]
extern crate diesel;
#[macro_use]
@ -21,26 +21,25 @@ extern crate serde_derive;
extern crate failure;
mod app;
mod models;
mod schema;
mod errors;
mod auth_handler;
mod auth_routes;
mod email_service;
mod errors;
mod invitation_handler;
mod invitation_routes;
mod models;
mod register_handler;
mod register_routes;
mod schema;
mod utils;
mod email_service;
use models::DbExecutor;
use actix::prelude::*;
use actix_web::server;
use diesel::{r2d2::ConnectionManager, PgConnection};
use dotenv::dotenv;
use models::DbExecutor;
use std::env;
fn main() {
dotenv().ok();
std::env::set_var("RUST_LOG", "simple-auth-server=debug,actix_web=info");
@ -55,7 +54,8 @@ fn main() {
.build(manager)
.expect("Failed to create pool.");
let address: Addr<DbExecutor> = SyncArbiter::start(4, move || DbExecutor(pool.clone()));
let address: Addr<DbExecutor> =
SyncArbiter::start(4, move || DbExecutor(pool.clone()));
server::new(move || app::create_app(address.clone()))
.bind("127.0.0.1:3000")

View File

@ -1,11 +1,11 @@
use actix::{Actor, SyncContext};
use chrono::{Local, NaiveDateTime};
use diesel::pg::PgConnection;
use diesel::r2d2::{ConnectionManager, Pool};
use chrono::{NaiveDateTime, Local};
use uuid::Uuid;
use std::convert::From;
use uuid::Uuid;
use schema::{users, invitations};
use schema::{invitations, users};
/// This is db executor actor. can be run in parallel
pub struct DbExecutor(pub Pool<ConnectionManager<PgConnection>>);
@ -51,8 +51,6 @@ pub struct SlimUser {
impl From<User> for SlimUser {
fn from(user: User) -> Self {
SlimUser {
email: user.email
}
SlimUser { email: user.email }
}
}

View File

@ -2,9 +2,9 @@ use actix::{Handler, Message};
use chrono::Local;
use diesel::prelude::*;
use errors::ServiceError;
use models::{DbExecutor, Invitation, User, SlimUser};
use uuid::Uuid;
use models::{DbExecutor, Invitation, SlimUser, User};
use utils::hash_password;
use uuid::Uuid;
// UserData is used to extract data from a post request by the client
#[derive(Debug, Deserialize)]
@ -23,11 +23,10 @@ impl Message for RegisterUser {
type Result = Result<SlimUser, ServiceError>;
}
impl Handler<RegisterUser> for DbExecutor {
type Result = Result<SlimUser, ServiceError>;
fn handle(&mut self, msg: RegisterUser, _: &mut Self::Context) -> Self::Result {
use schema::invitations::dsl::{invitations, id};
use schema::invitations::dsl::{id, invitations};
use schema::users::dsl::users;
let conn: &PgConnection = &self.0.get().unwrap();
@ -35,7 +34,8 @@ impl Handler<RegisterUser> for DbExecutor {
// return early with error that will be converted to ServiceError
let invitation_id = Uuid::parse_str(&msg.invitation_id)?;
invitations.filter(id.eq(invitation_id))
invitations
.filter(id.eq(invitation_id))
.load::<Invitation>(conn)
.map_err(|_db_error| ServiceError::BadRequest("Invalid Invitation".into()))
.and_then(|mut result| {
@ -45,9 +45,8 @@ impl Handler<RegisterUser> for DbExecutor {
// try hashing the password, else return the error that will be converted to ServiceError
let password: String = hash_password(&msg.password)?;
let user = User::with_details(invitation.email, password);
let inserted_user: User = diesel::insert_into(users)
.values(&user)
.get_result(conn)?;
let inserted_user: User =
diesel::insert_into(users).values(&user).get_result(conn)?;
return Ok(inserted_user.into());
}
@ -56,5 +55,3 @@ impl Handler<RegisterUser> for DbExecutor {
})
}
}

View File

@ -1,22 +1,27 @@
use actix_web::{AsyncResponder, FutureResponse, HttpResponse, ResponseError, State, Json, Path};
use actix_web::{
AsyncResponder, FutureResponse, HttpResponse, Json, Path, ResponseError, State,
};
use futures::future::Future;
use app::AppState;
use register_handler::{RegisterUser, UserData};
pub fn register_user((invitation_id, user_data, state): (Path<String>, Json<UserData>, State<AppState>))
-> FutureResponse<HttpResponse> {
pub fn register_user(
(invitation_id, user_data, state): (Path<String>, Json<UserData>, State<AppState>),
) -> FutureResponse<HttpResponse> {
let msg = RegisterUser {
// into_inner() returns the inner string value from Path
invitation_id: invitation_id.into_inner(),
password: user_data.password.clone(),
};
state.db.send(msg)
state
.db
.send(msg)
.from_err()
.and_then(|db_response| match db_response {
Ok(slim_user) => Ok(HttpResponse::Ok().json(slim_user)),
Err(service_error) => Ok(service_error.error_response()),
}).responder()
})
.responder()
}

View File

@ -14,7 +14,4 @@ table! {
}
}
allow_tables_to_appear_in_same_query!(
invitations,
users,
);
allow_tables_to_appear_in_same_query!(invitations, users,);