feat: implement appservices

this also reverts some stateres changes
This commit is contained in:
Timo Kösters 2020-12-08 10:33:44 +01:00
parent d62f17a91a
commit 6e5b35ea92
No known key found for this signature in database
GPG key ID: 24DA7517711A2BA4
26 changed files with 696 additions and 584 deletions

View file

@ -12,7 +12,7 @@ use std::{
#[cfg(feature = "conduit_bin")]
use {
crate::utils,
log::warn,
log::{debug, warn},
rocket::{
data::{
ByteUnit, Data, FromDataFuture, FromTransformedData, Transform, TransformFuture,
@ -34,6 +34,7 @@ pub struct Ruma<T: Outgoing> {
pub sender_user: Option<UserId>,
pub sender_device: Option<Box<DeviceId>>,
pub json_body: Option<Box<serde_json::value::RawValue>>, // This is None when body is not a valid string
pub from_appservice: bool,
}
#[cfg(feature = "conduit_bin")]
@ -66,28 +67,72 @@ where
.await
.expect("database was loaded");
let (sender_user, sender_device) = match T::METADATA.authentication {
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
// Get token from header or query value
let token = match request
.headers()
.get_one("Authorization")
.map(|s| s[7..].to_owned()) // Split off "Bearer "
.or_else(|| request.get_query_value("access_token").and_then(|r| r.ok()))
{
// TODO: M_MISSING_TOKEN
None => return Failure((Status::Unauthorized, ())),
Some(token) => token,
};
// Get token from header or query value
let token = request
.headers()
.get_one("Authorization")
.map(|s| s[7..].to_owned()) // Split off "Bearer "
.or_else(|| request.get_query_value("access_token").and_then(|r| r.ok()));
// Check if token is valid
match db.users.find_from_token(&token).unwrap() {
// TODO: M_UNKNOWN_TOKEN
None => return Failure((Status::Unauthorized, ())),
Some((user_id, device_id)) => (Some(user_id), Some(device_id.into())),
let (sender_user, sender_device, from_appservice) = if let Some((_id, registration)) =
db.appservice
.iter_all()
.filter_map(|r| r.ok())
.find(|(_id, registration)| {
registration
.get("as_token")
.and_then(|as_token| as_token.as_str())
.map_or(false, |as_token| token.as_deref() == Some(as_token))
}) {
match T::METADATA.authentication {
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
let user_id = request.get_query_value::<String>("user_id").map_or_else(
|| {
UserId::parse_with_server_name(
registration
.get("sender_localpart")
.unwrap()
.as_str()
.unwrap(),
db.globals.server_name(),
)
.unwrap()
},
|string| {
UserId::try_from(string.expect("parsing to string always works"))
.unwrap()
},
);
if !db.users.exists(&user_id).unwrap() {
return Failure((Status::Unauthorized, ()));
}
// TODO: Check if appservice is allowed to be that user
(Some(user_id), None, true)
}
AuthScheme::ServerSignatures => (None, None, true),
AuthScheme::None => (None, None, true),
}
} else {
match T::METADATA.authentication {
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
if let Some(token) = token {
match db.users.find_from_token(&token).unwrap() {
// TODO: M_UNKNOWN_TOKEN
None => return Failure((Status::Unauthorized, ())),
Some((user_id, device_id)) => {
(Some(user_id), Some(device_id.into()), false)
}
}
} else {
// TODO: M_MISSING_TOKEN
return Failure((Status::Unauthorized, ()));
}
}
AuthScheme::ServerSignatures => (None, None, false),
AuthScheme::None => (None, None, false),
}
_ => (None, None),
};
let mut http_request = http::Request::builder()
@ -103,7 +148,7 @@ where
handle.read_to_end(&mut body).await.unwrap();
let http_request = http_request.body(body.clone()).unwrap();
log::debug!("{:?}", http_request);
debug!("{:?}", http_request);
match <T as Outgoing>::Incoming::try_from(http_request) {
Ok(t) => Success(Ruma {
@ -114,6 +159,7 @@ where
json_body: utils::string_from_bytes(&body)
.ok()
.and_then(|s| serde_json::value::RawValue::from_string(s).ok()),
from_appservice,
}),
Err(e) => {
warn!("{:?}", e);