Can get current user identity
This commit is contained in:
@ -20,7 +20,7 @@ pub struct AppConfig {
|
||||
|
||||
/// Matrix API origin
|
||||
#[clap(short, long, env, default_value = "http://127.0.0.1:8448")]
|
||||
pub matrix_api: String,
|
||||
pub matrix_homeserver: String,
|
||||
|
||||
/// Redis connection hostname
|
||||
#[clap(long, env, default_value = "localhost")]
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::user::{APIClient, APIClientID, UserConfig, UserID};
|
||||
use crate::server::HttpFailure;
|
||||
use crate::user::{APIClient, APIClientID, RumaClient, UserConfig, UserID};
|
||||
use crate::utils::curr_time;
|
||||
use actix_remote_ip::RemoteIP;
|
||||
use actix_web::dev::Payload;
|
||||
@ -6,13 +7,14 @@ use actix_web::{FromRequest, HttpRequest};
|
||||
use bytes::Bytes;
|
||||
use jwt_simple::common::VerificationOptions;
|
||||
use jwt_simple::prelude::{Duration, HS256Key, MACLike};
|
||||
use ruma::api::{IncomingResponse, OutgoingRequest};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub struct APIClientAuth {
|
||||
pub user: UserConfig,
|
||||
client: APIClient,
|
||||
pub client: APIClient,
|
||||
pub payload: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
@ -94,7 +96,7 @@ impl APIClientAuth {
|
||||
// Decode JWT
|
||||
let key = HS256Key::from_bytes(client.secret.as_bytes());
|
||||
let mut verif = VerificationOptions::default();
|
||||
verif.max_validity = Some(Duration::from_mins(15));
|
||||
verif.max_validity = Some(Duration::from_mins(20));
|
||||
let claims = match key.verify_token::<TokenClaims>(jwt_token, Some(verif)) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
@ -178,6 +180,22 @@ impl APIClientAuth {
|
||||
user,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get an instance of Matrix client
|
||||
pub async fn client(&self) -> anyhow::Result<RumaClient> {
|
||||
self.user.matrix_client().await
|
||||
}
|
||||
|
||||
/// Send request to matrix server
|
||||
pub async fn send_request<R: OutgoingRequest<IncomingResponse = E>, E: IncomingResponse>(
|
||||
&self,
|
||||
request: R,
|
||||
) -> anyhow::Result<E, HttpFailure> {
|
||||
match self.client().await?.send_request(request).await {
|
||||
Ok(e) => Ok(e),
|
||||
Err(e) => Err(HttpFailure::MatrixClientError(e.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRequest for APIClientAuth {
|
||||
|
@ -48,6 +48,7 @@ async fn main() -> std::io::Result<()> {
|
||||
// API routes
|
||||
.route("/api", web::get().to(api::api_home))
|
||||
.route("/api", web::post().to(api::api_home))
|
||||
.route("/api/account/whoami", web::get().to(api::account::who_am_i))
|
||||
})
|
||||
.bind(&AppConfig::get().listen_address)?
|
||||
.run()
|
||||
|
23
src/server/api/account.rs
Normal file
23
src/server/api/account.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use crate::extractors::client_auth::APIClientAuth;
|
||||
use crate::server::HttpResult;
|
||||
use actix_web::HttpResponse;
|
||||
use ruma::api::client::account;
|
||||
use ruma::DeviceId;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct WhoAmIResponse {
|
||||
user_id: String,
|
||||
device_id: Option<String>,
|
||||
}
|
||||
|
||||
/// Get current user identity
|
||||
pub async fn who_am_i(auth: APIClientAuth) -> HttpResult {
|
||||
let res = auth
|
||||
.send_request(account::whoami::v3::Request::default())
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(WhoAmIResponse {
|
||||
user_id: res.user_id.to_string(),
|
||||
device_id: res.device_id.as_deref().map(DeviceId::to_string),
|
||||
}))
|
||||
}
|
@ -2,6 +2,8 @@ use crate::extractors::client_auth::APIClientAuth;
|
||||
use crate::server::HttpResult;
|
||||
use actix_web::HttpResponse;
|
||||
|
||||
pub mod account;
|
||||
|
||||
/// API Home route
|
||||
pub async fn api_home(auth: APIClientAuth) -> HttpResult {
|
||||
Ok(HttpResponse::Ok().body(format!("Welcome user {}!", auth.user.user_id.0)))
|
@ -1,6 +1,7 @@
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{HttpResponse, ResponseError};
|
||||
use std::error::Error;
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub mod api;
|
||||
pub mod web_ui;
|
||||
@ -21,6 +22,10 @@ pub enum HttpFailure {
|
||||
FetchUserConfig(anyhow::Error),
|
||||
#[error("an unspecified internal error occurred: {0}")]
|
||||
InternalError(#[from] anyhow::Error),
|
||||
#[error("a matrix api client error occurred: {0}")]
|
||||
MatrixApiClientError(#[from] ruma::api::client::Error),
|
||||
#[error("a matrix client error occurred: {0}")]
|
||||
MatrixClientError(String),
|
||||
}
|
||||
|
||||
impl ResponseError for HttpFailure {
|
||||
@ -37,4 +42,4 @@ impl ResponseError for HttpFailure {
|
||||
}
|
||||
}
|
||||
|
||||
pub type HttpResult = std::result::Result<HttpResponse, HttpFailure>;
|
||||
pub type HttpResult = Result<HttpResponse, HttpFailure>;
|
||||
|
18
src/user.rs
18
src/user.rs
@ -8,10 +8,15 @@ use crate::app_config::AppConfig;
|
||||
use crate::constants::TOKEN_LEN;
|
||||
use crate::utils::{curr_time, format_time, rand_str};
|
||||
|
||||
type HttpClient = ruma::client::http_client::HyperNativeTls;
|
||||
pub type RumaClient = ruma::Client<HttpClient>;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum UserError {
|
||||
#[error("failed to fetch user configuration: {0}")]
|
||||
FetchUserConfig(S3Error),
|
||||
#[error("missing matrix token")]
|
||||
MissingMatrixToken,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||
@ -220,4 +225,17 @@ impl UserConfig {
|
||||
pub fn find_client_by_id_mut(&mut self, id: &APIClientID) -> Option<&mut APIClient> {
|
||||
self.clients.iter_mut().find(|c| &c.id == id)
|
||||
}
|
||||
|
||||
/// Get a matrix client instance for the current user
|
||||
pub async fn matrix_client(&self) -> anyhow::Result<RumaClient> {
|
||||
if self.matrix_token.is_empty() {
|
||||
return Err(UserError::MissingMatrixToken.into());
|
||||
}
|
||||
|
||||
Ok(ruma::Client::builder()
|
||||
.homeserver_url(AppConfig::get().matrix_homeserver.to_string())
|
||||
.access_token(Some(self.matrix_token.clone()))
|
||||
.build()
|
||||
.await?)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user