-
Notifications
You must be signed in to change notification settings - Fork 315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move OAuth code->token routines from SessionSrv to Builder-API #616
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ doc = false | |
|
||
[dependencies] | ||
env_logger = "*" | ||
hyper = "*" | ||
iron = "*" | ||
log = "*" | ||
mount = "*" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,13 +16,16 @@ use iron::status; | |
use iron::headers::{Authorization, Bearer}; | ||
use protobuf; | ||
use protocol::jobsrv::{Job, JobCreate, JobGet}; | ||
use protocol::sessionsrv::{Session, SessionCreate, SessionGet}; | ||
use protocol::sessionsrv::{OAuthProvider, Session, SessionCreate, SessionGet}; | ||
use protocol::vault::{Origin, OriginCreate, OriginGet}; | ||
use protocol::net::{Msg, NetError, ErrCode}; | ||
use protocol::net::{self, NetError, ErrCode}; | ||
use router::Router; | ||
use rustc_serialize::json::{self, ToJson}; | ||
use zmq; | ||
|
||
use error::Error; | ||
use oauth::github; | ||
|
||
pub fn authenticate(req: &mut Request, | ||
ctx: &Arc<Mutex<zmq::Context>>) | ||
-> result::Result<Session, Response> { | ||
|
@@ -39,7 +42,10 @@ pub fn authenticate(req: &mut Request, | |
let session = protobuf::parse_from_bytes(rep.get_body()).unwrap(); | ||
Ok(session) | ||
} | ||
"NetError" => Err(render_net_error(&rep)), | ||
"NetError" => { | ||
let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap(); | ||
Err(render_net_error(&err)) | ||
} | ||
_ => unreachable!("unexpected msg: {:?}", rep), | ||
} | ||
} | ||
|
@@ -56,28 +62,70 @@ pub fn authenticate(req: &mut Request, | |
pub fn session_create(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult<Response> { | ||
let params = req.extensions.get::<Router>().unwrap(); | ||
let code = match params.find("code") { | ||
Some(code) => code.to_string(), | ||
Some(code) => code, | ||
_ => return Ok(Response::with(status::BadRequest)), | ||
}; | ||
let mut conn = Broker::connect(&ctx).unwrap(); | ||
let mut request = SessionCreate::new(); | ||
request.set_code(code.to_string()); | ||
conn.route(&request).unwrap(); | ||
match conn.recv() { | ||
Ok(rep) => { | ||
match rep.get_message_id() { | ||
"Session" => { | ||
let token: Session = protobuf::parse_from_bytes(rep.get_body()).unwrap(); | ||
let encoded = json::encode(&token.to_json()).unwrap(); | ||
Ok(Response::with((status::Ok, encoded))) | ||
match github::authenticate(code) { | ||
Ok(token) => { | ||
match github::user(&token) { | ||
Ok(user) => { | ||
let mut conn = Broker::connect(&ctx).unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The calls to I'm using |
||
let mut request = SessionCreate::new(); | ||
request.set_token(token); | ||
request.set_extern_id(user.id); | ||
request.set_email(user.email); | ||
request.set_name(user.name); | ||
request.set_provider(OAuthProvider::GitHub); | ||
conn.route(&request).unwrap(); | ||
match conn.recv() { | ||
Ok(rep) => { | ||
match rep.get_message_id() { | ||
"Session" => { | ||
let token: Session = protobuf::parse_from_bytes(rep.get_body()) | ||
.unwrap(); | ||
let encoded = json::encode(&token.to_json()).unwrap(); | ||
Ok(Response::with((status::Ok, encoded))) | ||
} | ||
"NetError" => { | ||
let err: NetError = protobuf::parse_from_bytes(rep.get_body()) | ||
.unwrap(); | ||
Ok(render_net_error(&err)) | ||
} | ||
_ => unreachable!("unexpected msg: {:?}", rep), | ||
} | ||
} | ||
Err(e) => { | ||
error!("{:?}", e); | ||
Ok(Response::with(status::ServiceUnavailable)) | ||
} | ||
} | ||
} | ||
Err(e @ Error::JsonDecode(_)) => { | ||
debug!("github user get, err={:?}", e); | ||
let err = net::err(ErrCode::BAD_REMOTE_REPLY, "rg:auth:1"); | ||
Ok(render_net_error(&err)) | ||
} | ||
Err(e) => { | ||
debug!("github user get, err={:?}", e); | ||
let err = net::err(ErrCode::BUG, "ss:auth:2"); | ||
Ok(render_net_error(&err)) | ||
} | ||
"NetError" => Ok(render_net_error(&rep)), | ||
_ => unreachable!("unexpected msg: {:?}", rep), | ||
} | ||
} | ||
Err(Error::Auth(e)) => { | ||
debug!("github authentication, err={:?}", e); | ||
let err = net::err(ErrCode::REMOTE_REJECTED, e.error); | ||
Ok(render_net_error(&err)) | ||
} | ||
Err(e @ Error::JsonDecode(_)) => { | ||
debug!("github authentication, err={:?}", e); | ||
let err = net::err(ErrCode::BAD_REMOTE_REPLY, "ss:auth:1"); | ||
Ok(render_net_error(&err)) | ||
} | ||
Err(e) => { | ||
error!("{:?}", e); | ||
Ok(Response::with(status::ServiceUnavailable)) | ||
error!("github authentication, err={:?}", e); | ||
let err = net::err(ErrCode::BUG, "ss:auth:0"); | ||
Ok(render_net_error(&err)) | ||
} | ||
} | ||
} | ||
|
@@ -100,7 +148,10 @@ pub fn origin_show(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronRes | |
let encoded = json::encode(&origin.to_json()).unwrap(); | ||
Ok(Response::with((status::Ok, encoded))) | ||
} | ||
"NetError" => Ok(render_net_error(&rep)), | ||
"NetError" => { | ||
let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap(); | ||
Ok(render_net_error(&err)) | ||
} | ||
_ => unreachable!("unexpected msg: {:?}", rep), | ||
} | ||
} | ||
|
@@ -137,7 +188,10 @@ pub fn origin_create(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronR | |
let encoded = json::encode(&origin.to_json()).unwrap(); | ||
Ok(Response::with((status::Created, encoded))) | ||
} | ||
"NetError" => Ok(render_net_error(&rep)), | ||
"NetError" => { | ||
let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap(); | ||
Ok(render_net_error(&err)) | ||
} | ||
_ => unreachable!("unexpected msg: {:?}", rep), | ||
} | ||
} | ||
|
@@ -165,7 +219,10 @@ pub fn job_create(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResu | |
let encoded = json::encode(&job.to_json()).unwrap(); | ||
Ok(Response::with((status::Created, encoded))) | ||
} | ||
"NetError" => Ok(render_net_error(&rep)), | ||
"NetError" => { | ||
let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap(); | ||
Ok(render_net_error(&err)) | ||
} | ||
_ => unreachable!("unexpected msg: {:?}", rep), | ||
} | ||
} | ||
|
@@ -199,7 +256,10 @@ pub fn job_show(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult | |
let encoded = json::encode(&job.to_json()).unwrap(); | ||
Ok(Response::with((status::Ok, encoded))) | ||
} | ||
"NetError" => Ok(render_net_error(&rep)), | ||
"NetError" => { | ||
let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap(); | ||
Ok(render_net_error(&err)) | ||
} | ||
_ => unreachable!("unexpected msg: {:?}", rep), | ||
} | ||
} | ||
|
@@ -221,14 +281,13 @@ pub fn job_show(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult | |
/// * The given encoded message was not a NetError | ||
/// * The given messsage could not be decoded | ||
/// * The NetError could not be encoded to JSON | ||
fn render_net_error(msg: &Msg) -> Response { | ||
assert_eq!(msg.get_message_id(), "NetError"); | ||
let err: NetError = protobuf::parse_from_bytes(msg.get_body()).unwrap(); | ||
fn render_net_error(err: &NetError) -> Response { | ||
let encoded = json::encode(&err.to_json()).unwrap(); | ||
let status = match err.get_code() { | ||
ErrCode::ENTITY_NOT_FOUND => status::NotFound, | ||
ErrCode::NO_SHARD => status::ServiceUnavailable, | ||
ErrCode::TIMEOUT => status::RequestTimeout, | ||
ErrCode::BAD_REMOTE_REPLY => status::BadGateway, | ||
_ => status::InternalServerError, | ||
}; | ||
Response::with((status, encoded)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,6 +70,37 @@ pub trait BasicSet: Bucket { | |
} | ||
} | ||
|
||
/// A generic data set for reading and writing entities into the datastore with a time to live. | ||
/// | ||
/// This is identical to `BasicSet` with the exception that entities expire. | ||
pub trait ExpiringSet: Bucket { | ||
/// Type of objects stored inside this data set. | ||
type Record: Persistable; | ||
|
||
/// Expiration time (in seconds) for any entities written to the set. | ||
fn expiry() -> usize; | ||
|
||
/// Retrieves a record from the data set with the given ID. | ||
fn find(&self, id: &<Self::Record as Persistable>::Key) -> Result<Self::Record> { | ||
let conn = try!(self.pool().get()); | ||
let bytes = try!(conn.get::<String, Vec<u8>>(Self::key(id))); | ||
if bytes.is_empty() { | ||
return Err(Error::EntityNotFound); | ||
} | ||
let value = parse_from_bytes(&bytes).unwrap(); | ||
Ok(value) | ||
} | ||
|
||
/// Write a new record to the data set with a TTL. | ||
fn write(&self, record: &Self::Record) -> Result<()> { | ||
let conn = try!(self.pool().get()); | ||
try!(conn.set_ex(Self::key(&record.primary_key()), | ||
record.write_to_bytes().unwrap(), | ||
Self::expiry())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice, so you implement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly! |
||
Ok(()) | ||
} | ||
} | ||
|
||
/// A specialized data set for reading and writing entities with a unique and sequential | ||
/// identifier. | ||
/// | ||
|
@@ -132,18 +163,20 @@ pub trait InstaSet: Bucket { | |
|
||
/// A data set for writing basic key/value indices. | ||
pub trait IndexSet: Bucket { | ||
/// Type of the lookup key | ||
type Key: Clone + redis::FromRedisValue + redis::ToRedisArgs; | ||
/// Type of the Value stored for each entry in the index. | ||
type Value: redis::FromRedisValue + redis::ToRedisArgs; | ||
|
||
/// Retrieves the value for the given ID. | ||
fn find(&self, id: &str) -> Result<Self::Value> { | ||
fn find(&self, id: &Self::Key) -> Result<Self::Value> { | ||
let conn = try!(self.pool().get()); | ||
let value = try!(conn.hget(Self::prefix(), id)); | ||
let value = try!(conn.hget(Self::prefix(), id.clone())); | ||
Ok(value) | ||
} | ||
|
||
/// Write a new index entry to the data set. | ||
fn write(&self, id: &str, value: Self::Value) -> Result<()> { | ||
fn write(&self, id: &Self::Key, value: Self::Value) -> Result<()> { | ||
let conn = try!(self.pool().get()); | ||
try!(conn.hset(Self::prefix(), id.clone(), value)); | ||
Ok(()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The matchers are certainly doing nice work here