[WIP] authenticate working
This commit is contained in:
@ -18,3 +18,4 @@ r2d2_postgres = "0.18.0"
|
||||
ansi_term = "0.12"
|
||||
rust-crypto = "^0.2"
|
||||
base64 = "0.13.0"
|
||||
base64-url = "1.4.10"
|
||||
|
@ -17,7 +17,7 @@ static mut POOL: Option<Arc<Mutex<Pool>>> = None;
|
||||
|
||||
pub fn init() -> Result<(), Error> {
|
||||
let manager = PostgresConnectionManager::new(
|
||||
"host=localhost user=postgres dbname=test".parse().unwrap(),
|
||||
"host=localhost user=postgres dbname=locutus".parse().unwrap(),
|
||||
NoTls,
|
||||
);
|
||||
|
||||
|
@ -12,6 +12,7 @@ pub enum Kind {
|
||||
NotImplementedError,
|
||||
UsimpProtocolError,
|
||||
Utf8DecodeError,
|
||||
AuthenticationError,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -61,6 +62,7 @@ impl Error {
|
||||
Kind::NotImplementedError => "Not yet implemented",
|
||||
Kind::UsimpProtocolError => "USIMP protocol error",
|
||||
Kind::Utf8DecodeError => "Unable to decode UTF-8 data",
|
||||
Kind::AuthenticationError => "Unable to authenticate",
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -91,6 +93,7 @@ impl fmt::Display for Error {
|
||||
Kind::NotImplementedError => "not yet implemented",
|
||||
Kind::UsimpProtocolError => "usimp protocol error",
|
||||
Kind::Utf8DecodeError => "unable to decode utf-8 data",
|
||||
Kind::AuthenticationError => "unable to authenticate",
|
||||
}
|
||||
.to_string();
|
||||
if let Some(desc) = &self.desc {
|
||||
|
@ -3,6 +3,7 @@ use crate::error::*;
|
||||
use crate::usimp;
|
||||
use crate::websocket;
|
||||
use serde_json;
|
||||
use crate::usimp::Envelope;
|
||||
|
||||
pub fn connection_handler(client: super::Stream) {
|
||||
let mut client = super::HttpStream {
|
||||
@ -49,6 +50,8 @@ fn request_handler(client: &mut super::HttpStream) {
|
||||
return websocket::connection_handler(client, &req, res);
|
||||
}
|
||||
|
||||
// TODO check Content-Type == application/json
|
||||
|
||||
let mut error = None;
|
||||
let parts: Vec<&str> = req.uri.split('/').collect();
|
||||
|
||||
@ -167,12 +170,48 @@ fn endpoint_handler(
|
||||
client.stream.read_exact(&mut buf[..length]).unwrap();
|
||||
|
||||
// TODO decompress
|
||||
let input = match serde_json::from_slice(&buf[..length]) {
|
||||
let data = match serde_json::from_slice(&buf[..length]) {
|
||||
Ok(val) => val,
|
||||
Err(e) => return error_handler(client, res, e.into()),
|
||||
};
|
||||
|
||||
let buf = match usimp::endpoint(endpoint, input) {
|
||||
let mut authorization = None;
|
||||
if let Some(auth) = req.header.find_field("Authorization") {
|
||||
authorization = Some(auth.split(" ").skip(1).collect());
|
||||
}
|
||||
|
||||
let mut from_domain;
|
||||
if let Some(from) = req.header.find_field("From-Domain") {
|
||||
from_domain = from.to_string();
|
||||
} else {
|
||||
return error_handler(
|
||||
client,
|
||||
res,
|
||||
Error::new(Kind::UsimpProtocolError, Class::ClientError)
|
||||
.set_desc("Unable to find field 'From-Domain'".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
let mut to_domain;
|
||||
if let Some(to) = req.header.find_field("To-Domain") {
|
||||
to_domain = to.to_string();
|
||||
} else {
|
||||
return error_handler(
|
||||
client,
|
||||
res,
|
||||
Error::new(Kind::UsimpProtocolError, Class::ClientError)
|
||||
.set_desc("Unable to find field 'To-Domain'".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
let input = Envelope {
|
||||
endpoint: endpoint.to_string(),
|
||||
from_domain,
|
||||
to_domain,
|
||||
authorization,
|
||||
data,
|
||||
};
|
||||
let buf = match usimp::endpoint(input) {
|
||||
Ok(output) => output.to_string() + "\r\n",
|
||||
Err(e) => return error_handler(client, res, e),
|
||||
};
|
||||
|
@ -266,7 +266,7 @@ impl Response {
|
||||
buf = Some(new_buf);
|
||||
}
|
||||
|
||||
self.send(stream);
|
||||
self.send(stream)?;
|
||||
|
||||
if let Some(buf) = buf {
|
||||
stream.write_all(buf.as_bytes())?;
|
||||
|
100
src/usimp/mod.rs
100
src/usimp/mod.rs
@ -3,12 +3,36 @@ use serde_json;
|
||||
|
||||
use crate::database;
|
||||
use crate::error::*;
|
||||
use crypto::digest::Digest;
|
||||
|
||||
pub fn endpoint(endpoint: &str, input: serde_json::Value) -> Result<serde_json::Value, Error> {
|
||||
match endpoint {
|
||||
"echo" => Ok(serde_json::to_value(echo(serde_json::from_value(input)?)?)?),
|
||||
_ => Err(Error::new(Kind::InvalidEndpointError, Class::ClientError)),
|
||||
pub struct Envelope {
|
||||
pub endpoint: String,
|
||||
pub from_domain: String,
|
||||
pub to_domain: String,
|
||||
pub authorization: Option<String>,
|
||||
pub data: serde_json::Value,
|
||||
}
|
||||
|
||||
pub fn endpoint(envelope: Envelope) -> Result<serde_json::Value, Error> {
|
||||
// TODO check authorization
|
||||
// TODO domain_check
|
||||
match envelope.endpoint.as_str() {
|
||||
"echo" => Ok(serde_json::to_value(echo(serde_json::from_value(envelope.data)?)?)?),
|
||||
"authorize" => Ok(serde_json::to_value(authorize(serde_json::from_value(envelope.data)?)?)?),
|
||||
"notify" => Ok(serde_json::to_value(notify(serde_json::from_value(envelope.data)?)?)?),
|
||||
_ => return Err(Error::new(Kind::InvalidEndpointError, Class::ClientError)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id(input: &str) -> String {
|
||||
let mut hasher = crypto::sha2::Sha256::new();
|
||||
hasher.input_str(chrono::Utc::now().timestamp_millis().to_string().as_str());
|
||||
hasher.input_str(" ");
|
||||
hasher.input_str(input);
|
||||
|
||||
let mut result = [0u8; 32];
|
||||
hasher.result(&mut result);
|
||||
base64_url::encode(&result)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -38,3 +62,71 @@ pub fn echo(input: EchoInput) -> Result<EchoOutput, Error> {
|
||||
}
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AuthorizeInput {
|
||||
r#type: String,
|
||||
name: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AuthorizeOutput {
|
||||
token: String,
|
||||
}
|
||||
|
||||
pub fn authorize(input: AuthorizeInput) -> Result<AuthorizeOutput, Error> {
|
||||
let backend = database::client()?;
|
||||
|
||||
let mut token;
|
||||
match backend {
|
||||
database::Client::Postgres(mut client) => {
|
||||
let res = client.query("SELECT account_id FROM accounts WHERE name = $1", &[&input.name])?;
|
||||
if res.len() == 0 {
|
||||
return Err(Error::new(Kind::AuthenticationError, Class::ClientError));
|
||||
}
|
||||
token = res.get(0).unwrap().get(0);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(AuthorizeOutput { token })
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SendEventInput {
|
||||
room_id: String,
|
||||
data: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SendEventOutput {
|
||||
event_id: String,
|
||||
}
|
||||
|
||||
pub fn send_event(input: SendEventInput) -> Result<SendEventOutput, Error> {
|
||||
let backend = database::client()?;
|
||||
let event_id = get_id("hermann"); // TODO fix id generation
|
||||
let data = serde_json::to_string(&input.data)?;
|
||||
|
||||
match backend {
|
||||
database::Client::Postgres(mut client) => {
|
||||
client.execute("INSERT INTO events (event_id, room_id, data) VALUES ($1, $2, $3)", &[&event_id, &input.room_id, &data])?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SendEventOutput { event_id })
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct NotifyInput {
|
||||
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct NotifyOutput {
|
||||
|
||||
}
|
||||
|
||||
pub fn notify(input: NotifyInput) -> Result<NotifyOutput, Error> {
|
||||
Ok(NotifyOutput {})
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ pub fn connection_handler(
|
||||
// TODO threads?
|
||||
let req: RequestEnvelope = serde_json::from_str(msg.data.as_str()).unwrap();
|
||||
println!("Endpoint: {}, ReqNo: {}, Data: {}", req.endpoint, req.request_nr, req.data);
|
||||
let a = usimp::endpoint(req.endpoint.as_str(), req.data).unwrap();
|
||||
//let a = usimp::endpoint(req.endpoint.as_str(), req.data).unwrap();
|
||||
},
|
||||
Message::CloseMessage(msg) => {
|
||||
println!("Received close frame: {}: {}", msg.code.unwrap_or(0), msg.reason.unwrap_or("-".to_string()));
|
||||
|
Reference in New Issue
Block a user