mirror of
https://github.com/actix/examples
synced 2024-11-27 16:02:57 +01:00
update deps
This commit is contained in:
parent
48b8e7c335
commit
e4f71e8fd5
@ -2,13 +2,15 @@
|
|||||||
name = "actix_redis"
|
name = "actix_redis"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["dowwie <dkcdkg@gmail.com>"]
|
authors = ["dowwie <dkcdkg@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
workspace = ".."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "0.7.3"
|
actix = "0.8.0-alpha.2"
|
||||||
actix-web = "0.7.3"
|
actix-web = "1.0.0-alpha.1"
|
||||||
actix-redis = "0.5.1"
|
actix-redis = { git="https://github.com/actix/actix-redis.git" }
|
||||||
futures = "0.1.23"
|
futures = "0.1.23"
|
||||||
redis-async = "0.4.0"
|
redis-async = "0.4.0"
|
||||||
serde = "1.0.71"
|
serde = "1.0.71"
|
||||||
serde_derive = "1.0.71"
|
serde_derive = "1.0.71"
|
||||||
env_logger = "0.5.12"
|
env_logger = "0.6"
|
||||||
|
@ -1,23 +1,13 @@
|
|||||||
extern crate actix;
|
|
||||||
extern crate actix_redis;
|
|
||||||
extern crate actix_web;
|
|
||||||
extern crate env_logger;
|
|
||||||
extern crate futures;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate redis_async;
|
extern crate redis_async;
|
||||||
extern crate serde;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
use actix_redis::{Command, Error as ARError, RedisActor};
|
use actix_redis::{Command, Error as ARError, RedisActor};
|
||||||
use actix_web::{
|
use actix_web::{middleware, web, App, Error as AWError, HttpResponse, HttpServer};
|
||||||
http::Method, middleware, server, App, AsyncResponder, Error as AWError,
|
|
||||||
HttpRequest, HttpResponse, Json,
|
|
||||||
};
|
|
||||||
use futures::future::{join_all, Future};
|
use futures::future::{join_all, Future};
|
||||||
use redis_async::resp::RespValue;
|
use redis_async::resp::RespValue;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CacheInfo {
|
pub struct CacheInfo {
|
||||||
@ -27,10 +17,10 @@ pub struct CacheInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cache_stuff(
|
fn cache_stuff(
|
||||||
(info, req): (Json<CacheInfo>, HttpRequest<AppState>),
|
info: web::Json<CacheInfo>,
|
||||||
|
redis: web::Data<Addr<RedisActor>>,
|
||||||
) -> impl Future<Item = HttpResponse, Error = AWError> {
|
) -> impl Future<Item = HttpResponse, Error = AWError> {
|
||||||
let info = info.into_inner();
|
let info = info.into_inner();
|
||||||
let redis = req.state().redis_addr.clone();
|
|
||||||
|
|
||||||
let one = redis.send(Command(resp_array!["SET", "mydomain:one", info.one]));
|
let one = redis.send(Command(resp_array!["SET", "mydomain:one", info.one]));
|
||||||
let two = redis.send(Command(resp_array!["SET", "mydomain:two", info.two]));
|
let two = redis.send(Command(resp_array!["SET", "mydomain:two", info.two]));
|
||||||
@ -58,14 +48,11 @@ fn cache_stuff(
|
|||||||
Ok(HttpResponse::Ok().body("successfully cached values"))
|
Ok(HttpResponse::Ok().body("successfully cached values"))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.responder()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn del_stuff(
|
fn del_stuff(
|
||||||
req: HttpRequest<AppState>,
|
redis: web::Data<Addr<RedisActor>>,
|
||||||
) -> impl Future<Item = HttpResponse, Error = AWError> {
|
) -> impl Future<Item = HttpResponse, Error = AWError> {
|
||||||
let redis = req.state().redis_addr.clone();
|
|
||||||
|
|
||||||
redis
|
redis
|
||||||
.send(Command(resp_array![
|
.send(Command(resp_array![
|
||||||
"DEL",
|
"DEL",
|
||||||
@ -83,33 +70,24 @@ fn del_stuff(
|
|||||||
Ok(HttpResponse::InternalServerError().finish())
|
Ok(HttpResponse::InternalServerError().finish())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.responder()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppState {
|
fn main() -> std::io::Result<()> {
|
||||||
pub redis_addr: Arc<Addr<RedisActor>>,
|
std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info");
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
::std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info");
|
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let sys = actix::System::new("actix_redis_ex");
|
|
||||||
|
|
||||||
server::new(|| {
|
HttpServer::new(|| {
|
||||||
let redis_addr = Arc::new(RedisActor::start("127.0.0.1:6379"));
|
let redis_addr = RedisActor::start("127.0.0.1:6379");
|
||||||
let app_state = AppState { redis_addr };
|
|
||||||
|
|
||||||
App::with_state(app_state)
|
App::new()
|
||||||
.middleware(middleware::Logger::default())
|
.data(redis_addr)
|
||||||
.resource("/stuff", |r| {
|
.wrap(middleware::Logger::default())
|
||||||
r.method(Method::POST).with_async(cache_stuff);
|
.service(
|
||||||
r.method(Method::DELETE).with_async(del_stuff)
|
web::resource("/stuff")
|
||||||
|
.route(web::post().to_async(cache_stuff))
|
||||||
|
.route(web::delete().to_async(del_stuff)),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
.bind("0.0.0.0:8080")?
|
||||||
.bind("0.0.0.0:8080")
|
.run()
|
||||||
.unwrap()
|
|
||||||
.workers(1)
|
|
||||||
.start();
|
|
||||||
|
|
||||||
let _ = sys.run();
|
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
actix-files = { git="https://github.com/actix/actix-web.git" }
|
actix-files = "0.1.0-alpha.1"
|
||||||
actix-session = { git="https://github.com/actix/actix-web.git" }
|
actix-session = "0.1.0-alpha.1"
|
||||||
dotenv = "0.13.0"
|
dotenv = "0.13.0"
|
||||||
env_logger = "0.5.10"
|
env_logger = "0.5.10"
|
||||||
futures = "0.1.22"
|
futures = "0.1.22"
|
||||||
|
@ -7,7 +7,7 @@ workspace = ".."
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "0.2"
|
actix-rt = "0.2"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
dotenv = "0.10"
|
dotenv = "0.10"
|
||||||
env_logger = "0.5"
|
env_logger = "0.5"
|
||||||
|
@ -7,7 +7,7 @@ workspace = ".."
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "0.2"
|
actix-rt = "0.2"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git", features=["ssl"] }
|
actix-web = { version="1.0.0-alpha.1", features=["ssl"] }
|
||||||
|
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
serde = "1.0.43"
|
serde = "1.0.43"
|
||||||
|
@ -7,9 +7,9 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "0.2"
|
actix-rt = "0.2"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
actix-files = { git="https://github.com/actix/actix-web.git" }
|
actix-files = "0.1.0-alpha.1"
|
||||||
actix-session = { git="https://github.com/actix/actix-web.git" }
|
actix-session = "0.1.0-alpha.1"
|
||||||
|
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
env_logger = "0.5"
|
env_logger = "0.5"
|
||||||
|
@ -6,5 +6,5 @@ edition = "2018"
|
|||||||
workspace = ".."
|
workspace = ".."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
|
@ -6,8 +6,8 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
actix-session = { git="https://github.com/actix/actix-web.git" }
|
actix-session = "0.1.0-alpha.1"
|
||||||
|
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
|
@ -6,7 +6,7 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
|||||||
workspace = ".."
|
workspace = ".."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
derive_more = "0.14.0"
|
derive_more = "0.14.0"
|
||||||
futures = "0.1.23"
|
futures = "0.1.23"
|
||||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
|||||||
workspace = ".."
|
workspace = ".."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
@ -6,5 +6,5 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
actix-web = "1.0.0-alpha.1"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
|
||||||
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "0.2"
|
actix-rt = "0.2"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
|
@ -15,7 +15,7 @@ path = "src/server.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "0.2"
|
actix-rt = "0.2"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
env_logger = "0.5"
|
env_logger = "0.5"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
|
@ -6,7 +6,7 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
|
@ -6,7 +6,7 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
@ -7,6 +7,6 @@ workspace = ".."
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-service = "0.3.3"
|
actix-service = "0.3.3"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
@ -2,15 +2,16 @@
|
|||||||
name = "multipart-example"
|
name = "multipart-example"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
workspace = "../"
|
workspace = ".."
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "multipart"
|
name = "multipart"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "*"
|
#actix-web = "1.0.0-alpha.1"
|
||||||
futures = "0.1"
|
actix-web = { git="https://github.com/actix/actix-web.git" }
|
||||||
|
|
||||||
actix = "0.7"
|
env_logger = "0.6"
|
||||||
actix-web = "0.7"
|
futures = "0.1.25"
|
||||||
|
@ -1,44 +1,30 @@
|
|||||||
#![allow(unused_variables)]
|
|
||||||
extern crate actix;
|
|
||||||
extern crate actix_web;
|
|
||||||
extern crate env_logger;
|
|
||||||
extern crate futures;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use actix_web::{
|
use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer};
|
||||||
dev, error, http, middleware, multipart, server, App, Error, FutureResponse,
|
use futures::future::{err, Either};
|
||||||
HttpMessage, HttpRequest, HttpResponse,
|
|
||||||
};
|
|
||||||
|
|
||||||
use futures::future;
|
|
||||||
use futures::{Future, Stream};
|
use futures::{Future, Stream};
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub counter: Cell<usize>,
|
pub counter: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_file(
|
pub fn save_file(field: web::MultipartField) -> impl Future<Item = i64, Error = Error> {
|
||||||
field: multipart::Field<dev::Payload>,
|
|
||||||
) -> Box<Future<Item = i64, Error = Error>> {
|
|
||||||
let file_path_string = "upload.png";
|
let file_path_string = "upload.png";
|
||||||
let mut file = match fs::File::create(file_path_string) {
|
let mut file = match fs::File::create(file_path_string) {
|
||||||
Ok(file) => file,
|
Ok(file) => file,
|
||||||
Err(e) => return Box::new(future::err(error::ErrorInternalServerError(e))),
|
Err(e) => return Either::A(err(error::ErrorInternalServerError(e))),
|
||||||
};
|
};
|
||||||
Box::new(
|
Either::B(
|
||||||
field
|
field
|
||||||
.fold(0i64, move |acc, bytes| {
|
.fold(0i64, move |acc, bytes| {
|
||||||
let rt = file
|
file.write_all(bytes.as_ref())
|
||||||
.write_all(bytes.as_ref())
|
|
||||||
.map(|_| acc + bytes.len() as i64)
|
.map(|_| acc + bytes.len() as i64)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("file.write_all failed: {:?}", e);
|
println!("file.write_all failed: {:?}", e);
|
||||||
error::MultipartError::Payload(error::PayloadError::Io(e))
|
error::MultipartError::Payload(error::PayloadError::Io(e))
|
||||||
});
|
})
|
||||||
future::result(rt)
|
|
||||||
})
|
})
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("save_file failed, {:?}", e);
|
println!("save_file failed, {:?}", e);
|
||||||
@ -48,13 +34,11 @@ pub fn save_file(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_multipart_item(
|
pub fn handle_multipart_item(
|
||||||
item: multipart::MultipartItem<dev::Payload>,
|
item: web::MultipartItem,
|
||||||
) -> Box<Stream<Item = i64, Error = Error>> {
|
) -> Box<Stream<Item = i64, Error = Error>> {
|
||||||
match item {
|
match item {
|
||||||
multipart::MultipartItem::Field(field) => {
|
web::MultipartItem::Field(field) => Box::new(save_file(field).into_stream()),
|
||||||
Box::new(save_file(field).into_stream())
|
web::MultipartItem::Nested(mp) => Box::new(
|
||||||
}
|
|
||||||
multipart::MultipartItem::Nested(mp) => Box::new(
|
|
||||||
mp.map_err(error::ErrorInternalServerError)
|
mp.map_err(error::ErrorInternalServerError)
|
||||||
.map(handle_multipart_item)
|
.map(handle_multipart_item)
|
||||||
.flatten(),
|
.flatten(),
|
||||||
@ -62,11 +46,14 @@ pub fn handle_multipart_item(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn upload(req: HttpRequest<AppState>) -> FutureResponse<HttpResponse> {
|
pub fn upload(
|
||||||
req.state().counter.set(req.state().counter.get() + 1);
|
multipart: web::Multipart,
|
||||||
println!("{:?}", req.state().counter.get());
|
counter: web::Data<Cell<usize>>,
|
||||||
Box::new(
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
||||||
req.multipart()
|
counter.set(counter.get() + 1);
|
||||||
|
println!("{:?}", counter.get());
|
||||||
|
|
||||||
|
multipart
|
||||||
.map_err(error::ErrorInternalServerError)
|
.map_err(error::ErrorInternalServerError)
|
||||||
.map(handle_multipart_item)
|
.map(handle_multipart_item)
|
||||||
.flatten()
|
.flatten()
|
||||||
@ -75,11 +62,10 @@ pub fn upload(req: HttpRequest<AppState>) -> FutureResponse<HttpResponse> {
|
|||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("failed: {}", e);
|
println!("failed: {}", e);
|
||||||
e
|
e
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn index(_req: HttpRequest<AppState>) -> Result<HttpResponse, error::Error> {
|
fn index() -> HttpResponse {
|
||||||
let html = r#"<html>
|
let html = r#"<html>
|
||||||
<head><title>Upload Test</title></head>
|
<head><title>Upload Test</title></head>
|
||||||
<body>
|
<body>
|
||||||
@ -90,28 +76,23 @@ fn index(_req: HttpRequest<AppState>) -> Result<HttpResponse, error::Error> {
|
|||||||
</body>
|
</body>
|
||||||
</html>"#;
|
</html>"#;
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().body(html))
|
HttpResponse::Ok().body(html)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() -> std::io::Result<()> {
|
||||||
::std::env::set_var("RUST_LOG", "actix_web=info");
|
std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info");
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let sys = actix::System::new("multipart-example");
|
|
||||||
|
|
||||||
server::new(|| {
|
HttpServer::new(|| {
|
||||||
App::with_state(AppState {
|
App::new()
|
||||||
counter: Cell::new(0),
|
.data(Cell::new(0usize))
|
||||||
|
.wrap(middleware::Logger::default())
|
||||||
|
.service(
|
||||||
|
web::resource("/")
|
||||||
|
.route(web::get().to(index))
|
||||||
|
.route(web::post().to_async(upload)),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.middleware(middleware::Logger::default())
|
.bind("127.0.0.1:8080")?
|
||||||
.resource("/", |r| {
|
.run()
|
||||||
r.method(http::Method::GET).with(index);
|
|
||||||
r.method(http::Method::POST).with(upload);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8080")
|
|
||||||
.unwrap()
|
|
||||||
.start();
|
|
||||||
|
|
||||||
println!("Starting http server: 127.0.0.1:8080");
|
|
||||||
let _ = sys.run();
|
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@ name = "r2d2-example"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
workspace = "../"
|
workspace = ".."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "0.2"
|
actix-rt = "0.2"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
name = "redis-session"
|
name = "redis-session"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
workspace = "../"
|
workspace = ".."
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.5"
|
actix = "0.8.0-alpha.2"
|
||||||
actix = "0.7"
|
actix-web = "1.0.0-alpha.1"
|
||||||
actix-web = "0.7.3"
|
actix-session = "0.1.0-alpha.1"
|
||||||
actix-redis = { version = "0.5.1", features = ["web"] }
|
actix-redis = { git = "https://github.com/actix/actix-redis.git", features = ["web"] }
|
||||||
|
env_logger = "0.6"
|
||||||
|
@ -1,50 +1,38 @@
|
|||||||
//! Example of redis based session
|
//! Example of redis based session
|
||||||
//!
|
//!
|
||||||
//! [User guide](https://actix.rs/book/actix-web/sec-9-middlewares.html#user-sessions)
|
//! [User guide](https://actix.rs/book/actix-web/sec-9-middlewares.html#user-sessions)
|
||||||
extern crate actix;
|
use actix_redis::RedisSession;
|
||||||
extern crate actix_redis;
|
use actix_session::Session;
|
||||||
extern crate actix_web;
|
use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer, Result};
|
||||||
extern crate env_logger;
|
|
||||||
|
|
||||||
use actix_redis::RedisSessionBackend;
|
|
||||||
use actix_web::middleware::session::{RequestSession, SessionStorage};
|
|
||||||
use actix_web::{middleware, server, App, HttpRequest, HttpResponse, Result};
|
|
||||||
|
|
||||||
/// simple handler
|
/// simple handler
|
||||||
fn index(req: &HttpRequest) -> Result<HttpResponse> {
|
fn index(req: HttpRequest, session: Session) -> Result<HttpResponse> {
|
||||||
println!("{:?}", req);
|
println!("{:?}", req);
|
||||||
|
|
||||||
// session
|
// session
|
||||||
if let Some(count) = req.session().get::<i32>("counter")? {
|
if let Some(count) = session.get::<i32>("counter")? {
|
||||||
println!("SESSION value: {}", count);
|
println!("SESSION value: {}", count);
|
||||||
req.session().set("counter", count + 1)?;
|
session.set("counter", count + 1)?;
|
||||||
} else {
|
} else {
|
||||||
req.session().set("counter", 1)?;
|
session.set("counter", 1)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok("Welcome!".into())
|
Ok("Welcome!".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() -> std::io::Result<()> {
|
||||||
::std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info");
|
std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info");
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let sys = actix::System::new("basic-example");
|
|
||||||
|
|
||||||
server::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
// enable logger
|
// enable logger
|
||||||
.middleware(middleware::Logger::default())
|
.wrap(middleware::Logger::default())
|
||||||
// redis session middleware
|
// redis session middleware
|
||||||
.middleware(SessionStorage::new(RedisSessionBackend::new(
|
.wrap(RedisSession::new("127.0.0.1:6379", &[0; 32]))
|
||||||
"127.0.0.1:6379",
|
|
||||||
&[0; 32],
|
|
||||||
)))
|
|
||||||
// register simple route, handle all methods
|
// register simple route, handle all methods
|
||||||
.resource("/", |r| r.f(index))
|
.service(web::resource("/").to(index))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8080")
|
.bind("127.0.0.1:8080")?
|
||||||
.unwrap()
|
.run()
|
||||||
.start();
|
|
||||||
|
|
||||||
let _ = sys.run();
|
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,22 @@
|
|||||||
name = "simple-auth-server"
|
name = "simple-auth-server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["mygnu <tech@hgill.io>"]
|
authors = ["mygnu <tech@hgill.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
workspace = ".."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "0.7.7"
|
actix = { version = "0.8.0-alpha.2", features = ["http"] }
|
||||||
actix-web = "0.7.14"
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
actix-files = "0.1.0-alpha.1"
|
||||||
|
|
||||||
bcrypt = "0.2.1"
|
bcrypt = "0.2.1"
|
||||||
chrono = { version = "0.4.6", features = ["serde"] }
|
chrono = { version = "0.4.6", features = ["serde"] }
|
||||||
diesel = { version = "1.3.3", features = ["postgres", "uuid", "r2d2", "chrono"] }
|
diesel = { version = "1.3.3", features = ["postgres", "uuid", "r2d2", "chrono"] }
|
||||||
dotenv = "0.13.0"
|
dotenv = "0.13.0"
|
||||||
|
derive_more = "0.14"
|
||||||
env_logger = "0.6.0"
|
env_logger = "0.6.0"
|
||||||
failure = "0.1.3"
|
|
||||||
jsonwebtoken = "5.0"
|
jsonwebtoken = "5.0"
|
||||||
futures = "0.1"
|
futures = "0.1.25"
|
||||||
r2d2 = "0.8.3"
|
r2d2 = "0.8.3"
|
||||||
serde_derive="1.0.80"
|
serde_derive="1.0.80"
|
||||||
serde_json="1.0"
|
serde_json="1.0"
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
use actix::prelude::*;
|
|
||||||
use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService};
|
|
||||||
use actix_web::{fs, http::Method, middleware::Logger, App};
|
|
||||||
use auth_routes::{get_me, login, logout};
|
|
||||||
use chrono::Duration;
|
|
||||||
use invitation_routes::register_email;
|
|
||||||
use models::DbExecutor;
|
|
||||||
use register_routes::register_user;
|
|
||||||
|
|
||||||
pub struct AppState {
|
|
||||||
pub db: Addr<DbExecutor>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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());
|
|
||||||
|
|
||||||
App::with_state(AppState { db })
|
|
||||||
.middleware(Logger::default())
|
|
||||||
.middleware(IdentityService::new(
|
|
||||||
CookieIdentityPolicy::new(secret.as_bytes())
|
|
||||||
.name("auth")
|
|
||||||
.path("/")
|
|
||||||
.domain(domain.as_str())
|
|
||||||
.max_age(Duration::days(1))
|
|
||||||
.secure(false), // this can only be true if you have https
|
|
||||||
))
|
|
||||||
// everything under '/api/' route
|
|
||||||
.scope("/api", |api| {
|
|
||||||
// routes for authentication
|
|
||||||
api.resource("/auth", |r| {
|
|
||||||
r.method(Method::POST).with(login);
|
|
||||||
r.method(Method::DELETE).with(logout);
|
|
||||||
r.method(Method::GET).with(get_me);
|
|
||||||
})
|
|
||||||
// routes to invitation
|
|
||||||
.resource("/invitation", |r| {
|
|
||||||
r.method(Method::POST).with(register_email);
|
|
||||||
})
|
|
||||||
// routes to register as a user after the
|
|
||||||
.resource("/register/{invitation_id}", |r| {
|
|
||||||
r.method(Method::POST).with(register_user);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// serve static files
|
|
||||||
.handler(
|
|
||||||
"/",
|
|
||||||
fs::StaticFiles::new("./static/")
|
|
||||||
.unwrap()
|
|
||||||
.index_file("index.html"),
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,10 +1,12 @@
|
|||||||
use actix::{Handler, Message};
|
use actix::{Handler, Message};
|
||||||
use actix_web::{middleware::identity::RequestIdentity, FromRequest, HttpRequest};
|
use actix_web::{dev::ServiceFromRequest, Error};
|
||||||
|
use actix_web::{middleware::identity::Identity, FromRequest, HttpRequest};
|
||||||
use bcrypt::verify;
|
use bcrypt::verify;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use errors::ServiceError;
|
|
||||||
use models::{DbExecutor, SlimUser, User};
|
use crate::errors::ServiceError;
|
||||||
use utils::decode_token;
|
use crate::models::{DbExecutor, SlimUser, User};
|
||||||
|
use crate::utils::decode_token;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct AuthData {
|
pub struct AuthData {
|
||||||
@ -19,7 +21,7 @@ impl Message for AuthData {
|
|||||||
impl Handler<AuthData> for DbExecutor {
|
impl Handler<AuthData> for DbExecutor {
|
||||||
type Result = Result<SlimUser, ServiceError>;
|
type Result = Result<SlimUser, ServiceError>;
|
||||||
fn handle(&mut self, msg: AuthData, _: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: AuthData, _: &mut Self::Context) -> Self::Result {
|
||||||
use schema::users::dsl::{email, users};
|
use crate::schema::users::dsl::{email, users};
|
||||||
let conn: &PgConnection = &self.0.get().unwrap();
|
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)?;
|
||||||
@ -44,14 +46,15 @@ impl Handler<AuthData> for DbExecutor {
|
|||||||
// simple aliasing makes the intentions clear and its more readable
|
// simple aliasing makes the intentions clear and its more readable
|
||||||
pub type LoggedUser = SlimUser;
|
pub type LoggedUser = SlimUser;
|
||||||
|
|
||||||
impl<S> FromRequest<S> for LoggedUser {
|
impl<P> FromRequest<P> for LoggedUser {
|
||||||
type Config = ();
|
type Error = Error;
|
||||||
type Result = Result<LoggedUser, ServiceError>;
|
type Future = Result<LoggedUser, Error>;
|
||||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
|
||||||
if let Some(identity) = req.identity() {
|
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||||
|
if let Some(identity) = Identity::from_request(req)?.identity() {
|
||||||
let user: SlimUser = decode_token(&identity)?;
|
let user: SlimUser = decode_token(&identity)?;
|
||||||
return Ok(user as LoggedUser);
|
return Ok(user as LoggedUser);
|
||||||
}
|
}
|
||||||
Err(ServiceError::Unauthorized)
|
Err(ServiceError::Unauthorized.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,32 @@
|
|||||||
use actix_web::middleware::identity::RequestIdentity;
|
use actix::Addr;
|
||||||
use actix_web::{
|
use actix_web::middleware::identity::Identity;
|
||||||
AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Json, ResponseError,
|
use actix_web::{web, Error, HttpRequest, HttpResponse, Responder, ResponseError};
|
||||||
};
|
use futures::Future;
|
||||||
use futures::future::Future;
|
|
||||||
use utils::create_token;
|
|
||||||
|
|
||||||
use app::AppState;
|
use crate::auth_handler::{AuthData, LoggedUser};
|
||||||
use auth_handler::{AuthData, LoggedUser};
|
use crate::models::DbExecutor;
|
||||||
|
use crate::utils::create_token;
|
||||||
|
|
||||||
pub fn login(
|
pub fn login(
|
||||||
(auth_data, req): (Json<AuthData>, HttpRequest<AppState>),
|
auth_data: web::Json<AuthData>,
|
||||||
) -> FutureResponse<HttpResponse> {
|
id: Identity,
|
||||||
req.state()
|
db: web::Data<Addr<DbExecutor>>,
|
||||||
.db
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
||||||
.send(auth_data.into_inner())
|
db.send(auth_data.into_inner())
|
||||||
.from_err()
|
.from_err()
|
||||||
.and_then(move |res| match res {
|
.and_then(move |res| match res {
|
||||||
Ok(user) => {
|
Ok(user) => {
|
||||||
let token = create_token(&user)?;
|
let token = create_token(&user)?;
|
||||||
req.remember(token);
|
id.remember(token);
|
||||||
Ok(HttpResponse::Ok().into())
|
Ok(HttpResponse::Ok().into())
|
||||||
}
|
}
|
||||||
Err(err) => Ok(err.error_response()),
|
Err(err) => Ok(err.error_response()),
|
||||||
})
|
})
|
||||||
.responder()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logout(req: HttpRequest<AppState>) -> HttpResponse {
|
pub fn logout(id: Identity) -> impl Responder {
|
||||||
req.forget();
|
id.forget();
|
||||||
HttpResponse::Ok().into()
|
HttpResponse::Ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_me(logged_user: LoggedUser) -> HttpResponse {
|
pub fn get_me(logged_user: LoggedUser) -> HttpResponse {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use models::Invitation;
|
use crate::models::Invitation;
|
||||||
use sparkpost::transmission::{
|
use sparkpost::transmission::{
|
||||||
EmailAddress, Message, Options, Recipient, Transmission, TransmissionResponse,
|
EmailAddress, Message, Options, Recipient, Transmission, TransmissionResponse,
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
use actix_web::{error::ResponseError, HttpResponse};
|
use actix_web::{error::ResponseError, HttpResponse};
|
||||||
|
use derive_more::Display;
|
||||||
use diesel::result::{DatabaseErrorKind, Error};
|
use diesel::result::{DatabaseErrorKind, Error};
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use uuid::ParseError;
|
use uuid::ParseError;
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Debug, Display)]
|
||||||
pub enum ServiceError {
|
pub enum ServiceError {
|
||||||
#[fail(display = "Internal Server Error")]
|
#[display(fmt = "Internal Server Error")]
|
||||||
InternalServerError,
|
InternalServerError,
|
||||||
|
|
||||||
#[fail(display = "BadRequest: {}", _0)]
|
#[display(fmt = "BadRequest: {}", _0)]
|
||||||
BadRequest(String),
|
BadRequest(String),
|
||||||
|
|
||||||
#[fail(display = "Unauthorized")]
|
#[display(fmt = "Unauthorized")]
|
||||||
Unauthorized,
|
Unauthorized,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use actix::{Handler, Message};
|
use actix::{Handler, Message};
|
||||||
use chrono::{Duration, Local};
|
use chrono::{Duration, Local};
|
||||||
use diesel::{self, prelude::*};
|
use diesel::{self, prelude::*};
|
||||||
use errors::ServiceError;
|
|
||||||
use models::{DbExecutor, Invitation};
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::errors::ServiceError;
|
||||||
|
use crate::models::{DbExecutor, Invitation};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CreateInvitation {
|
pub struct CreateInvitation {
|
||||||
pub email: String,
|
pub email: String,
|
||||||
@ -18,7 +19,7 @@ impl Handler<CreateInvitation> for DbExecutor {
|
|||||||
type Result = Result<Invitation, ServiceError>;
|
type Result = Result<Invitation, ServiceError>;
|
||||||
|
|
||||||
fn handle(&mut self, msg: CreateInvitation, _: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: CreateInvitation, _: &mut Self::Context) -> Self::Result {
|
||||||
use schema::invitations::dsl::*;
|
use crate::schema::invitations::dsl::*;
|
||||||
let conn: &PgConnection = &self.0.get().unwrap();
|
let conn: &PgConnection = &self.0.get().unwrap();
|
||||||
|
|
||||||
// creating a new Invitation object with expired at time that is 24 hours from now
|
// creating a new Invitation object with expired at time that is 24 hours from now
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
use actix_web::{
|
use actix::Addr;
|
||||||
AsyncResponder, FutureResponse, HttpResponse, Json, ResponseError, State,
|
use actix_web::{web, Error, HttpResponse, ResponseError};
|
||||||
};
|
|
||||||
use futures::future::Future;
|
use futures::future::Future;
|
||||||
|
|
||||||
use app::AppState;
|
use crate::email_service::send_invitation;
|
||||||
use email_service::send_invitation;
|
use crate::invitation_handler::CreateInvitation;
|
||||||
use invitation_handler::CreateInvitation;
|
use crate::models::DbExecutor;
|
||||||
|
|
||||||
pub fn register_email(
|
pub fn register_email(
|
||||||
(signup_invitation, state): (Json<CreateInvitation>, State<AppState>),
|
signup_invitation: web::Json<CreateInvitation>,
|
||||||
) -> FutureResponse<HttpResponse> {
|
db: web::Data<Addr<DbExecutor>>,
|
||||||
state
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
||||||
.db
|
db.send(signup_invitation.into_inner())
|
||||||
.send(signup_invitation.into_inner())
|
|
||||||
.from_err()
|
.from_err()
|
||||||
.and_then(|db_response| match db_response {
|
.and_then(|db_response| match db_response {
|
||||||
Ok(invitation) => {
|
Ok(invitation) => {
|
||||||
@ -21,5 +19,4 @@ pub fn register_email(
|
|||||||
}
|
}
|
||||||
Err(err) => Ok(err.error_response()),
|
Err(err) => Ok(err.error_response()),
|
||||||
})
|
})
|
||||||
.responder()
|
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,21 @@
|
|||||||
// to avoid the warning from diesel macros
|
#![allow(unused_imports)]
|
||||||
#![allow(proc_macro_derive_resolution_fallback)]
|
|
||||||
|
|
||||||
extern crate actix;
|
|
||||||
extern crate actix_web;
|
|
||||||
extern crate bcrypt;
|
|
||||||
extern crate chrono;
|
|
||||||
extern crate dotenv;
|
|
||||||
extern crate env_logger;
|
|
||||||
extern crate futures;
|
|
||||||
extern crate jsonwebtoken as jwt;
|
|
||||||
extern crate r2d2;
|
|
||||||
extern crate serde;
|
|
||||||
extern crate sparkpost;
|
|
||||||
extern crate uuid;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate diesel;
|
extern crate diesel;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
#[macro_use]
|
|
||||||
extern crate failure;
|
|
||||||
|
|
||||||
mod app;
|
use actix::prelude::*;
|
||||||
|
use actix_files as fs;
|
||||||
|
use actix_web::middleware::{
|
||||||
|
identity::{CookieIdentityPolicy, IdentityService},
|
||||||
|
Logger,
|
||||||
|
};
|
||||||
|
use actix_web::{web, App, HttpServer};
|
||||||
|
use chrono::Duration;
|
||||||
|
use diesel::{r2d2::ConnectionManager, PgConnection};
|
||||||
|
use dotenv::dotenv;
|
||||||
|
|
||||||
mod auth_handler;
|
mod auth_handler;
|
||||||
mod auth_routes;
|
mod auth_routes;
|
||||||
mod email_service;
|
mod email_service;
|
||||||
@ -33,20 +28,17 @@ mod register_routes;
|
|||||||
mod schema;
|
mod schema;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use actix::prelude::*;
|
use crate::models::DbExecutor;
|
||||||
use actix_web::server;
|
|
||||||
use diesel::{r2d2::ConnectionManager, PgConnection};
|
|
||||||
use dotenv::dotenv;
|
|
||||||
use models::DbExecutor;
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() -> std::io::Result<()> {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
std::env::set_var("RUST_LOG", "simple-auth-server=debug,actix_web=info");
|
std::env::set_var(
|
||||||
std::env::set_var("RUST_BACKTRACE", "1");
|
"RUST_LOG",
|
||||||
|
"simple-auth-server=debug,actix_web=info,actix_server=info",
|
||||||
|
);
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
|
||||||
let sys = actix::System::new("Actix_Tutorial");
|
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||||
|
|
||||||
// create db connection pool
|
// create db connection pool
|
||||||
let manager = ConnectionManager::<PgConnection>::new(database_url);
|
let manager = ConnectionManager::<PgConnection>::new(database_url);
|
||||||
@ -57,10 +49,49 @@ fn main() {
|
|||||||
let address: Addr<DbExecutor> =
|
let address: Addr<DbExecutor> =
|
||||||
SyncArbiter::start(4, move || DbExecutor(pool.clone()));
|
SyncArbiter::start(4, move || DbExecutor(pool.clone()));
|
||||||
|
|
||||||
server::new(move || app::create_app(address.clone()))
|
HttpServer::new(move || {
|
||||||
.bind("127.0.0.1:3000")
|
// secret is a random minimum 32 bytes long base 64 string
|
||||||
.expect("Can not bind to '127.0.0.1:3000'")
|
let secret: String =
|
||||||
.start();
|
std::env::var("SECRET_KEY").unwrap_or_else(|_| "0123".repeat(8));
|
||||||
|
let domain: String =
|
||||||
|
std::env::var("DOMAIN").unwrap_or_else(|_| "localhost".to_string());
|
||||||
|
|
||||||
sys.run();
|
App::new()
|
||||||
|
.data(address.clone())
|
||||||
|
.wrap(Logger::default())
|
||||||
|
.wrap(IdentityService::new(
|
||||||
|
CookieIdentityPolicy::new(secret.as_bytes())
|
||||||
|
.name("auth")
|
||||||
|
.path("/")
|
||||||
|
.domain(domain.as_str())
|
||||||
|
.max_age(Duration::days(1))
|
||||||
|
.secure(false), // this can only be true if you have https
|
||||||
|
))
|
||||||
|
// everything under '/api/' route
|
||||||
|
.service(
|
||||||
|
web::scope("/api")
|
||||||
|
// routes for authentication
|
||||||
|
.service(
|
||||||
|
web::resource("/auth")
|
||||||
|
.route(web::post().to_async(auth_routes::login))
|
||||||
|
.route(web::delete().to(auth_routes::logout))
|
||||||
|
.route(web::get().to_async(auth_routes::get_me)),
|
||||||
|
)
|
||||||
|
// routes to invitation
|
||||||
|
.service(
|
||||||
|
web::resource("/invitation").route(
|
||||||
|
web::post().to_async(invitation_routes::register_email),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// routes to register as a user after the
|
||||||
|
.service(
|
||||||
|
web::resource("/register/{invitation_id}")
|
||||||
|
.route(web::post().to_async(register_routes::register_user)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// serve static files
|
||||||
|
.service(fs::Files::new("/", "./static/").index_file("index.html"))
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:3000")?
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
|
|||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use schema::{invitations, users};
|
use crate::schema::{invitations, users};
|
||||||
|
|
||||||
/// This is db executor actor. can be run in parallel
|
/// This is db executor actor. can be run in parallel
|
||||||
pub struct DbExecutor(pub Pool<ConnectionManager<PgConnection>>);
|
pub struct DbExecutor(pub Pool<ConnectionManager<PgConnection>>);
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use actix::{Handler, Message};
|
use actix::{Handler, Message};
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use errors::ServiceError;
|
|
||||||
use models::{DbExecutor, Invitation, SlimUser, User};
|
|
||||||
use utils::hash_password;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::errors::ServiceError;
|
||||||
|
use crate::models::{DbExecutor, Invitation, SlimUser, User};
|
||||||
|
use crate::utils::hash_password;
|
||||||
|
|
||||||
// UserData is used to extract data from a post request by the client
|
// UserData is used to extract data from a post request by the client
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct UserData {
|
pub struct UserData {
|
||||||
@ -26,8 +27,8 @@ impl Message for RegisterUser {
|
|||||||
impl Handler<RegisterUser> for DbExecutor {
|
impl Handler<RegisterUser> for DbExecutor {
|
||||||
type Result = Result<SlimUser, ServiceError>;
|
type Result = Result<SlimUser, ServiceError>;
|
||||||
fn handle(&mut self, msg: RegisterUser, _: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: RegisterUser, _: &mut Self::Context) -> Self::Result {
|
||||||
use schema::invitations::dsl::{id, invitations};
|
use crate::schema::invitations::dsl::{id, invitations};
|
||||||
use schema::users::dsl::users;
|
use crate::schema::users::dsl::users;
|
||||||
let conn: &PgConnection = &self.0.get().unwrap();
|
let conn: &PgConnection = &self.0.get().unwrap();
|
||||||
|
|
||||||
// try parsing the string provided by the user as url parameter
|
// try parsing the string provided by the user as url parameter
|
||||||
|
@ -1,27 +1,25 @@
|
|||||||
use actix_web::{
|
use actix::Addr;
|
||||||
AsyncResponder, FutureResponse, HttpResponse, Json, Path, ResponseError, State,
|
use actix_web::{web, Error, HttpResponse, ResponseError};
|
||||||
};
|
use futures::Future;
|
||||||
use futures::future::Future;
|
|
||||||
|
|
||||||
use app::AppState;
|
use crate::models::DbExecutor;
|
||||||
use register_handler::{RegisterUser, UserData};
|
use crate::register_handler::{RegisterUser, UserData};
|
||||||
|
|
||||||
pub fn register_user(
|
pub fn register_user(
|
||||||
(invitation_id, user_data, state): (Path<String>, Json<UserData>, State<AppState>),
|
invitation_id: web::Path<String>,
|
||||||
) -> FutureResponse<HttpResponse> {
|
user_data: web::Json<UserData>,
|
||||||
|
db: web::Data<Addr<DbExecutor>>,
|
||||||
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
||||||
let msg = RegisterUser {
|
let msg = RegisterUser {
|
||||||
// into_inner() returns the inner string value from Path
|
// into_inner() returns the inner string value from Path
|
||||||
invitation_id: invitation_id.into_inner(),
|
invitation_id: invitation_id.into_inner(),
|
||||||
password: user_data.password.clone(),
|
password: user_data.password.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
state
|
db.send(msg)
|
||||||
.db
|
|
||||||
.send(msg)
|
|
||||||
.from_err()
|
.from_err()
|
||||||
.and_then(|db_response| match db_response {
|
.and_then(|db_response| match db_response {
|
||||||
Ok(slim_user) => Ok(HttpResponse::Ok().json(slim_user)),
|
Ok(slim_user) => Ok(HttpResponse::Ok().json(slim_user)),
|
||||||
Err(service_error) => Ok(service_error.error_response()),
|
Err(service_error) => Ok(service_error.error_response()),
|
||||||
})
|
})
|
||||||
.responder()
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
use bcrypt::{hash, DEFAULT_COST};
|
use bcrypt::{hash, DEFAULT_COST};
|
||||||
use chrono::{Duration, Local};
|
use chrono::{Duration, Local};
|
||||||
use errors::ServiceError;
|
use jsonwebtoken::{decode, encode, Header, Validation};
|
||||||
use jwt::{decode, encode, Header, Validation};
|
|
||||||
use models::SlimUser;
|
use crate::errors::ServiceError;
|
||||||
use std::convert::From;
|
use crate::models::SlimUser;
|
||||||
use std::env;
|
|
||||||
|
|
||||||
pub fn hash_password(plain: &str) -> Result<String, ServiceError> {
|
pub fn hash_password(plain: &str) -> Result<String, ServiceError> {
|
||||||
// get the hashing cost from the env variable or use default
|
// get the hashing cost from the env variable or use default
|
||||||
let hashing_cost: u32 = match env::var("HASH_ROUNDS") {
|
let hashing_cost: u32 = match std::env::var("HASH_ROUNDS") {
|
||||||
Ok(cost) => cost.parse().unwrap_or(DEFAULT_COST),
|
Ok(cost) => cost.parse().unwrap_or(DEFAULT_COST),
|
||||||
_ => DEFAULT_COST,
|
_ => DEFAULT_COST,
|
||||||
};
|
};
|
||||||
@ -64,5 +63,5 @@ pub fn decode_token(token: &str) -> Result<SlimUser, ServiceError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_secret() -> String {
|
fn get_secret() -> String {
|
||||||
env::var("JWT_SECRET").unwrap_or_else(|_| "my secret".into())
|
std::env::var("JWT_SECRET").unwrap_or_else(|_| "my secret".into())
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
futures = "0.1.25"
|
||||||
futures = "0.1"
|
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
|
@ -9,5 +9,5 @@ edition = "2018"
|
|||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
env_logger = "0.5"
|
env_logger = "0.5"
|
||||||
|
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
actix-files = { git="https://github.com/actix/actix-web.git" }
|
actix-files = "0.1.0-alpha.1"
|
||||||
|
@ -6,9 +6,9 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
actix-web = "1.0.0-alpha.1"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
askama = "0.6"
|
askama = "0.6"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
askama = "0.6"
|
askama = "0.6"
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate askama;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer, Result};
|
use actix_web::{web, App, HttpResponse, HttpServer, Result};
|
||||||
|
@ -7,5 +7,5 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
tera = "*"
|
tera = "0.11"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
|
@ -4,14 +4,12 @@ version = "0.0.1"
|
|||||||
authors = ["Rust-iendo Barcelona <riendocontributions@gmail.com>"]
|
authors = ["Rust-iendo Barcelona <riendocontributions@gmail.com>"]
|
||||||
publish = false
|
publish = false
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
workspace = ".."
|
workspace = ".."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
actix-web = "1.0.0-alpha.1"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
|
|
||||||
yarte = "0.1"
|
yarte = "0.1"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
yarte = "0.1"
|
yarte = "0.1"
|
||||||
|
@ -10,8 +10,7 @@ name = "tls-server"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.5"
|
|
||||||
openssl = { version="0.10" }
|
|
||||||
|
|
||||||
actix-rt = "0.2"
|
actix-rt = "0.2"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git", features=["ssl"] }
|
actix-web = { version="1.0.0-alpha.1", features=["ssl"] }
|
||||||
|
env_logger = "0.6"
|
||||||
|
openssl = { version="0.10" }
|
||||||
|
@ -3,16 +3,13 @@ name = "actix-web-cors"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["krircc <krircc@aliyun.com>"]
|
authors = ["krircc <krircc@aliyun.com>"]
|
||||||
workspace = "../../"
|
workspace = "../../"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
actix-web = "1.0.0-alpha.1"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
http = "0.1"
|
|
||||||
|
|
||||||
actix = "0.7"
|
|
||||||
actix-web = "0.7"
|
|
||||||
|
|
||||||
dotenv = "0.10"
|
dotenv = "0.10"
|
||||||
env_logger = "0.5"
|
env_logger = "0.6"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
|
@ -1,49 +1,29 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate actix;
|
|
||||||
extern crate actix_web;
|
|
||||||
extern crate env_logger;
|
|
||||||
extern crate futures;
|
|
||||||
extern crate serde;
|
|
||||||
extern crate serde_json;
|
|
||||||
|
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
http::{header, Method},
|
http::header, middleware::cors::Cors, middleware::Logger, web, App, HttpServer,
|
||||||
middleware,
|
|
||||||
middleware::cors::Cors,
|
|
||||||
server, App,
|
|
||||||
};
|
};
|
||||||
use std::env;
|
|
||||||
|
|
||||||
mod user;
|
mod user;
|
||||||
use user::info;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() -> std::io::Result<()> {
|
||||||
env::set_var("RUST_LOG", "actix_web=info");
|
std::env::set_var("RUST_LOG", "actix_web=info");
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
let sys = actix::System::new("Actix-web-CORS");
|
HttpServer::new(move || {
|
||||||
|
|
||||||
server::new(move || {
|
|
||||||
App::new()
|
App::new()
|
||||||
.middleware(middleware::Logger::default())
|
.wrap(
|
||||||
.configure(|app| {
|
Cors::new()
|
||||||
Cors::for_app(app)
|
|
||||||
.allowed_origin("http://localhost:1234")
|
.allowed_origin("http://localhost:1234")
|
||||||
.allowed_methods(vec!["GET", "POST"])
|
.allowed_methods(vec!["GET", "POST"])
|
||||||
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
|
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
|
||||||
.allowed_header(header::CONTENT_TYPE)
|
.allowed_header(header::CONTENT_TYPE)
|
||||||
.max_age(3600)
|
.max_age(3600),
|
||||||
.resource("/user/info", |r| {
|
)
|
||||||
r.method(Method::POST).with(info);
|
.wrap(Logger::default())
|
||||||
|
.service(web::resource("/user/info").route(web::post().to(user::info)))
|
||||||
})
|
})
|
||||||
.register()
|
.bind("127.0.0.1:8000")?
|
||||||
})
|
.run()
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8000")
|
|
||||||
.unwrap()
|
|
||||||
.shutdown_timeout(2)
|
|
||||||
.start();
|
|
||||||
|
|
||||||
let _ = sys.run();
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use actix_web::{Json, Result};
|
use actix_web::web;
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub struct Info {
|
pub struct Info {
|
||||||
@ -8,12 +8,12 @@ pub struct Info {
|
|||||||
confirm_password: String,
|
confirm_password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn info(info: Json<Info>) -> Result<Json<Info>> {
|
pub fn info(info: web::Json<Info>) -> web::Json<Info> {
|
||||||
println!("=========={:?}=========", info);
|
println!("=========={:?}=========", info);
|
||||||
Ok(Json(Info {
|
web::Json(Info {
|
||||||
username: info.username.clone(),
|
username: info.username.clone(),
|
||||||
email: info.email.clone(),
|
email: info.email.clone(),
|
||||||
password: info.password.clone(),
|
password: info.password.clone(),
|
||||||
confirm_password: info.confirm_password.clone(),
|
confirm_password: info.confirm_password.clone(),
|
||||||
}))
|
})
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,10 @@ path = "src/main.rs"
|
|||||||
#path = "src/client.rs"
|
#path = "src/client.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = { git="https://github.com/actix/actix.git" }
|
actix = "0.8.0-alpha.1"
|
||||||
actix-web = { git="https://github.com/actix/actix-web.git" }
|
actix-web = "1.0.0-alpha.1"
|
||||||
actix-web-actors = { git="https://github.com/actix/actix-web.git" }
|
actix-web-actors = "1.0.0-alpha.1"
|
||||||
actix-files = { git="https://github.com/actix/actix-web.git" }
|
actix-files = "0.1.0-alpha.1"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
@ -1,16 +1,9 @@
|
|||||||
//! Simple websocket client.
|
//! Simple websocket client.
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
extern crate actix;
|
|
||||||
extern crate actix_web;
|
|
||||||
extern crate env_logger;
|
|
||||||
extern crate futures;
|
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
|
|
||||||
use actix::*;
|
use actix::*;
|
||||||
use actix_web::ws::{Client, ClientWriter, Message, ProtocolError};
|
use actix_web::client::{Client, ClientWriter, Message, ProtocolError};
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user