Login screen and api endpoint reorganization
This commit is contained in:
@@ -12,7 +12,13 @@ pub mod telemetry;
|
||||
// SPDX-SnippetEnd
|
||||
pub mod diagnose;
|
||||
|
||||
use crate::management::diagnose::{DeliveryStage, spawn_delivery_diagnose};
|
||||
use crate::{
|
||||
api::diagnose::{DeliveryStage, spawn_delivery_diagnose},
|
||||
auth::{
|
||||
authenticate::Authenticator, oauth::auth::OAuthApiHandler,
|
||||
permissions::PermissionsApiHandler,
|
||||
},
|
||||
};
|
||||
use common::{
|
||||
Server,
|
||||
auth::{AccessToken, oauth::GrantType},
|
||||
@@ -31,27 +37,61 @@ use std::time::Duration;
|
||||
use utils::url_params::UrlParams;
|
||||
|
||||
pub trait ManagementApi: Sync + Send {
|
||||
fn handle_api_manage_request(
|
||||
fn handle_api_request(
|
||||
&self,
|
||||
req: &mut HttpRequest,
|
||||
access_token: &AccessToken,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
||||
|
||||
fn management_access_token(
|
||||
&self,
|
||||
req: &HttpRequest,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<AccessToken>> + Send;
|
||||
}
|
||||
|
||||
impl ManagementApi for Server {
|
||||
#[allow(unused_variables)]
|
||||
async fn handle_api_manage_request(
|
||||
async fn handle_api_request(
|
||||
&self,
|
||||
req: &mut HttpRequest,
|
||||
access_token: &AccessToken,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<HttpResponse> {
|
||||
let body = fetch_body(req, 1024 * 1024, session.session_id).await;
|
||||
let is_post = req.method() == Method::POST;
|
||||
let body = if is_post {
|
||||
fetch_body(req, 1024 * 1024, session.session_id).await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let path = req.uri().path().split('/').skip(2).collect::<Vec<_>>();
|
||||
|
||||
match path.first().copied().unwrap_or_default() {
|
||||
"auth" if is_post => {
|
||||
self.is_http_anonymous_request_allowed(session.remote_ip)
|
||||
.await?;
|
||||
self.handle_login_request(
|
||||
session,
|
||||
body.ok_or_else(|| trc::LimitEvent::SizeRequest.into_err())?,
|
||||
)
|
||||
.await
|
||||
}
|
||||
"discover" => {
|
||||
if let Some(email) = path.get(2).copied() {
|
||||
self.is_http_anonymous_request_allowed(session.remote_ip)
|
||||
.await?;
|
||||
self.handle_discover_request(req, session, decode_path_element(email).as_ref())
|
||||
.await
|
||||
} else {
|
||||
Err(trc::ResourceEvent::NotFound.into_err())
|
||||
}
|
||||
}
|
||||
"permissions" => {
|
||||
// Authenticate request
|
||||
let (_in_flight, access_token) = self.authenticate_headers(req, session).await?;
|
||||
self.handle_permissions_request(&access_token).await
|
||||
}
|
||||
"token" => {
|
||||
let access_token = self.management_access_token(req, session).await?;
|
||||
let account_id = access_token.account_id();
|
||||
match path.get(1).copied() {
|
||||
// SPDX-SnippetBegin
|
||||
@@ -98,6 +138,7 @@ impl ManagementApi for Server {
|
||||
}
|
||||
}
|
||||
"live" => {
|
||||
let access_token = self.management_access_token(req, session).await?;
|
||||
let params = UrlParams::new(req.uri().query());
|
||||
let account_id = access_token.account_id();
|
||||
|
||||
@@ -140,16 +181,16 @@ impl ManagementApi for Server {
|
||||
// SPDX-License-Identifier: LicenseRef-SEL
|
||||
#[cfg(feature = "enterprise")]
|
||||
("traces", _, &Method::GET) if self.core.is_enterprise_edition() => {
|
||||
use crate::management::telemetry::TelemetryApi;
|
||||
use crate::api::telemetry::TelemetryApi;
|
||||
|
||||
self.handle_telemetry_api_request(req, true, access_token)
|
||||
self.handle_telemetry_api_request(req, true, &access_token)
|
||||
.await
|
||||
}
|
||||
#[cfg(feature = "enterprise")]
|
||||
("metrics", _, &Method::GET) if self.core.is_enterprise_edition() => {
|
||||
use crate::management::telemetry::TelemetryApi;
|
||||
use crate::api::telemetry::TelemetryApi;
|
||||
|
||||
self.handle_telemetry_api_request(req, false, access_token)
|
||||
self.handle_telemetry_api_request(req, false, &access_token)
|
||||
.await
|
||||
}
|
||||
// SPDX-SnippetEnd
|
||||
@@ -160,10 +201,55 @@ impl ManagementApi for Server {
|
||||
_ => Err(trc::ResourceEvent::NotFound.into_err()),
|
||||
}
|
||||
}
|
||||
|
||||
_ => Err(trc::ResourceEvent::NotFound.into_err()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn management_access_token(
|
||||
&self,
|
||||
req: &HttpRequest,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<AccessToken> {
|
||||
let params = UrlParams::new(req.uri().query());
|
||||
if let Some(token) = params.get("token") {
|
||||
// SPDX-SnippetBegin
|
||||
// SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
// SPDX-License-Identifier: LicenseRef-SEL
|
||||
#[cfg(feature = "enterprise")]
|
||||
if self.core.is_enterprise_edition() {
|
||||
let path = req.uri().path();
|
||||
let (grant_type, permissions) = if path.starts_with("/api/telemetry/traces") {
|
||||
(GrantType::LiveTracing, Permission::LiveTracing)
|
||||
} else if path.starts_with("/api/telemetry/metrics") {
|
||||
(GrantType::LiveMetrics, Permission::LiveMetrics)
|
||||
} else if path.starts_with("/api/diagnose") {
|
||||
(GrantType::Diagnose, Permission::LiveDeliveryTest)
|
||||
} else {
|
||||
return Err(trc::ResourceEvent::NotFound.into_err());
|
||||
};
|
||||
self.validate_access_token(grant_type.into(), token)
|
||||
.await
|
||||
.map(|token_info| {
|
||||
AccessToken::from_permissions(token_info.account_id, [permissions])
|
||||
})
|
||||
} else {
|
||||
self.authenticate_headers(req, session)
|
||||
.await
|
||||
.map(|(_, token)| token)
|
||||
}
|
||||
// SPDX-SnippetEnd
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
{
|
||||
self.authenticate_headers(req, session)
|
||||
.await
|
||||
.map(|(_, token)| token)
|
||||
}
|
||||
} else {
|
||||
self.authenticate_headers(req, session)
|
||||
.await
|
||||
.map(|(_, token)| token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToManageHttpResponse {
|
||||
@@ -57,7 +57,7 @@ impl TelemetryApi for Server {
|
||||
for (key, value) in params.into_inner() {
|
||||
if key == "filter" {
|
||||
filter = value.into_owned().into();
|
||||
} else if let Some(key) = Key::try_parse(key.to_ascii_lowercase().as_str()) {
|
||||
} else if let Some(key) = Key::parse(key.to_ascii_lowercase().as_str()) {
|
||||
key_filters.insert(key, value.into_owned());
|
||||
}
|
||||
}
|
||||
@@ -152,8 +152,7 @@ impl TelemetryApi for Server {
|
||||
"event: trace\ndata: {}\n\n",
|
||||
serde_json::to_string(
|
||||
&JsonEventSerializer::new(std::mem::take(&mut events))
|
||||
.with_description()
|
||||
.with_explanation()).unwrap_or_default()
|
||||
.with_description()).unwrap_or_default()
|
||||
))));
|
||||
|
||||
ping_interval
|
||||
@@ -6,3 +6,4 @@
|
||||
|
||||
pub mod authenticate;
|
||||
pub mod oauth;
|
||||
pub mod permissions;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
use super::{DeviceAuthResponse, FormData, MAX_POST_LEN, OAuthCode};
|
||||
use crate::auth::oauth::OAuthStatus;
|
||||
use crate::auth::oauth::{OAuthStatus, openid::OpenIdHandler};
|
||||
use common::{
|
||||
KV_OAUTH, Server,
|
||||
auth::{
|
||||
@@ -46,22 +46,29 @@ pub struct OAuthMetadata {
|
||||
}
|
||||
|
||||
pub trait OAuthApiHandler: Sync + Send {
|
||||
fn handle_discover_request(
|
||||
&self,
|
||||
req: &HttpRequest,
|
||||
session: &HttpSessionData,
|
||||
account_name: &str,
|
||||
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
||||
|
||||
fn handle_login_request(
|
||||
&self,
|
||||
session: HttpSessionData,
|
||||
session: &HttpSessionData,
|
||||
body: Vec<u8>,
|
||||
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
||||
|
||||
fn handle_device_auth(
|
||||
&self,
|
||||
req: &mut HttpRequest,
|
||||
session: HttpSessionData,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
||||
|
||||
fn handle_oauth_metadata(
|
||||
&self,
|
||||
req: HttpRequest,
|
||||
session: HttpSessionData,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
||||
}
|
||||
|
||||
@@ -69,9 +76,6 @@ pub trait OAuthApiHandler: Sync + Send {
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum LoginRequest {
|
||||
Discovery {
|
||||
account_name: String,
|
||||
},
|
||||
AuthCode {
|
||||
account_name: String,
|
||||
account_secret: String,
|
||||
@@ -83,6 +87,14 @@ pub enum LoginRequest {
|
||||
redirect_uri: Option<String>,
|
||||
#[serde(default)]
|
||||
nonce: Option<String>,
|
||||
#[serde(default)]
|
||||
scope: Option<String>,
|
||||
#[serde(default)]
|
||||
code_challenge: Option<String>,
|
||||
#[serde(default)]
|
||||
code_challenge_method: Option<String>,
|
||||
#[serde(default)]
|
||||
state: Option<String>,
|
||||
},
|
||||
AuthDevice {
|
||||
account_name: String,
|
||||
@@ -98,8 +110,6 @@ pub enum LoginRequest {
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum LoginResponse {
|
||||
Local,
|
||||
External { endpoint: String },
|
||||
Authenticated { client_code: String },
|
||||
Verified,
|
||||
MfaRequired,
|
||||
@@ -107,9 +117,28 @@ pub enum LoginResponse {
|
||||
}
|
||||
|
||||
impl OAuthApiHandler for Server {
|
||||
async fn handle_discover_request(
|
||||
&self,
|
||||
req: &HttpRequest,
|
||||
session: &HttpSessionData,
|
||||
account_name: &str,
|
||||
) -> trc::Result<HttpResponse> {
|
||||
let account_name = account_name.trim().to_lowercase();
|
||||
if let Some(domain_name) = account_name.try_domain_part()
|
||||
&& let Some(endpoint) = self
|
||||
.get_directory_for_domain(domain_name)
|
||||
.await?
|
||||
.and_then(|directory| directory.oidc_discovery_document())
|
||||
{
|
||||
Ok(JsonResponse::new(endpoint).no_cache().into_http_response())
|
||||
} else {
|
||||
self.handle_oidc_metadata(req, session).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_login_request(
|
||||
&self,
|
||||
session: HttpSessionData,
|
||||
session: &HttpSessionData,
|
||||
body: Vec<u8>,
|
||||
) -> trc::Result<HttpResponse> {
|
||||
let request = serde_json::from_slice::<LoginRequest>(&body).map_err(|err| {
|
||||
@@ -117,22 +146,6 @@ impl OAuthApiHandler for Server {
|
||||
})?;
|
||||
|
||||
let response = match request {
|
||||
LoginRequest::Discovery { account_name } => {
|
||||
let account_name = account_name.trim().to_lowercase();
|
||||
if let Some(domain_name) = account_name.try_domain_part() {
|
||||
if let Some(endpoint) = self
|
||||
.get_directory_for_domain(domain_name)
|
||||
.await?
|
||||
.and_then(|directory| directory.oidc_authorization_endpoint())
|
||||
{
|
||||
LoginResponse::External { endpoint }
|
||||
} else {
|
||||
LoginResponse::Local
|
||||
}
|
||||
} else {
|
||||
LoginResponse::Local
|
||||
}
|
||||
}
|
||||
LoginRequest::AuthCode {
|
||||
account_name,
|
||||
account_secret,
|
||||
@@ -140,6 +153,7 @@ impl OAuthApiHandler for Server {
|
||||
client_id,
|
||||
redirect_uri,
|
||||
nonce,
|
||||
..
|
||||
} => {
|
||||
// Validate clientId
|
||||
if client_id.len() > CLIENT_ID_MAX_LEN {
|
||||
@@ -315,7 +329,7 @@ impl OAuthApiHandler for Server {
|
||||
async fn handle_device_auth(
|
||||
&self,
|
||||
req: &mut HttpRequest,
|
||||
session: HttpSessionData,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<HttpResponse> {
|
||||
// Parse form
|
||||
let mut form_data = FormData::from_request(req, MAX_POST_LEN, session.session_id).await?;
|
||||
@@ -379,10 +393,10 @@ impl OAuthApiHandler for Server {
|
||||
.await?;
|
||||
|
||||
// Build response
|
||||
let base_url = HttpContext::new(&session, req).resolve_response_url(self);
|
||||
let base_url = HttpContext::new(session, req).resolve_response_url(self);
|
||||
Ok(JsonResponse::new(DeviceAuthResponse {
|
||||
verification_uri: format!("{base_url}/authorize"),
|
||||
verification_uri_complete: format!("{base_url}/authorize/?code={user_code}"),
|
||||
verification_uri: format!("{base_url}/device"),
|
||||
verification_uri_complete: format!("{base_url}/device/?code={user_code}"),
|
||||
device_code,
|
||||
user_code,
|
||||
expires_in: self.core.oauth.oauth_expiry_user_code,
|
||||
@@ -395,12 +409,12 @@ impl OAuthApiHandler for Server {
|
||||
async fn handle_oauth_metadata(
|
||||
&self,
|
||||
req: HttpRequest,
|
||||
session: HttpSessionData,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<HttpResponse> {
|
||||
let base_url = HttpContext::new(&session, &req).resolve_response_url(self);
|
||||
let base_url = HttpContext::new(session, &req).resolve_response_url(self);
|
||||
|
||||
Ok(JsonResponse::new(OAuthMetadata {
|
||||
authorization_endpoint: format!("{base_url}/authorize/code",),
|
||||
authorization_endpoint: format!("{base_url}/login",),
|
||||
token_endpoint: format!("{base_url}/auth/token"),
|
||||
device_authorization_endpoint: format!("{base_url}/auth/device"),
|
||||
introspection_endpoint: format!("{base_url}/auth/introspect"),
|
||||
|
||||
@@ -34,8 +34,8 @@ pub trait OpenIdHandler: Sync + Send {
|
||||
|
||||
fn handle_oidc_metadata(
|
||||
&self,
|
||||
req: HttpRequest,
|
||||
session: HttpSessionData,
|
||||
req: &HttpRequest,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
||||
}
|
||||
|
||||
@@ -57,10 +57,10 @@ impl OpenIdHandler for Server {
|
||||
|
||||
async fn handle_oidc_metadata(
|
||||
&self,
|
||||
req: HttpRequest,
|
||||
session: HttpSessionData,
|
||||
req: &HttpRequest,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<HttpResponse> {
|
||||
let base_url = HttpContext::new(&session, &req).resolve_response_url(self);
|
||||
let base_url = HttpContext::new(session, req).resolve_response_url(self);
|
||||
|
||||
Ok(JsonResponse::new(OpenIdMetadata {
|
||||
authorization_endpoint: format!("{base_url}/authorize/code",),
|
||||
|
||||
47
crates/http/src/auth/permissions.rs
Normal file
47
crates/http/src/auth/permissions.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use http_proto::{HttpResponse, JsonResponse, ToHttpResponse};
|
||||
use registry::schema::enums::Permission;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Permissions {
|
||||
pub permissions: Vec<Permission>,
|
||||
#[serde(rename = "isEnterprise")]
|
||||
pub is_enterprise: bool,
|
||||
}
|
||||
|
||||
pub trait PermissionsApiHandler: Sync + Send {
|
||||
fn handle_permissions_request(
|
||||
&self,
|
||||
access_token: &AccessToken,
|
||||
) -> impl Future<Output = trc::Result<HttpResponse>> + Send;
|
||||
}
|
||||
|
||||
impl PermissionsApiHandler for Server {
|
||||
async fn handle_permissions_request(
|
||||
&self,
|
||||
access_token: &AccessToken,
|
||||
) -> trc::Result<HttpResponse> {
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
let is_enterprise = false;
|
||||
|
||||
// SPDX-SnippetBegin
|
||||
// SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
// SPDX-License-Identifier: LicenseRef-SEL
|
||||
#[cfg(feature = "enterprise")]
|
||||
let is_enterprise = self.core.is_enterprise_edition();
|
||||
// SPDX-SnippetEnd
|
||||
|
||||
Ok(JsonResponse::new(Permissions {
|
||||
permissions: access_token.permissions(),
|
||||
is_enterprise,
|
||||
})
|
||||
.into_http_response())
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,13 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
pub mod api;
|
||||
pub mod auth;
|
||||
pub mod form;
|
||||
pub mod management;
|
||||
pub mod request;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::Inner;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HttpSessionManager {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
use crate::{
|
||||
HttpSessionManager,
|
||||
api::{ManagementApi, ToManageHttpResponse},
|
||||
auth::{
|
||||
authenticate::{Authenticator, HttpHeaders},
|
||||
oauth::{
|
||||
@@ -14,11 +15,9 @@ use crate::{
|
||||
},
|
||||
},
|
||||
form::FormHandler,
|
||||
management::{ManagementApi, ToManageHttpResponse},
|
||||
};
|
||||
use common::{
|
||||
BuildServer, Inner, KV_ACME, Server,
|
||||
auth::{AccessToken, oauth::GrantType},
|
||||
ipc::PushEvent,
|
||||
manager::application::Resource,
|
||||
network::{SessionData, SessionManager, SessionStream},
|
||||
@@ -50,7 +49,6 @@ use std::{net::IpAddr, str::FromStr, sync::Arc};
|
||||
use store::dispatch::lookup::KeyValue;
|
||||
use trc::SecurityEvent;
|
||||
use types::{blob::BlobId, id::Id};
|
||||
use utils::url_params::UrlParams;
|
||||
|
||||
pub trait ParseHttp: Sync + Send {
|
||||
fn parse_http_request(
|
||||
@@ -273,14 +271,14 @@ impl ParseHttp for Server {
|
||||
self.is_http_anonymous_request_allowed(session.remote_ip)
|
||||
.await?;
|
||||
|
||||
return self.handle_oauth_metadata(req, session).await;
|
||||
return self.handle_oauth_metadata(req, &session).await;
|
||||
}
|
||||
("openid-configuration", &Method::GET) => {
|
||||
// Limit anonymous requests
|
||||
self.is_http_anonymous_request_allowed(session.remote_ip)
|
||||
.await?;
|
||||
|
||||
return self.handle_oidc_metadata(req, session).await;
|
||||
return self.handle_oidc_metadata(&req, &session).await;
|
||||
}
|
||||
("acme-challenge", &Method::GET) if self.has_acme_http_providers() => {
|
||||
if let Some(token) = path.next() {
|
||||
@@ -347,21 +345,11 @@ impl ParseHttp for Server {
|
||||
_ => (),
|
||||
},
|
||||
"auth" => match (path.next().unwrap_or_default(), req.method()) {
|
||||
("login", &Method::POST) => {
|
||||
self.is_http_anonymous_request_allowed(session.remote_ip)
|
||||
.await?;
|
||||
|
||||
let bytes = fetch_body(&mut req, 4096, session.session_id)
|
||||
.await
|
||||
.ok_or_else(|| trc::LimitEvent::SizeRequest.into_err())?;
|
||||
|
||||
return self.handle_login_request(session, bytes).await;
|
||||
}
|
||||
("device", &Method::POST) => {
|
||||
self.is_http_anonymous_request_allowed(session.remote_ip)
|
||||
.await?;
|
||||
|
||||
return self.handle_device_auth(&mut req, session).await;
|
||||
return self.handle_device_auth(&mut req, &session).await;
|
||||
}
|
||||
("token", &Method::POST) => {
|
||||
self.is_http_anonymous_request_allowed(session.remote_ip)
|
||||
@@ -410,45 +398,7 @@ impl ParseHttp for Server {
|
||||
return Ok(JsonProblemResponse(StatusCode::NO_CONTENT).into_http_response());
|
||||
}
|
||||
|
||||
let params = UrlParams::new(req.uri().query());
|
||||
let access_token = if let Some(token) = params.get("token") {
|
||||
// SPDX-SnippetBegin
|
||||
// SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
// SPDX-License-Identifier: LicenseRef-SEL
|
||||
#[cfg(feature = "enterprise")]
|
||||
if self.core.is_enterprise_edition() {
|
||||
let path = req.uri().path();
|
||||
let (grant_type, permissions) = if path.starts_with("/api/telemetry/traces")
|
||||
{
|
||||
(GrantType::LiveTracing, Permission::LiveTracing)
|
||||
} else if path.starts_with("/api/telemetry/metrics") {
|
||||
(GrantType::LiveMetrics, Permission::LiveMetrics)
|
||||
} else if path.starts_with("/api/diagnose") {
|
||||
(GrantType::Diagnose, Permission::LiveDeliveryTest)
|
||||
} else {
|
||||
return Err(trc::ResourceEvent::NotFound.into_err());
|
||||
};
|
||||
AccessToken::from_permissions(
|
||||
self.validate_access_token(grant_type.into(), token)
|
||||
.await?
|
||||
.account_id,
|
||||
[permissions],
|
||||
)
|
||||
} else {
|
||||
self.authenticate_headers(&req, &session).await?.1
|
||||
}
|
||||
// SPDX-SnippetEnd
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
{
|
||||
self.authenticate_headers(&req, &session).await?.1
|
||||
}
|
||||
} else {
|
||||
self.authenticate_headers(&req, &session).await?.1
|
||||
};
|
||||
|
||||
return self
|
||||
.handle_api_manage_request(&mut req, &access_token, &session)
|
||||
.await;
|
||||
return self.handle_api_request(&mut req, &session).await;
|
||||
}
|
||||
"mail" => {
|
||||
if req.method() == Method::GET
|
||||
@@ -593,7 +543,7 @@ impl ParseHttp for Server {
|
||||
// SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
// SPDX-License-Identifier: LicenseRef-SEL
|
||||
#[cfg(feature = "enterprise")]
|
||||
"logo.svg" if self.is_enterprise_edition() => {
|
||||
"logo" if self.is_enterprise_edition() => {
|
||||
match self
|
||||
.logo_resource(
|
||||
req.headers()
|
||||
@@ -607,17 +557,13 @@ impl ParseHttp for Server {
|
||||
Ok(Some(resource)) => {
|
||||
return Ok(resource.into_http_response());
|
||||
}
|
||||
Ok(None) => (),
|
||||
Ok(None) => {
|
||||
return Err(trc::ResourceEvent::NotFound.into_err());
|
||||
}
|
||||
Err(err) => {
|
||||
trc::error!(err.span_id(session.session_id));
|
||||
}
|
||||
}
|
||||
|
||||
let resource = self.inner.data.applications.get("logo.svg").await?;
|
||||
|
||||
if !resource.is_empty() {
|
||||
return Ok(resource.into_http_response());
|
||||
}
|
||||
}
|
||||
// SPDX-SnippetEnd
|
||||
"form" => {
|
||||
@@ -642,6 +588,14 @@ impl ParseHttp for Server {
|
||||
}
|
||||
}
|
||||
}
|
||||
"login" | "device" => {
|
||||
let page = include_str!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/../../resources/html-templates/login.html.min"
|
||||
));
|
||||
|
||||
return Ok(HtmlResponse::new(page.to_string()).into_http_response());
|
||||
}
|
||||
_ => {
|
||||
let path = req.uri().path();
|
||||
let resource = self
|
||||
|
||||
Reference in New Issue
Block a user