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:
@ -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())
|
||||
|
@ -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(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,5 +35,3 @@ impl Handler<CreateInvitation> for DbExecutor {
|
||||
Ok(inserted_invitation)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -14,7 +14,4 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
allow_tables_to_appear_in_same_query!(
|
||||
invitations,
|
||||
users,
|
||||
);
|
||||
allow_tables_to_appear_in_same_query!(invitations, users,);
|
||||
|
Reference in New Issue
Block a user