2020-11-17 14:28:04 +01:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2020-05-11 18:21:45 +02:00
|
|
|
use slog::Logger;
|
|
|
|
|
2020-09-07 17:23:42 +02:00
|
|
|
use smol::net::TcpStream;
|
2020-05-11 18:21:45 +02:00
|
|
|
|
2020-10-29 13:04:20 +01:00
|
|
|
use crate::error::{Error, Result};
|
2020-11-17 14:35:16 +01:00
|
|
|
use crate::api::auth;
|
|
|
|
use crate::api::Bootstrap;
|
2020-05-10 17:23:43 +02:00
|
|
|
|
2020-10-29 13:04:20 +01:00
|
|
|
use capnp_rpc::{twoparty, rpc_twoparty_capnp};
|
|
|
|
|
2020-11-17 14:35:16 +01:00
|
|
|
use crate::schema::connection_capnp;
|
2020-05-11 18:21:45 +02:00
|
|
|
|
2020-11-20 13:06:55 +01:00
|
|
|
use crate::db::Databases;
|
2020-11-24 14:16:22 +01:00
|
|
|
use crate::db::access::{AccessControl, Permission};
|
2020-11-24 15:57:23 +01:00
|
|
|
use crate::db::user::User;
|
2020-11-24 14:16:22 +01:00
|
|
|
use crate::builtin;
|
2020-11-20 13:06:55 +01:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
2020-10-23 15:29:32 +02:00
|
|
|
/// Connection context
|
2020-11-17 14:28:04 +01:00
|
|
|
// TODO this should track over several connections
|
|
|
|
pub struct Session {
|
2020-11-24 14:16:22 +01:00
|
|
|
// Session-spezific log
|
2020-11-19 14:53:14 +01:00
|
|
|
pub log: Logger,
|
2020-11-24 15:57:23 +01:00
|
|
|
user: Option<User>,
|
2020-11-24 14:16:22 +01:00
|
|
|
accessdb: Arc<AccessControl>,
|
2020-10-23 15:29:32 +02:00
|
|
|
}
|
2020-05-11 18:21:45 +02:00
|
|
|
|
2020-11-17 14:28:04 +01:00
|
|
|
impl Session {
|
2020-11-24 14:16:22 +01:00
|
|
|
pub fn new(log: Logger, accessdb: Arc<AccessControl>) -> Self {
|
2020-11-24 15:57:23 +01:00
|
|
|
let user = None;
|
2020-10-29 13:04:20 +01:00
|
|
|
|
2020-11-24 15:57:23 +01:00
|
|
|
Session { log, user, accessdb }
|
2020-11-24 14:16:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if the current session has a certain permission
|
|
|
|
pub async fn check_permission<P: AsRef<Permission>>(&self, perm: &P) -> Result<bool> {
|
2020-11-24 15:57:23 +01:00
|
|
|
if let Some(user) = self.user.as_ref() {
|
|
|
|
self.accessdb.check(&user.data, perm).await
|
2020-11-24 14:16:22 +01:00
|
|
|
} else {
|
2020-11-24 15:57:23 +01:00
|
|
|
Ok(false)
|
2020-11-24 14:16:22 +01:00
|
|
|
}
|
2020-10-29 13:04:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn handshake(log: &Logger, stream: &mut TcpStream) -> Result<()> {
|
2020-11-10 13:34:09 +01:00
|
|
|
if let Some(m) = capnp_futures::serialize::read_message(stream.clone(), Default::default()).await? {
|
2020-10-29 13:04:20 +01:00
|
|
|
let greeting = m.get_root::<connection_capnp::greeting::Reader>()?;
|
|
|
|
let major = greeting.get_major();
|
|
|
|
let minor = greeting.get_minor();
|
|
|
|
|
2020-11-10 13:34:09 +01:00
|
|
|
if major != 0 {
|
2020-10-29 13:04:20 +01:00
|
|
|
Err(Error::BadVersion((major, minor)))
|
|
|
|
} else {
|
2020-11-10 13:34:09 +01:00
|
|
|
let program = format!("{}-{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
|
|
|
|
|
|
|
|
let mut answer = ::capnp::message::Builder::new_default();
|
|
|
|
let mut b = answer.init_root::<connection_capnp::greeting::Builder>();
|
|
|
|
b.set_program(&program);
|
|
|
|
b.set_host("localhost");
|
|
|
|
b.set_major(0);
|
|
|
|
b.set_minor(1);
|
|
|
|
capnp_futures::serialize::write_message(stream, answer).await?;
|
2020-10-29 13:04:20 +01:00
|
|
|
info!(log, "Handshake successful with peer {} running {}, API {}.{}",
|
|
|
|
greeting.get_host()?, greeting.get_program()?, major, minor);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-20 15:54:53 +01:00
|
|
|
pub async fn handle_connection(log: Logger, mut stream: TcpStream, db: Databases) -> Result<()> {
|
2020-11-19 14:53:14 +01:00
|
|
|
info!(log, "New connection from on {:?}", stream);
|
2020-11-24 14:16:22 +01:00
|
|
|
let session = Arc::new(Session::new(log, db.access.clone()));
|
2020-11-20 13:06:55 +01:00
|
|
|
let boots = Bootstrap::new(session, db);
|
2020-11-17 14:28:04 +01:00
|
|
|
let rpc: connection_capnp::bootstrap::Client = capnp_rpc::new_client(boots);
|
2020-10-29 13:04:20 +01:00
|
|
|
|
|
|
|
let network = twoparty::VatNetwork::new(stream.clone(), stream,
|
|
|
|
rpc_twoparty_capnp::Side::Server, Default::default());
|
|
|
|
let rpc_system = capnp_rpc::RpcSystem::new(Box::new(network),
|
|
|
|
Some(rpc.client));
|
|
|
|
|
2020-11-17 14:28:04 +01:00
|
|
|
rpc_system.await.unwrap();
|
2020-10-29 13:04:20 +01:00
|
|
|
Ok(())
|
2020-05-11 18:21:45 +02:00
|
|
|
}
|