92 lines
2.6 KiB
Rust
92 lines
2.6 KiB
Rust
use crate::constants;
|
|
use crate::users::{User, UserEmail};
|
|
use crate::utils::rand_utils::rand_string;
|
|
use actix_session::Session;
|
|
use actix_web::dev::Payload;
|
|
use actix_web::{Error, FromRequest, HttpRequest};
|
|
use futures_util::future::{Ready, ready};
|
|
use std::net::IpAddr;
|
|
|
|
/// Matrix Gateway session errors
|
|
#[derive(thiserror::Error, Debug)]
|
|
enum MatrixGWSessionError {
|
|
#[error("Missing state!")]
|
|
OIDCMissingState,
|
|
#[error("Missing IP address!")]
|
|
OIDCMissingIP,
|
|
#[error("Invalid state!")]
|
|
OIDCInvalidState,
|
|
#[error("Invalid IP address!")]
|
|
OIDCInvalidIP,
|
|
}
|
|
|
|
/// Matrix Gateway session
|
|
///
|
|
/// Basic wrapper around actix-session extractor
|
|
pub struct MatrixGWSession(Session);
|
|
|
|
impl MatrixGWSession {
|
|
/// Generate OpenID state for this session
|
|
pub fn gen_oidc_state(&self, ip: IpAddr) -> anyhow::Result<String> {
|
|
let random_string = rand_string(50);
|
|
self.0
|
|
.insert(constants::sessions::OIDC_STATE_KEY, random_string.clone())?;
|
|
self.0.insert(constants::sessions::OIDC_REMOTE_IP, ip)?;
|
|
Ok(random_string)
|
|
}
|
|
|
|
/// Validate OpenID state
|
|
pub fn validate_state(&self, state: &str, ip: IpAddr) -> anyhow::Result<()> {
|
|
let session_state: String = self
|
|
.0
|
|
.get(constants::sessions::OIDC_STATE_KEY)?
|
|
.ok_or(MatrixGWSessionError::OIDCMissingState)?;
|
|
|
|
let session_ip: IpAddr = self
|
|
.0
|
|
.get(constants::sessions::OIDC_REMOTE_IP)?
|
|
.ok_or(MatrixGWSessionError::OIDCMissingIP)?;
|
|
|
|
if session_state != state {
|
|
return Err(anyhow::anyhow!(MatrixGWSessionError::OIDCInvalidState));
|
|
}
|
|
|
|
if session_ip != ip {
|
|
return Err(anyhow::anyhow!(MatrixGWSessionError::OIDCInvalidIP));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Set current user
|
|
pub fn set_user(&self, user: &User) -> anyhow::Result<()> {
|
|
self.0.insert(constants::sessions::USER_ID, &user.email)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Get current user
|
|
pub fn current_user(&self) -> anyhow::Result<Option<UserEmail>> {
|
|
Ok(self.0.get(constants::sessions::USER_ID)?)
|
|
}
|
|
|
|
/// Remove defined user
|
|
pub fn unset_current_user(&self) -> anyhow::Result<()> {
|
|
self.0.remove(constants::sessions::USER_ID);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl FromRequest for MatrixGWSession {
|
|
type Error = Error;
|
|
type Future = Ready<Result<Self, Error>>;
|
|
|
|
#[inline]
|
|
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
|
ready(
|
|
Session::from_request(req, &mut Payload::None)
|
|
.into_inner()
|
|
.map(MatrixGWSession),
|
|
)
|
|
}
|
|
}
|