diff --git a/Cargo.lock b/Cargo.lock index 93a3ddd76..c9898de72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2439,6 +2439,7 @@ dependencies = [ "kanidmd_lib", "oauth2", "reqwest", + "serde", "serde_json", "sketching", "testkit-macros", diff --git a/libs/client/src/lib.rs b/libs/client/src/lib.rs index 1ceec9307..d9a393778 100644 --- a/libs/client/src/lib.rs +++ b/libs/client/src/lib.rs @@ -24,6 +24,7 @@ use std::os::unix::fs::MetadataExt; use std::path::Path; use std::time::Duration; +use kanidm_proto::constants::APPLICATION_JSON; use kanidm_proto::v1::*; use reqwest::header::CONTENT_TYPE; pub use reqwest::StatusCode; @@ -44,7 +45,6 @@ mod service_account; mod sync_account; mod system; -pub const APPLICATION_JSON: &str = "application/json"; pub const KOPID: &str = "X-KANIDM-OPID"; pub const KSESSIONID: &str = "X-KANIDM-AUTH-SESSION-ID"; @@ -621,7 +621,7 @@ impl KanidmClient { .map_err(|e| ClientError::JsonDecode(e, opid)) } - async fn perform_post_request( + pub async fn perform_post_request( &self, dest: &str, request: R, diff --git a/proto/src/constants.rs b/proto/src/constants.rs index 2a24239a5..46859351d 100644 --- a/proto/src/constants.rs +++ b/proto/src/constants.rs @@ -1,5 +1,7 @@ /// Because consistency is great! +pub const APPLICATION_JSON: &str = "application/json"; + /// The "system" path for Kanidm client config pub const DEFAULT_CLIENT_CONFIG_PATH: &str = "/etc/kanidm/config"; /// The user-owned path for Kanidm client config diff --git a/proto/src/oauth2.rs b/proto/src/oauth2.rs index 5410ef333..f528522ff 100644 --- a/proto/src/oauth2.rs +++ b/proto/src/oauth2.rs @@ -341,7 +341,7 @@ pub struct OidcDiscoveryResponse { } #[skip_serializing_none] -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] pub struct ErrorResponse { pub error: String, pub error_description: Option, diff --git a/proto/src/v1.rs b/proto/src/v1.rs index f99318c96..d771668d6 100644 --- a/proto/src/v1.rs +++ b/proto/src/v1.rs @@ -611,8 +611,12 @@ impl fmt::Display for UnixUserToken { } #[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(deny_unknown_fields)] pub struct AccountUnixExtend { pub gidnumber: Option, + // TODO: rename shell to loginshell everywhere we can find + /// The internal attribute is "loginshell" but we use shell in the API currently + #[serde(alias = "loginshell")] pub shell: Option, } diff --git a/server/core/src/https/manifest.rs b/server/core/src/https/manifest.rs index ee01f7555..f5110b7d5 100644 --- a/server/core/src/https/manifest.rs +++ b/server/core/src/https/manifest.rs @@ -3,6 +3,7 @@ use axum::extract::State; use axum::response::{IntoResponse, Response}; use axum::Extension; +use http::header::CONTENT_TYPE; use http::HeaderValue; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -163,7 +164,7 @@ pub(crate) async fn manifest( let mut res = Response::new(manifest_string); res.headers_mut() - .insert("Content-Type", HeaderValue::from_static(MIME_TYPE_MANIFEST)); + .insert(CONTENT_TYPE, HeaderValue::from_static(MIME_TYPE_MANIFEST)); res } diff --git a/server/core/src/https/middleware/hsts_header.rs b/server/core/src/https/middleware/hsts_header.rs index 12f1f7e06..0ac101591 100644 --- a/server/core/src/https/middleware/hsts_header.rs +++ b/server/core/src/https/middleware/hsts_header.rs @@ -10,10 +10,10 @@ pub async fn strict_transport_security_layer(request: Request, next: Next< let mut response = next.run(request).await; // add the header - let headers = response.headers_mut(); - let hsts_header = HeaderValue::from_static(HSTS_HEADER); - - headers.insert(http::header::STRICT_TRANSPORT_SECURITY, hsts_header); + response.headers_mut().insert( + http::header::STRICT_TRANSPORT_SECURITY, + HeaderValue::from_static(HSTS_HEADER), + ); response } diff --git a/server/core/src/https/middleware/mod.rs b/server/core/src/https/middleware/mod.rs index 227caac64..f82d95baf 100644 --- a/server/core/src/https/middleware/mod.rs +++ b/server/core/src/https/middleware/mod.rs @@ -5,6 +5,8 @@ use axum::{ response::Response, TypedHeader, }; +#[cfg(debug_assertions)] +use http::header::CONTENT_TYPE; use http::HeaderValue; use uuid::Uuid; @@ -19,8 +21,9 @@ const KANIDM_VERSION: &str = env!("CARGO_PKG_VERSION"); /// Injects a header into the response with "X-KANIDM-VERSION" matching the version of the package. pub async fn version_middleware(request: Request, next: Next) -> Response { let mut response = next.run(request).await; - let headers = response.headers_mut(); - headers.insert("X-KANIDM-VERSION", HeaderValue::from_static(KANIDM_VERSION)); + response + .headers_mut() + .insert("X-KANIDM-VERSION", HeaderValue::from_static(KANIDM_VERSION)); response } @@ -31,6 +34,41 @@ pub struct KOpId { pub uat: Option, } +/// Ensure the status code is 200..=299 +#[cfg(debug_assertions)] +fn from_200_to_299(status: http::StatusCode) -> bool { + status.as_u16() >= 200 && status.as_u16() <= 299 +} + +#[test] +fn test_from_200_to_299() { + assert!(from_200_to_299(http::StatusCode::OK)); + assert!(from_200_to_299(http::StatusCode::IM_USED)); + assert!(!from_200_to_299(http::StatusCode::BAD_REQUEST)); + assert!(!from_200_to_299(http::StatusCode::INTERNAL_SERVER_ERROR)); +} + +#[cfg(debug_assertions)] +/// This is a debug middleware to ensure that /v1/ endpoints only return JSON +#[instrument(name = "are_we_json_yet", skip_all)] +pub async fn are_we_json_yet(request: Request, next: Next) -> Response { + let uri = request.uri().path().to_string(); + + let response = next.run(request).await; + + if uri.starts_with("/v1") && from_200_to_299(response.status()) { + let headers = response.headers(); + assert!(headers.contains_key(CONTENT_TYPE)); + dbg!(headers.get(CONTENT_TYPE)); + assert!( + headers.get(CONTENT_TYPE) + == Some(&HeaderValue::from_static(crate::https::APPLICATION_JSON)) + ); + } + + response +} + /// This runs at the start of the request, adding an extension with `KOpId` which has useful things inside it. #[instrument(name = "request", skip_all)] pub async fn kopid_middleware( diff --git a/server/core/src/https/middleware/security_headers.rs b/server/core/src/https/middleware/security_headers.rs index bec908962..88d244d1a 100644 --- a/server/core/src/https/middleware/security_headers.rs +++ b/server/core/src/https/middleware/security_headers.rs @@ -26,32 +26,26 @@ pub async fn security_headers_layer( // // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options // https://scotthelme.co.uk/hardening-your-http-response-headers/#x-content-type-options - #[allow(clippy::expect_used)] headers.insert( X_CONTENT_TYPE_OPTIONS, - HeaderValue::from_str(X_CONTENT_TYPE_OPTIONS_VALUE) - .expect("Failed to generate security header X-Content-Type-Options"), + HeaderValue::from_static(X_CONTENT_TYPE_OPTIONS_VALUE), ); // Permissions policy defines access to platform services like geolocation, fullscreen etc. // // https://www.w3.org/TR/permissions-policy-1/ - #[allow(clippy::expect_used)] headers.insert( "Permissions-Policy", - HeaderValue::from_str(PERMISSIONS_POLICY_VALUE) - .expect("Failed to generate security header Permissions-Policy"), + HeaderValue::from_static(PERMISSIONS_POLICY_VALUE), ); // Don't send a referrer header when the user is navigating to a non-HTTPS URL // Ref: // https://scotthelme.co.uk/a-new-security-header-referrer-policy/ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - #[allow(clippy::expect_used)] headers.insert( http::header::REFERRER_POLICY, - HeaderValue::from_str("no-referrer-when-downgrade") - .expect("Failed to generate Referer-Policy header"), + HeaderValue::from_static("no-referrer-when-downgrade"), ); response diff --git a/server/core/src/https/mod.rs b/server/core/src/https/mod.rs index 86a1e561d..50219d142 100644 --- a/server/core/src/https/mod.rs +++ b/server/core/src/https/mod.rs @@ -14,21 +14,24 @@ use crate::actors::v1_write::QueryServerWriteV1; use crate::config::{Configuration, ServerRole, TlsConfiguration}; use axum::extract::connect_info::{IntoMakeServiceWithConnectInfo, ResponseFuture}; use axum::middleware::{from_fn, from_fn_with_state}; -use axum::response::{Redirect, Response}; +use axum::response::{IntoResponse, Redirect, Response}; use axum::routing::*; use axum::Router; use axum_csp::{CspDirectiveType, CspValue}; use axum_macros::FromRef; use compact_jwt::{Jws, JwsSigner, JwsUnverified}; use generic::*; -use http::{HeaderMap, HeaderValue}; +use http::header::{ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE}; +use http::{HeaderMap, HeaderValue, StatusCode}; use hyper::server::accept::Accept; use hyper::server::conn::{AddrStream, Http}; use hyper::Body; use javascript::*; +use kanidm_proto::constants::APPLICATION_JSON; use kanidm_proto::v1::OperationError; use kanidmd_lib::status::StatusActor; use openssl::ssl::{Ssl, SslAcceptor, SslFiletype, SslMethod}; +use sketching::*; use tokio_openssl::SslStream; use futures_util::future::poll_fn; @@ -247,7 +250,13 @@ pub async fn create_https_server( // This is because the last middleware here is the first to be entered and the last // to be exited, and this middleware sets up ids' and other bits for for logging // coherence to be maintained. - .layer(from_fn(middleware::kopid_middleware)) + .layer(from_fn(middleware::kopid_middleware)); + + // layer which checks the responses have a content-type of JSON when we're in debug mode + #[cfg(debug_assertions)] + let app = app.layer(from_fn(middleware::are_we_json_yet)); + + let app = app .with_state(state) // the connect_info bit here lets us pick up the remote address of the client .into_make_service_with_connect_info::(); @@ -369,8 +378,8 @@ async fn handle_conn( std::io::Error::from(ErrorKind::ConnectionAborted) }) } - Err(_error) => { - // trace!("Failed to handle connection: {:?}", error); + Err(error) => { + trace!("Failed to handle connection: {:?}", error); Ok(()) } } @@ -393,7 +402,10 @@ pub fn to_axum_response( }; trace!("Response Body: {:?}", body); #[allow(clippy::unwrap_used)] - Response::builder().body(Body::from(body)).unwrap() + Response::builder() + .header(CONTENT_TYPE, APPLICATION_JSON) + .body(Body::from(body)) + .unwrap() } Err(e) => { debug!("OperationError: {:?}", e); @@ -430,3 +442,27 @@ pub fn to_axum_response( } } } + +/// Wrapper for the externally-defined error type from the protocol +pub struct HttpOperationError(OperationError); + +impl IntoResponse for HttpOperationError { + fn into_response(self) -> Response { + let HttpOperationError(error) = self; + + let body = match serde_json::to_string(&error) { + Ok(val) => val, + Err(e) => { + admin_warn!("Failed to serialize error response: original_error=\"{:?}\" serialization_error=\"{:?}\"", error , e); + format!("{:?}", error) + } + }; + #[allow(clippy::unwrap_used)] + Response::builder() + .status(StatusCode::BAD_REQUEST) + .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .body(Body::from(body)) + .unwrap() + .into_response() + } +} diff --git a/server/core/src/https/oauth2.rs b/server/core/src/https/oauth2.rs index 745ae41da..b543049bf 100644 --- a/server/core/src/https/oauth2.rs +++ b/server/core/src/https/oauth2.rs @@ -1,17 +1,20 @@ use super::middleware::KOpId; use super::v1::{json_rest_event_get, json_rest_event_post}; -use super::{to_axum_response, ServerState}; +use super::{to_axum_response, HttpOperationError, ServerState}; use axum::extract::{Path, Query, State}; use axum::middleware::from_fn; use axum::response::{IntoResponse, Response}; use axum::routing::{get, post}; use axum::{Extension, Form, Json, Router}; +use axum_macros::debug_handler; use http::header::{ - ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, AUTHORIZATION, LOCATION, + ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, AUTHORIZATION, CONTENT_TYPE, + LOCATION, WWW_AUTHENTICATE, }; use http::{HeaderMap, HeaderValue, StatusCode}; use hyper::Body; -use kanidm_proto::oauth2::AuthorisationResponse; +use kanidm_proto::constants::APPLICATION_JSON; +use kanidm_proto::oauth2::{AuthorisationResponse, OidcDiscoveryResponse}; use kanidm_proto::v1::Entry as ProtoEntry; use kanidmd_lib::idm::oauth2::{ AccessTokenIntrospectRequest, AccessTokenRequest, AuthorisationRequest, AuthorisePermitSuccess, @@ -22,6 +25,45 @@ use kanidmd_lib::prelude::*; use kanidmd_lib::value::PartialValue; use serde::{Deserialize, Serialize}; +pub struct HTTPOauth2Error(Oauth2Error); + +impl IntoResponse for HTTPOauth2Error { + fn into_response(self) -> Response { + let HTTPOauth2Error(error) = self; + + if let Oauth2Error::AuthenticationRequired = error { + #[allow(clippy::unwrap_used)] + Response::builder() + .status(StatusCode::UNAUTHORIZED) + .header(WWW_AUTHENTICATE, "Bearer") + .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .body(Body::empty()) + .unwrap() + } else { + let err = ErrorResponse { + error: error.to_string(), + ..Default::default() + }; + + let body = match serde_json::to_string(&err) { + Ok(val) => val, + Err(e) => { + admin_warn!("Failed to serialize error response: original_error=\"{:?}\" serialization_error=\"{:?}\"", err, e); + format!("{:?}", err) + } + }; + #[allow(clippy::unwrap_used)] + Response::builder() + .status(StatusCode::BAD_REQUEST) + .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .body(Body::from(body)) + .unwrap() + + } + .into_response() + } +} + // == Oauth2 Configuration Endpoints == /// List all the OAuth2 Resource Servers @@ -73,7 +115,7 @@ pub async fn oauth2_id_get( State(state): State, Path(rs_name): Path, Extension(kopid): Extension, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state @@ -89,7 +131,7 @@ pub async fn oauth2_id_get_basic_secret( State(state): State, Extension(kopid): Extension, Path(rs_name): Path, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state .qe_r_ref @@ -103,7 +145,7 @@ pub async fn oauth2_id_patch( Path(rs_name): Path, Extension(kopid): Extension, Json(obj): Json, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state @@ -118,7 +160,7 @@ pub async fn oauth2_id_scopemap_post( Extension(kopid): Extension, Path((rs_name, group)): Path<(String, String)>, Json(scopes): Json>, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state .qe_w_ref @@ -131,7 +173,7 @@ pub async fn oauth2_id_scopemap_delete( State(state): State, Extension(kopid): Extension, Path((rs_name, group)): Path<(String, String)>, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state .qe_w_ref @@ -145,7 +187,7 @@ pub async fn oauth2_id_sup_scopemap_post( Extension(kopid): Extension, Path((rs_name, group)): Path<(String, String)>, Json(scopes): Json>, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state .qe_w_ref @@ -158,7 +200,7 @@ pub async fn oauth2_id_sup_scopemap_delete( State(state): State, Extension(kopid): Extension, Path((rs_name, group)): Path<(String, String)>, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state .qe_w_ref @@ -171,7 +213,7 @@ pub async fn oauth2_id_delete( State(state): State, Extension(kopid): Extension, Path(rs_name): Path, -) -> impl IntoResponse { +) -> Response { let filter = oauth2_id(&rs_name); let res = state .qe_w_ref @@ -337,7 +379,7 @@ async fn oauth2_authorise( #[allow(clippy::unwrap_used)] Response::builder() .status(StatusCode::UNAUTHORIZED) - .header("WWW-Authenticate", HeaderValue::from_str("Bearer").unwrap()) + .header(WWW_AUTHENTICATE, HeaderValue::from_static("Bearer")) .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") .body(Body::empty()) .unwrap() @@ -432,9 +474,9 @@ async fn oauth2_authorise_permit( #[allow(clippy::unwrap_used)] Response::builder() .status(StatusCode::FOUND) - .header("Location", redirect_uri.as_str()) + .header(LOCATION, redirect_uri.as_str()) .header( - "Access-Control-Allow-Origin", + ACCESS_CONTROL_ALLOW_ORIGIN, redirect_uri.origin().ascii_serialization(), ) .body(Body::empty()) @@ -464,7 +506,7 @@ pub async fn oauth2_authorise_reject_post( State(state): State, Extension(kopid): Extension, Form(consent_req): Form, -) -> impl IntoResponse { +) -> Response { oauth2_authorise_reject(state, consent_req.token, kopid).await } @@ -472,7 +514,7 @@ pub async fn oauth2_authorise_reject_get( State(state): State, Extension(kopid): Extension, Query(consent_req): Query, -) -> impl IntoResponse { +) -> Response { oauth2_authorise_reject(state, consent_req.token, kopid).await } @@ -483,7 +525,7 @@ async fn oauth2_authorise_reject( state: ServerState, consent_req: String, kopid: KOpId, -) -> impl IntoResponse { +) -> Response { // Need to go back to the redir_uri // For this, we'll need to lookup where to go. @@ -525,12 +567,14 @@ async fn oauth2_authorise_reject( } } +#[axum_macros::debug_handler] +#[instrument(skip(state, kopid, headers), level = "DEBUG")] pub async fn oauth2_token_post( State(state): State, Extension(kopid): Extension, - headers: HeaderMap, // TODO: make this a typed basic auth header + headers: HeaderMap, Form(tok_req): Form, -) -> impl IntoResponse { +) -> Result, HTTPOauth2Error> { // This is called directly by the resource server, where we then issue // the token to the caller. @@ -545,53 +589,13 @@ pub async fn oauth2_token_post( // grant? Should we cease the delayed/async session update here and just opt // for a wr txn? - let res = state + match state .qe_w_ref .handle_oauth2_token_exchange(client_authz, tok_req, kopid.eventid) - .await; - - match res { - Ok(atr) => - { - #[allow(clippy::unwrap_used)] - Response::builder() - .status(StatusCode::OK) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from(serde_json::to_string(&atr).unwrap())) - .unwrap() - } - Err(Oauth2Error::AuthenticationRequired) => - { - #[allow(clippy::unwrap_used)] - Response::builder() - .status(StatusCode::UNAUTHORIZED) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::empty()) - .unwrap() - } - Err(e) => { - // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 - let err = ErrorResponse { - error: e.to_string(), - error_description: None, - error_uri: None, - }; - - let body = match serde_json::to_string(&err) { - Ok(val) => val, - Err(e) => { - admin_warn!("Failed to serialize error response: original_error=\"{:?}\" serialization_error=\"{:?}\"", err, e); - format!("{:?}", err) - } - }; - - #[allow(clippy::unwrap_used)] - Response::builder() - .status(StatusCode::BAD_REQUEST) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from(body)) - .unwrap() - } + .await + { + Ok(tok_res) => Ok(Json(tok_res)), + Err(e) => Err(HTTPOauth2Error(e)), } } @@ -600,7 +604,7 @@ pub async fn oauth2_openid_discovery_get( State(state): State, Path(client_id): Path, Extension(kopid): Extension, -) -> impl IntoResponse { +) -> Result, HttpOperationError> { // let client_id = req.get_url_param("client_id")?; let res = state @@ -609,51 +613,26 @@ pub async fn oauth2_openid_discovery_get( .await; match res { - Ok(dsc) => { - // Humans may look at this so we pretty it. - #[allow(clippy::unwrap_used)] - let body = serde_json::to_string_pretty(&dsc).unwrap(); - #[allow(clippy::unwrap_used)] - Response::builder() - .status(StatusCode::OK) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from(body)) - .unwrap() - } + Ok(dsc) => Ok(Json(dsc)), Err(e) => { error!(err = ?e, "Unable to access discovery info"); - let body = match serde_json::to_string(&e) { - Ok(val) => val, - Err(e) => { - format!("{:?}", e) - } - }; - #[allow(clippy::unwrap_used)] - Response::builder() - .status(StatusCode::BAD_REQUEST) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from(body)) - .unwrap() + Err(HttpOperationError(e)) } } } +#[debug_handler] pub async fn oauth2_openid_userinfo_get( State(state): State, Path(client_id): Path, Extension(kopid): Extension, -) -> Response { +) -> impl IntoResponse { // The token we want to inspect is in the authorisation header. let client_token = match kopid.uat { Some(val) => val, None => { error!("Bearer Authentication Not Provided"); - #[allow(clippy::unwrap_used)] - return Response::builder() - .status(StatusCode::UNAUTHORIZED) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from("Invalid Bearer Authorisation")) - .unwrap(); + return Err(HTTPOauth2Error(Oauth2Error::AuthenticationRequired)); } }; @@ -663,36 +642,8 @@ pub async fn oauth2_openid_userinfo_get( .await; match res { - Ok(uir) => { - #[allow(clippy::unwrap_used)] - let body = serde_json::to_string(&uir).unwrap(); - #[allow(clippy::unwrap_used)] - Response::builder() - .status(StatusCode::OK) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from(body)) - .unwrap() - } - Err(e) => { - let err = ErrorResponse { - error: e.to_string(), - error_description: None, - error_uri: None, - }; - let body = match serde_json::to_string(&err) { - Ok(val) => val, - Err(e) => { - format!("{:?}", e) - } - }; - #[allow(clippy::unwrap_used)] - Response::builder() - .status(StatusCode::BAD_REQUEST) - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from(body)) - .unwrap() - // https://datatracker.ietf.org/doc/html/rfc6750#section-6.2 - } + Ok(uir) => Ok(Json(uir)), + Err(e) => Err(HTTPOauth2Error(e)), } } @@ -700,12 +651,13 @@ pub async fn oauth2_openid_publickey_get( State(state): State, Path(client_id): Path, Extension(kopid): Extension, -) -> impl IntoResponse { - let res = state - .qe_r_ref - .handle_oauth2_openid_publickey(client_id, kopid.eventid) - .await; - to_axum_response(res) +) -> Response { + to_axum_response( + state + .qe_r_ref + .handle_oauth2_openid_publickey(client_id, kopid.eventid) + .await, + ) } /// This is called directly by the resource server, where we then issue @@ -760,6 +712,7 @@ pub async fn oauth2_token_introspect_post( #[allow(clippy::unwrap_used)] Response::builder() .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .header(CONTENT_TYPE, APPLICATION_JSON) .body(Body::from(body)) .unwrap() } @@ -776,8 +729,7 @@ pub async fn oauth2_token_introspect_post( // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 let err = ErrorResponse { error: e.to_string(), - error_description: None, - error_uri: None, + ..Default::default() }; let body = match serde_json::to_string(&err) { @@ -847,21 +799,22 @@ pub async fn oauth2_token_revoke_post( // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 let err = ErrorResponse { error: e.to_string(), - error_description: None, - error_uri: None, + ..Default::default() }; #[allow(clippy::unwrap_used)] Response::builder() .status(StatusCode::BAD_REQUEST) .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .body(Body::from(serde_json::to_string(&err).unwrap())) + .body(Body::from( + serde_json::to_string(&err).unwrap_or("".to_string()), + )) .unwrap() } } } // Some requests from browsers require preflight so that CORS works. -pub async fn oauth2_preflight_options() -> impl IntoResponse { +pub async fn oauth2_preflight_options() -> Response { #[allow(clippy::unwrap_used)] Response::builder() .status(StatusCode::OK) diff --git a/server/core/src/https/ui.rs b/server/core/src/https/ui.rs index c56bc1202..b30b49f19 100644 --- a/server/core/src/https/ui.rs +++ b/server/core/src/https/ui.rs @@ -2,6 +2,7 @@ use axum::extract::State; use axum::http::HeaderValue; use axum::response::Response; use axum::Extension; +use http::header::CONTENT_TYPE; use super::middleware::KOpId; use super::ServerState; @@ -58,7 +59,7 @@ pub async fn ui_handler( let mut res = Response::new(body); res.headers_mut().insert( - "Content-Type", + CONTENT_TYPE, HeaderValue::from_static("text/html;charset=utf-8"), ); res diff --git a/server/core/src/https/v1.rs b/server/core/src/https/v1.rs index e987cd8a6..aafb489e7 100644 --- a/server/core/src/https/v1.rs +++ b/server/core/src/https/v1.rs @@ -892,6 +892,7 @@ pub async fn account_get_id_radius_token( res } +/// Expects an `AccountUnixExtend` object pub async fn account_post_id_unix( State(state): State, Path(id): Path, @@ -1403,27 +1404,26 @@ pub fn router(state: ServerState) -> Router { ) .route( "/v1/schema/classtype/:id", - get(schema_classtype_get_id) - .put(|| async { "TODO" }) - .patch(|| async { "TODO" }), + get(schema_classtype_get_id), // .put(|| async { "TODO" }) + // .patch(|| async { "TODO" }), ) .route("/v1/self", get(whoami)) .route("/v1/self/_uat", get(whoami_uat)) - .route("/v1/self/_attr/:attr", get(|| async { "TODO" })) - .route("/v1/self/_credential", get(|| async { "TODO" })) - .route("/v1/self/_credential/:cid/_lock", get(|| async { "TODO" })) - .route( - "/v1/self/_radius", - get(|| async { "TODO" }) - .delete(|| async { "TODO" }) - .post(|| async { "TODO" }), - ) - .route("/v1/self/_radius/_config", post(|| async { "TODO" })) - .route("/v1/self/_radius/_config/:token", get(|| async { "TODO" })) - .route( - "/v1/self/_radius/_config/:token/apple", - get(|| async { "TODO" }), - ) + // .route("/v1/self/_attr/:attr", get(|| async { "TODO" })) + // .route("/v1/self/_credential", get(|| async { "TODO" })) + // .route("/v1/self/_credential/:cid/_lock", get(|| async { "TODO" })) + // .route( + // "/v1/self/_radius", + // get(|| async { "TODO" }) + // .delete(|| async { "TODO" }) + // .post(|| async { "TODO" }), + // ) + // .route("/v1/self/_radius/_config", post(|| async { "TODO" })) + // .route("/v1/self/_radius/_config/:token", get(|| async { "TODO" })) + // .route( + // "/v1/self/_radius/_config/:token/apple", + // get(|| async { "TODO" }), + // ) // Applinks are the list of apps this account can access. .route("/v1/self/_applinks", get(applinks_get)) // Person routes @@ -1442,16 +1442,16 @@ pub fn router(state: ServerState) -> Router { .post(account_id_post_attr) .delete(account_id_delete_attr), ) - .route("/v1/person/:id/_lock", get(|| async { "TODO" })) - .route("/v1/person/:id/_credential", get(|| async { "TODO" })) + // .route("/v1/person/:id/_lock", get(|| async { "TODO" })) + // .route("/v1/person/:id/_credential", get(|| async { "TODO" })) .route( "/v1/person/:id/_credential/_status", get(account_get_id_credential_status), ) - .route( - "/v1/person/:id/_credential/:cid/_lock", - get(|| async { "TODO" }), - ) + // .route( + // "/v1/person/:id/_credential/:cid/_lock", + // get(|| async { "TODO" }), + // ) .route( "/v1/person/:id/_credential/_update", get(account_get_id_credential_update), @@ -1481,7 +1481,7 @@ pub fn router(state: ServerState) -> Router { .route( "/v1/person/:id/_radius/_token", get(account_get_id_radius_token), - ) // TODO: make this cacheable + ) // TODO: make radius token cacheable .route("/v1/person/:id/_unix", post(account_post_id_unix)) .route( "/v1/person/:id/_unix/_credential", @@ -1507,7 +1507,7 @@ pub fn router(state: ServerState) -> Router { .post(account_id_post_attr) .delete(account_id_delete_attr), ) - .route("/v1/service_account/:id/_lock", get(|| async { "TODO" })) + // .route("/v1/service_account/:id/_lock", get(|| async { "TODO" })) .route( "/v1/service_account/:id/_into_person", post(service_account_into_person), @@ -1520,10 +1520,10 @@ pub fn router(state: ServerState) -> Router { "/v1/service_account/:id/_api_token/:token_id", delete(service_account_api_token_delete), ) - .route( - "/v1/service_account/:id/_credential", - get(|| async { "TODO" }), - ) + // .route( + // "/v1/service_account/:id/_credential", + // get(|| async { "TODO" }), + // ) .route( "/v1/service_account/:id/_credential/_generate", get(service_account_credential_generate), @@ -1532,10 +1532,10 @@ pub fn router(state: ServerState) -> Router { "/v1/service_account/:id/_credential/_status", get(account_get_id_credential_status), ) - .route( - "/v1/service_account/:id/_credential/:cid/_lock", - get(|| async { "TODO" }), - ) + // .route( + // "/v1/service_account/:id/_credential/:cid/_lock", + // get(|| async { "TODO" }), + // ) .route( "/v1/service_account/:id/_ssh_pubkeys", get(account_get_id_ssh_pubkeys).post(account_post_id_ssh_pubkey), @@ -1614,12 +1614,12 @@ pub fn router(state: ServerState) -> Router { "/v1/recycle_bin/:id/_revive", post(recycle_bin_revive_id_post), ) - .route("/v1/access_profile", get(|| async { "TODO" })) - .route("/v1/access_profile/:id", get(|| async { "TODO" })) - .route( - "/v1/access_profile/:id/_attr/:attr", - get(|| async { "TODO" }), - ) + // .route("/v1/access_profile", get(|| async { "TODO" })) + // .route("/v1/access_profile/:id", get(|| async { "TODO" })) + // .route( + // "/v1/access_profile/:id/_attr/:attr", + // get(|| async { "TODO" }), + // ) .route("/v1/auth", post(auth)) .route("/v1/auth/valid", get(auth_valid)) .route("/v1/logout", get(logout)) diff --git a/server/testkit/Cargo.toml b/server/testkit/Cargo.toml index a4d9a8503..9a1dff194 100644 --- a/server/testkit/Cargo.toml +++ b/server/testkit/Cargo.toml @@ -28,12 +28,12 @@ kanidmd_lib = { workspace = true } # used for webdriver testing hyper-tls = { workspace = true } # used for webdriver testing -fantoccini = { version="0.19.3", optional=true} - +fantoccini = { version = "0.19.3", optional = true } +serde = { workspace = true } url = { workspace = true, features = ["serde"] } -reqwest = { workspace = true, default-features = false, features=["cookies"] } +reqwest = { workspace = true, default-features = false, features = ["cookies"] } sketching = { workspace = true } testkit-macros = { workspace = true } tracing = { workspace = true, features = ["attributes"] } diff --git a/server/testkit/tests/default_entries.rs b/server/testkit/tests/default_entries.rs index 69ffa773d..92327327c 100644 --- a/server/testkit/tests/default_entries.rs +++ b/server/testkit/tests/default_entries.rs @@ -2,8 +2,9 @@ use std::collections::HashSet; use kanidm_client::KanidmClient; - +use kanidm_proto::constants::APPLICATION_JSON; use kanidmd_testkit::*; +use reqwest::header::CONTENT_TYPE; static USER_READABLE_ATTRS: [&str; 9] = [ "name", @@ -607,7 +608,7 @@ async fn test_v1_raw_delete(rsclient: KanidmClient) { let response = match client .post(format!("{}/v1/raw/delete", &addr)) - .header("Content-Type", "application/json") + .header(CONTENT_TYPE, APPLICATION_JSON) .body(post_body) .send() .await diff --git a/server/testkit/tests/oauth2_test.rs b/server/testkit/tests/oauth2_test.rs index 7307e9e47..e8a32dabc 100644 --- a/server/testkit/tests/oauth2_test.rs +++ b/server/testkit/tests/oauth2_test.rs @@ -4,11 +4,13 @@ use std::convert::TryFrom; use std::str::FromStr; use compact_jwt::{JwkKeySet, JwsValidator, OidcToken, OidcUnverified}; +use kanidm_proto::constants::APPLICATION_JSON; use kanidm_proto::oauth2::{ AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest, AccessTokenResponse, AuthorisationResponse, GrantTypeReq, OidcDiscoveryResponse, }; use oauth2_ext::PkceCodeChallenge; +use reqwest::header::{HeaderValue, CONTENT_TYPE}; use reqwest::StatusCode; use url::Url; @@ -318,6 +320,9 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) { .expect("Failed to send code exchange request."); assert!(response.status() == reqwest::StatusCode::OK); + assert!( + response.headers().get(CONTENT_TYPE) == Some(&HeaderValue::from_static(APPLICATION_JSON)) + ); assert_no_cache!(response); // The body is a json AccessTokenResponse @@ -342,6 +347,10 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) { .expect("Failed to send token introspect request."); assert!(response.status() == reqwest::StatusCode::OK); + dbg!(response.headers()); + assert!( + response.headers().get(CONTENT_TYPE) == Some(&HeaderValue::from_static(APPLICATION_JSON)) + ); assert_no_cache!(response); let tir = response @@ -384,6 +393,10 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) { .await .expect("Failed to send userinfo request."); + dbg!(response.headers()); + assert!( + response.headers().get(CONTENT_TYPE) == Some(&HeaderValue::from_static(APPLICATION_JSON)) + ); let userinfo = response .json::() .await diff --git a/server/testkit/tests/person.rs b/server/testkit/tests/person.rs index e77ffb5e2..608f7af94 100644 --- a/server/testkit/tests/person.rs +++ b/server/testkit/tests/person.rs @@ -1,4 +1,6 @@ use kanidm_client::KanidmClient; +use kanidm_proto::constants::APPLICATION_JSON; +use reqwest::header::CONTENT_TYPE; /// This literally tests that the thing exists and responds in a way we expect, probably worth testing it better... #[kanidmd_testkit::test] @@ -14,7 +16,7 @@ async fn test_v1_person_patch(rsclient: KanidmClient) { let response = match client .patch(format!("{}/v1/person/foo", &addr)) - .header("Content-Type", "application/json") + .header(CONTENT_TYPE, APPLICATION_JSON) .body(post_body) .send() .await diff --git a/server/testkit/tests/proto_v1_test.rs b/server/testkit/tests/proto_v1_test.rs index cb983e6e2..c93734b0a 100644 --- a/server/testkit/tests/proto_v1_test.rs +++ b/server/testkit/tests/proto_v1_test.rs @@ -635,6 +635,34 @@ async fn test_server_rest_posix_auth_lifecycle(rsclient: KanidmClient) { .await .unwrap(); + // test sending a faulty JSON blob to the person unix update endpoint + let bad_json: serde_json::Value = serde_json::json!({ + "shell" : "test_value", + "gidnumber" : "5" // this should be a u32, but it's not! + }); + let res = rsclient + .perform_post_request::( + format!("/v1/person/{}/_unix", "posix_account").as_str(), + bad_json, + ) + .await; + dbg!(&res); + assert!(res.is_err()); + + // test sending a faulty JSON blob to the person unix update endpoint + let bad_json: serde_json::Value = serde_json::json!({ + "crab" : "cakes", // this is an invalid field. + "gidnumber" : 5 + }); + let res = rsclient + .perform_post_request::( + format!("/v1/person/{}/_unix", "posix_account").as_str(), + bad_json, + ) + .await; + dbg!(&res); + assert!(res.is_err()); + // attempt to verify (good, anon-conn) let r1 = anon_rsclient .idm_account_unix_cred_verify("posix_account", UNIX_TEST_PASSWORD) diff --git a/server/testkit/tests/routes.rs b/server/testkit/tests/routes.rs deleted file mode 100644 index 5b35b0d44..000000000 --- a/server/testkit/tests/routes.rs +++ /dev/null @@ -1,681 +0,0 @@ -use kanidm_client::KanidmClient; - -#[kanidmd_testkit::test] -async fn test_routes(rsclient: KanidmClient) { - let routemap = r#" - [ - { - "path": "/", - "method": "GET" - }, - { - "path": "/robots.txt", - "method": "GET" - }, - { - "path": "/manifest.webmanifest", - "method": "GET" - }, - { - "path": "/ui", - "method": "GET" - }, - { - "path": "/ui/login", - "method": "GET" - }, - { - "path": "/v1/account/:id/_unix/_token", - "method": "GET" - }, - { - "path": "/v1/account/:id/_radius/_token", - "method": "GET" - }, - { - "path": "/v1/group/:id/_unix/_token", - "method": "GET" - }, - { - "path": "/v1/oauth2/:rs_name/_icon", - "method": "GET" - }, - { - "path": "/status", - "method": "GET" - }, - { - "path": "/oauth2/authorise", - "method": "POST" - }, - { - "path": "/oauth2/authorise", - "method": "GET" - }, - { - "path": "/oauth2/authorise/permit", - "method": "POST" - }, - { - "path": "/oauth2/authorise/permit", - "method": "GET" - }, - { - "path": "/oauth2/authorise/reject", - "method": "POST" - }, - { - "path": "/oauth2/authorise/reject", - "method": "GET" - }, - { - "path": "/oauth2/token", - "method": "POST" - }, - { - "path": "/oauth2/token/introspect", - "method": "POST" - }, - { - "path": "/oauth2/token/revoke", - "method": "POST" - }, - { - "path": "/oauth2/openid/:client_id/.well-known/openid-configuration", - "method": "GET" - }, - { - "path": "/oauth2/openid/:client_id/userinfo", - "method": "GET" - }, - { - "path": "/oauth2/openid/:client_id/public_key.jwk", - "method": "GET" - }, - { - "path": "/scim/v1/Sync", - "method": "POST" - }, - { - "path": "/scim/v1/Sync", - "method": "GET" - }, - { - "path": "/scim/v1/Sink", - "method": "GET" - }, - { - "path": "/v1/sync_account", - "method": "GET" - }, - { - "path": "/v1/sync_account", - "method": "POST" - }, - { - "path": "/v1/sync_account/:id", - "method": "GET" - }, - { - "path": "/v1/sync_account/:id", - "method": "PATCH" - }, - { - "path": "/v1/sync_account/:id/_finalise", - "method": "GET" - }, - { - "path": "/v1/sync_account/:id/_terminate", - "method": "GET" - }, - { - "path": "/v1/sync_account/:id/_sync_token", - "method": "POST" - }, - { - "path": "/v1/sync_account/:id/_sync_token", - "method": "DELETE" - }, - { - "path": "/v1/raw/create", - "method": "POST" - }, - { - "path": "/v1/raw/modify", - "method": "POST" - }, - { - "path": "/v1/raw/delete", - "method": "POST" - }, - { - "path": "/v1/raw/search", - "method": "POST" - }, - { - "path": "/v1/auth", - "method": "POST" - }, - { - "path": "/v1/auth/valid", - "method": "GET" - }, - { - "path": "/v1/reauth", - "method": "POST" - }, - { - "path": "/v1/logout", - "method": "GET" - }, - { - "path": "/v1/schema", - "method": "GET" - }, - { - "path": "/v1/schema/attributetype", - "method": "GET" - }, - { - "path": "/v1/schema/attributetype", - "method": "POST" - }, - { - "path": "/v1/schema/attributetype/:id", - "method": "GET" - }, - { - "path": "/v1/schema/attributetype/:id", - "method": "PUT" - }, - { - "path": "/v1/schema/attributetype/:id", - "method": "PATCH" - }, - { - "path": "/v1/schema/classtype", - "method": "GET" - }, - { - "path": "/v1/schema/classtype", - "method": "POST" - }, - { - "path": "/v1/schema/classtype/:id", - "method": "GET" - }, - { - "path": "/v1/schema/classtype/:id", - "method": "PUT" - }, - { - "path": "/v1/schema/classtype/:id", - "method": "PATCH" - }, - { - "path": "/v1/oauth2", - "method": "GET" - }, - { - "path": "/v1/oauth2/_basic", - "method": "POST" - }, - { - "path": "/v1/oauth2/:rs_name", - "method": "GET" - }, - { - "path": "/v1/oauth2/:rs_name", - "method": "PATCH" - }, - { - "path": "/v1/oauth2/:rs_name", - "method": "DELETE" - }, - { - "path": "/v1/oauth2/:rs_name/_basic_secret", - "method": "GET" - }, - { - "path": "/v1/oauth2/_scopemap/:id/:group", - "method": "POST" - }, - { - "path": "/v1/oauth2/_scopemap/:id/:group", - "method": "DELETE" - }, - { - "path": "/v1/oauth2/_sup_scopemap/:id/:group", - "method": "POST" - }, - { - "path": "/v1/oauth2/_sup_scopemap/:id/:group", - "method": "DELETE" - }, - { - "path": "/v1/self", - "method": "GET" - }, - { - "path": "/v1/self/_uat", - "method": "GET" - }, - { - "path": "/v1/self/_attr/:attr", - "method": "GET" - }, - { - "path": "/v1/self/_credential", - "method": "GET" - }, - { - "path": "/v1/self/_credential/:cid/_lock", - "method": "GET" - }, - { - "path": "/v1/self/_radius", - "method": "GET" - }, - { - "path": "/v1/self/_radius", - "method": "DELETE" - }, - { - "path": "/v1/self/_radius", - "method": "POST" - }, - { - "path": "/v1/self/_radius/_config", - "method": "POST" - }, - { - "path": "/v1/self/_radius/_config/:token", - "method": "GET" - }, - { - "path": "/v1/self/_radius/_config/:token/apple", - "method": "GET" - }, - { - "path": "/v1/self/_applinks", - "method": "GET" - }, - { - "path": "/v1/person", - "method": "GET" - }, - { - "path": "/v1/person", - "method": "POST" - }, - { - "path": "/v1/person/:id", - "method": "GET" - }, - { - "path": "/v1/person/:id", - "method": "PATCH" - }, - { - "path": "/v1/person/:id", - "method": "DELETE" - }, - { - "path": "/v1/person/:id/_attr/:attr", - "method": "GET" - }, - { - "path": "/v1/person/:id/_attr/:attr", - "method": "PUT" - }, - { - "path": "/v1/person/:id/_attr/:attr", - "method": "POST" - }, - { - "path": "/v1/person/:id/_attr/:attr", - "method": "DELETE" - }, - { - "path": "/v1/person/:id/_lock", - "method": "GET" - }, - { - "path": "/v1/person/:id/_credential", - "method": "GET" - }, - { - "path": "/v1/person/:id/_credential/_status", - "method": "GET" - }, - { - "path": "/v1/person/:id/_credential/:cid/_lock", - "method": "GET" - }, - { - "path": "/v1/person/:id/_credential/_update", - "method": "GET" - }, - { - "path": "/v1/person/:id/_credential/_update_intent", - "method": "GET" - }, - { - "path": "/v1/person/:id/_credential/_update_intent/:ttl", - "method": "GET" - }, - { - "path": "/v1/person/:id/_ssh_pubkeys", - "method": "GET" - }, - { - "path": "/v1/person/:id/_ssh_pubkeys", - "method": "POST" - }, - { - "path": "/v1/person/:id/_ssh_pubkeys/:tag", - "method": "GET" - }, - { - "path": "/v1/person/:id/_ssh_pubkeys/:tag", - "method": "DELETE" - }, - { - "path": "/v1/person/:id/_radius", - "method": "GET" - }, - { - "path": "/v1/person/:id/_radius", - "method": "POST" - }, - { - "path": "/v1/person/:id/_radius", - "method": "DELETE" - }, - { - "path": "/v1/person/:id/_unix", - "method": "POST" - }, - { - "path": "/v1/person/:id/_unix/_credential", - "method": "PUT" - }, - { - "path": "/v1/person/:id/_unix/_credential", - "method": "DELETE" - }, - { - "path": "/v1/service_account", - "method": "GET" - }, - { - "path": "/v1/service_account", - "method": "POST" - }, - { - "path": "/v1/service_account/:id", - "method": "GET" - }, - { - "path": "/v1/service_account/:id", - "method": "PATCH" - }, - { - "path": "/v1/service_account/:id", - "method": "DELETE" - }, - { - "path": "/v1/service_account/:id/_attr/:attr", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_attr/:attr", - "method": "PUT" - }, - { - "path": "/v1/service_account/:id/_attr/:attr", - "method": "POST" - }, - { - "path": "/v1/service_account/:id/_attr/:attr", - "method": "DELETE" - }, - { - "path": "/v1/service_account/:id/_lock", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_into_person", - "method": "POST" - }, - { - "path": "/v1/service_account/:id/_api_token", - "method": "POST" - }, - { - "path": "/v1/service_account/:id/_api_token", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_api_token/:token_id", - "method": "DELETE" - }, - { - "path": "/v1/service_account/:id/_credential", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_credential/_generate", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_credential/_status", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_credential/:cid/_lock", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_ssh_pubkeys", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_ssh_pubkeys", - "method": "POST" - }, - { - "path": "/v1/service_account/:id/_ssh_pubkeys/:tag", - "method": "GET" - }, - { - "path": "/v1/service_account/:id/_ssh_pubkeys/:tag", - "method": "DELETE" - }, - { - "path": "/v1/service_account/:id/_unix", - "method": "POST" - }, - { - "path": "/v1/account/:id/_unix/_auth", - "method": "POST" - }, - { - "path": "/v1/account/:id/_ssh_pubkeys", - "method": "GET" - }, - { - "path": "/v1/account/:id/_ssh_pubkeys/:tag", - "method": "GET" - }, - { - "path": "/v1/account/:id/_user_auth_token", - "method": "GET" - }, - { - "path": "/v1/account/:id/_user_auth_token/:token_id", - "method": "DELETE" - }, - { - "path": "/v1/credential/_exchange_intent", - "method": "POST" - }, - { - "path": "/v1/credential/_status", - "method": "POST" - }, - { - "path": "/v1/credential/_update", - "method": "POST" - }, - { - "path": "/v1/credential/_commit", - "method": "POST" - }, - { - "path": "/v1/credential/_cancel", - "method": "POST" - }, - { - "path": "/v1/group", - "method": "GET" - }, - { - "path": "/v1/group", - "method": "POST" - }, - { - "path": "/v1/group/:id", - "method": "GET" - }, - { - "path": "/v1/group/:id", - "method": "DELETE" - }, - { - "path": "/v1/group/:id/_attr/:attr", - "method": "DELETE" - }, - { - "path": "/v1/group/:id/_attr/:attr", - "method": "GET" - }, - { - "path": "/v1/group/:id/_attr/:attr", - "method": "PUT" - }, - { - "path": "/v1/group/:id/_attr/:attr", - "method": "POST" - }, - { - "path": "/v1/group/:id/_unix", - "method": "POST" - }, - { - "path": "/v1/domain", - "method": "GET" - }, - { - "path": "/v1/domain/_attr/:attr", - "method": "GET" - }, - { - "path": "/v1/domain/_attr/:attr", - "method": "PUT" - }, - { - "path": "/v1/domain/_attr/:attr", - "method": "DELETE" - }, - { - "path": "/v1/system", - "method": "GET" - }, - { - "path": "/v1/system/_attr/:attr", - "method": "GET" - }, - { - "path": "/v1/system/_attr/:attr", - "method": "POST" - }, - { - "path": "/v1/system/_attr/:attr", - "method": "DELETE" - }, - { - "path": "/v1/recycle_bin", - "method": "GET" - }, - { - "path": "/v1/recycle_bin/:id", - "method": "GET" - }, - { - "path": "/v1/recycle_bin/:id/_revive", - "method": "POST" - }, - { - "path": "/v1/access_profile", - "method": "GET" - }, - { - "path": "/v1/access_profile/:id", - "method": "GET" - }, - { - "path": "/v1/access_profile/:id/_attr/:attr", - "method": "GET" - } - ] - "#; - // ,{ - // "path": "/v1/routemap", - // "method": "GET" - // } - let routelist: Vec = serde_json::from_str(routemap).unwrap(); - let client = reqwest::ClientBuilder::new() - .danger_accept_invalid_certs(true) - .danger_accept_invalid_hostnames(true) - .build() - .unwrap(); - for route in routelist { - // println!("{:?}", route); - let path: String = route.get("path").unwrap().to_string(); - let method: String = route.get("method").unwrap().to_string(); - let method = method.replace('"', ""); - let method = method.as_str(); - println!("'{method}'"); - let method = match method { - "GET" => reqwest::Method::GET, - "POST" => reqwest::Method::POST, - "DELETE" => reqwest::Method::DELETE, - "PATCH" => reqwest::Method::PATCH, - "PUT" => reqwest::Method::PUT, - _ => todo!("{}", method), - }; - if path.contains(':') { - println!("Can't do this because it has an attribute: {}", path); - continue; - } - let url = format!("{}{}", rsclient.get_url(), path.replace('"', "")); - - println!("#### {:?} {} {}", method, path, url); - - let res = match client - .request(method, &url) - // .version(http::Version::HTTP_11) - .send() - .await - { - Ok(val) => val, - Err(error) => { - panic!("Failed to query {:?} : {:#?}", url, error); - } - }; - if res.status() == 404 { - panic!("Failed to query {:?} : {:#?}", url, res); - } - } -} diff --git a/server/web_ui/pkg/kanidmd_web_ui.js b/server/web_ui/pkg/kanidmd_web_ui.js index 651153185..d8de84543 100644 --- a/server/web_ui/pkg/kanidmd_web_ui.js +++ b/server/web_ui/pkg/kanidmd_web_ui.js @@ -234,7 +234,7 @@ function addBorrowedObject(obj) { } function __wbg_adapter_48(arg0, arg1, arg2) { try { - wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__he237e4e531e49fe1(arg0, arg1, addBorrowedObject(arg2)); + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hc988533207355089(arg0, arg1, addBorrowedObject(arg2)); } finally { heap[stack_pointer++] = undefined; } @@ -242,14 +242,14 @@ function __wbg_adapter_48(arg0, arg1, arg2) { function __wbg_adapter_51(arg0, arg1, arg2) { try { - wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hc1460e7f28360ed3(arg0, arg1, addBorrowedObject(arg2)); + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha34c6831d0d6d86f(arg0, arg1, addBorrowedObject(arg2)); } finally { heap[stack_pointer++] = undefined; } } function __wbg_adapter_54(arg0, arg1, arg2) { - wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha2ecae7653526986(arg0, arg1, addHeapObject(arg2)); + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h52363d7e83a077de(arg0, arg1, addHeapObject(arg2)); } /** @@ -356,13 +356,13 @@ function __wbg_get_imports() { getInt32Memory0()[arg0 / 4 + 1] = len1; getInt32Memory0()[arg0 / 4 + 0] = ptr1; }; - imports.wbg.__wbg_modalhidebyid_14daee5d362376c0 = function(arg0, arg1) { - modal_hide_by_id(getStringFromWasm0(arg0, arg1)); - }; imports.wbg.__wbindgen_object_clone_ref = function(arg0) { const ret = getObject(arg0); return addHeapObject(ret); }; + imports.wbg.__wbg_modalhidebyid_a36f33eb8222a059 = function(arg0, arg1) { + modal_hide_by_id(getStringFromWasm0(arg0, arg1)); + }; imports.wbg.__wbindgen_error_new = function(arg0, arg1) { const ret = new Error(getStringFromWasm0(arg0, arg1)); return addHeapObject(ret); @@ -411,11 +411,14 @@ function __wbg_get_imports() { const ret = getObject(arg0) === undefined; return ret; }; - imports.wbg.__wbg_cachekey_b61393159c57fd7b = function(arg0, arg1) { - const ret = getObject(arg1).__yew_subtree_cache_key; + imports.wbg.__wbg_listenerid_12315eee21527820 = function(arg0, arg1) { + const ret = getObject(arg1).__yew_listener_id; getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); }; + imports.wbg.__wbg_setlistenerid_3183aae8fa5840fb = function(arg0, arg1) { + getObject(arg0).__yew_listener_id = arg1 >>> 0; + }; imports.wbg.__wbg_subtreeid_e348577f7ef777e3 = function(arg0, arg1) { const ret = getObject(arg1).__yew_subtree_id; getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; @@ -424,16 +427,13 @@ function __wbg_get_imports() { imports.wbg.__wbg_setsubtreeid_d32e6327eef1f7fc = function(arg0, arg1) { getObject(arg0).__yew_subtree_id = arg1 >>> 0; }; - imports.wbg.__wbg_setcachekey_80183b7cfc421143 = function(arg0, arg1) { - getObject(arg0).__yew_subtree_cache_key = arg1 >>> 0; - }; - imports.wbg.__wbg_listenerid_12315eee21527820 = function(arg0, arg1) { - const ret = getObject(arg1).__yew_listener_id; + imports.wbg.__wbg_cachekey_b61393159c57fd7b = function(arg0, arg1) { + const ret = getObject(arg1).__yew_subtree_cache_key; getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); }; - imports.wbg.__wbg_setlistenerid_3183aae8fa5840fb = function(arg0, arg1) { - getObject(arg0).__yew_listener_id = arg1 >>> 0; + imports.wbg.__wbg_setcachekey_80183b7cfc421143 = function(arg0, arg1) { + getObject(arg0).__yew_subtree_cache_key = arg1 >>> 0; }; imports.wbg.__wbg_new_abda76e883ba8a5f = function() { const ret = new Error(); @@ -461,9 +461,6 @@ function __wbg_get_imports() { const ret = arg0; return addHeapObject(ret); }; - imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) { - getObject(arg0)[takeObject(arg1)] = takeObject(arg2); - }; imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { const ret = getObject(arg0) == getObject(arg1); return ret; @@ -495,6 +492,9 @@ function __wbg_get_imports() { wasm.__wbindgen_free(arg0, arg1 * 4); console.warn(...v0); }; + imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; imports.wbg.__wbg_documentURI_4bff51077cdeeac1 = function() { return handleError(function (arg0, arg1) { const ret = getObject(arg1).documentURI; const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); @@ -564,21 +564,15 @@ function __wbg_get_imports() { const ret = getObject(arg0).fetch(getObject(arg1)); return addHeapObject(ret); }; - imports.wbg.__wbg_addEventListener_a5963e26cd7b176b = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); - }, arguments) }; - imports.wbg.__wbg_removeEventListener_782040b4432709cb = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0); - }, arguments) }; - imports.wbg.__wbg_instanceof_HtmlFormElement_b57527983c7c1ada = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof HTMLFormElement; - } catch { - result = false; - } - const ret = result; - return ret; + imports.wbg.__wbg_value_3c5f08ffc2b7d6f9 = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setvalue_0dc100d4b9908028 = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); }; imports.wbg.__wbg_instanceof_ShadowRoot_b64337370f59fe2d = function(arg0) { let result; @@ -601,6 +595,13 @@ function __wbg_get_imports() { imports.wbg.__wbg_pushState_1145414a47c0b629 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { getObject(arg0).pushState(getObject(arg1), getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5)); }, arguments) }; + imports.wbg.__wbg_href_47b90f0ddf3ddcd7 = function(arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; imports.wbg.__wbg_getItem_ed8e218e51f1efeb = function() { return handleError(function (arg0, arg1, arg2, arg3) { const ret = getObject(arg1).getItem(getStringFromWasm0(arg2, arg3)); var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); @@ -614,16 +615,6 @@ function __wbg_get_imports() { imports.wbg.__wbg_setItem_d002ee486462bfff = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { getObject(arg0).setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); }, arguments) }; - imports.wbg.__wbg_value_3c5f08ffc2b7d6f9 = function(arg0, arg1) { - const ret = getObject(arg1).value; - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }; - imports.wbg.__wbg_setvalue_0dc100d4b9908028 = function(arg0, arg1, arg2) { - getObject(arg0).value = getStringFromWasm0(arg1, arg2); - }; imports.wbg.__wbg_instanceof_HtmlInputElement_31b50e0cf542c524 = function(arg0) { let result; try { @@ -651,6 +642,12 @@ function __wbg_get_imports() { imports.wbg.__wbg_setvalue_1f95e61cbc382f7f = function(arg0, arg1, arg2) { getObject(arg0).value = getStringFromWasm0(arg1, arg2); }; + imports.wbg.__wbg_add_3eafedc4b2a28db0 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).add(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_remove_8ae45e50cb58bb66 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).remove(getStringFromWasm0(arg1, arg2)); + }, arguments) }; imports.wbg.__wbg_instanceof_Element_4622f5da1249a3eb = function(arg0) { let result; try { @@ -715,20 +712,6 @@ function __wbg_get_imports() { imports.wbg.__wbg_set_b34caba58723c454 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { getObject(arg0).set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); }, arguments) }; - imports.wbg.__wbg_href_47b90f0ddf3ddcd7 = function(arg0, arg1) { - const ret = getObject(arg1).href; - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }; - imports.wbg.__wbg_log_1d3ae0273d8f4f8a = function(arg0) { - console.log(getObject(arg0)); - }; - imports.wbg.__wbg_credentials_66b6baa89eb03c21 = function(arg0) { - const ret = getObject(arg0).credentials; - return addHeapObject(ret); - }; imports.wbg.__wbg_headers_b439dcff02e808e5 = function(arg0) { const ret = getObject(arg0).headers; return addHeapObject(ret); @@ -737,12 +720,16 @@ function __wbg_get_imports() { const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_newwithform_368648c82279d486 = function() { return handleError(function (arg0) { - const ret = new FormData(getObject(arg0)); + imports.wbg.__wbg_create_c7e40b6b88186cbf = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).create(getObject(arg1)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_get_4c356dcef81d58a5 = function(arg0, arg1, arg2) { - const ret = getObject(arg0).get(getStringFromWasm0(arg1, arg2)); + imports.wbg.__wbg_get_e66794f89dcd7828 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).get(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_credentials_66b6baa89eb03c21 = function(arg0) { + const ret = getObject(arg0).credentials; return addHeapObject(ret); }; imports.wbg.__wbg_instanceof_Response_fc4327dbfcdf5ced = function(arg0) { @@ -767,14 +754,9 @@ function __wbg_get_imports() { const ret = getObject(arg0).json(); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_create_c7e40b6b88186cbf = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).create(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_get_e66794f89dcd7828 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).get(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; + imports.wbg.__wbg_log_1d3ae0273d8f4f8a = function(arg0) { + console.log(getObject(arg0)); + }; imports.wbg.__wbg_target_f171e89c61e2bccf = function(arg0) { const ret = getObject(arg0).target; return isLikeNone(ret) ? 0 : addHeapObject(ret); @@ -794,6 +776,49 @@ function __wbg_get_imports() { imports.wbg.__wbg_preventDefault_24104f3f0a54546a = function(arg0) { getObject(arg0).preventDefault(); }; + imports.wbg.__wbg_newwithform_368648c82279d486 = function() { return handleError(function (arg0) { + const ret = new FormData(getObject(arg0)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_get_4c356dcef81d58a5 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).get(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_href_d62a28e4fc1ab948 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_pathname_c8fd5c498079312d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).pathname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_search_6c3c472e076ee010 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_hash_a1a795b89dda8e3d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_replace_5d1d2b7956cafd7b = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).replace(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_getClientExtensionResults_b9108fbba9f54b38 = function(arg0) { + const ret = getObject(arg0).getClientExtensionResults(); + return addHeapObject(ret); + }; imports.wbg.__wbg_parentNode_9e53f8b17eb98c9d = function(arg0) { const ret = getObject(arg0).parentNode; return isLikeNone(ret) ? 0 : addHeapObject(ret); @@ -832,47 +857,6 @@ function __wbg_get_imports() { const ret = getObject(arg0).removeChild(getObject(arg1)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_getClientExtensionResults_b9108fbba9f54b38 = function(arg0) { - const ret = getObject(arg0).getClientExtensionResults(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_add_3eafedc4b2a28db0 = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).add(getStringFromWasm0(arg1, arg2)); - }, arguments) }; - imports.wbg.__wbg_remove_8ae45e50cb58bb66 = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).remove(getStringFromWasm0(arg1, arg2)); - }, arguments) }; - imports.wbg.__wbg_href_d62a28e4fc1ab948 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg1).href; - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }, arguments) }; - imports.wbg.__wbg_pathname_c8fd5c498079312d = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg1).pathname; - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }, arguments) }; - imports.wbg.__wbg_search_6c3c472e076ee010 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg1).search; - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }, arguments) }; - imports.wbg.__wbg_hash_a1a795b89dda8e3d = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg1).hash; - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }, arguments) }; - imports.wbg.__wbg_replace_5d1d2b7956cafd7b = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).replace(getStringFromWasm0(arg1, arg2)); - }, arguments) }; imports.wbg.__wbg_href_17ed54b321396524 = function(arg0, arg1) { const ret = getObject(arg1).href; const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); @@ -915,6 +899,22 @@ function __wbg_get_imports() { const ret = new URL(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3)); return addHeapObject(ret); }, arguments) }; + imports.wbg.__wbg_addEventListener_a5963e26cd7b176b = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); + }, arguments) }; + imports.wbg.__wbg_removeEventListener_782040b4432709cb = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0); + }, arguments) }; + imports.wbg.__wbg_instanceof_HtmlFormElement_b57527983c7c1ada = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLFormElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) { const ret = getObject(arg0)[arg1 >>> 0]; return addHeapObject(ret); @@ -1123,16 +1123,16 @@ function __wbg_get_imports() { const ret = wasm.memory; return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2610 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 1223, __wbg_adapter_48); + imports.wbg.__wbindgen_closure_wrapper2586 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 1198, __wbg_adapter_48); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper3431 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 1533, __wbg_adapter_51); + imports.wbg.__wbindgen_closure_wrapper2813 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 1257, __wbg_adapter_51); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper4517 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 1592, __wbg_adapter_54); + imports.wbg.__wbindgen_closure_wrapper2986 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 1319, __wbg_adapter_54); return addHeapObject(ret); }; diff --git a/server/web_ui/pkg/kanidmd_web_ui_bg.wasm b/server/web_ui/pkg/kanidmd_web_ui_bg.wasm index 59f66a981..4e1931ebb 100644 Binary files a/server/web_ui/pkg/kanidmd_web_ui_bg.wasm and b/server/web_ui/pkg/kanidmd_web_ui_bg.wasm differ diff --git a/server/web_ui/pkg/kanidmd_web_ui_bg.wasm.br b/server/web_ui/pkg/kanidmd_web_ui_bg.wasm.br index acc56c50b..94a897e5b 100644 Binary files a/server/web_ui/pkg/kanidmd_web_ui_bg.wasm.br and b/server/web_ui/pkg/kanidmd_web_ui_bg.wasm.br differ diff --git a/server/web_ui/src/constants.rs b/server/web_ui/src/constants.rs index b278b05f5..ab61bdeb9 100644 --- a/server/web_ui/src/constants.rs +++ b/server/web_ui/src/constants.rs @@ -1,5 +1,7 @@ //! Constants +pub const CONTENT_TYPE: &str = "content-type"; + // CSS classes that get applied to full-page forms pub const CSS_CLASSES_BODY_FORM: &[&str] = &["flex-column", "d-flex", "h-100"]; diff --git a/server/web_ui/src/lib.rs b/server/web_ui/src/lib.rs index 5f9143a92..aa2726ca4 100644 --- a/server/web_ui/src/lib.rs +++ b/server/web_ui/src/lib.rs @@ -14,6 +14,7 @@ #![allow(clippy::disallowed_types)] use error::FetchError; +use kanidm_proto::constants::APPLICATION_JSON; use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::JsFuture; @@ -83,7 +84,7 @@ pub async fn do_request( let request = Request::new_with_str_and_init(uri, &opts)?; request .headers() - .set("content-type", "application/json") + .set(crate::constants::CONTENT_TYPE, APPLICATION_JSON) .expect_throw("failed to set content-type header"); if let Some(sessionid) = models::pop_auth_session_id() { diff --git a/server/web_ui/src/oauth2.rs b/server/web_ui/src/oauth2.rs index ef8e40fbc..3bd39b0f2 100644 --- a/server/web_ui/src/oauth2.rs +++ b/server/web_ui/src/oauth2.rs @@ -1,4 +1,5 @@ use gloo::console; +use kanidm_proto::constants::APPLICATION_JSON; pub use kanidm_proto::oauth2::{ AccessTokenRequest, AccessTokenResponse, AuthorisationRequest, AuthorisationResponse, CodeChallengeMethod, ErrorResponse, @@ -146,9 +147,10 @@ impl Oauth2App { opts.body(Some(&consentreq_jsvalue)); let request = Request::new_with_str_and_init("/oauth2/authorise/permit", &opts)?; + request .headers() - .set("content-type", "application/json") + .set(crate::constants::CONTENT_TYPE, APPLICATION_JSON) .expect_throw("failed to set header"); if let Some(bearer_token) = models::get_bearer_token() { diff --git a/unix_integration/tests/cache_layer_test.rs b/unix_integration/tests/cache_layer_test.rs index 15f93ccbd..13353868f 100644 --- a/unix_integration/tests/cache_layer_test.rs +++ b/unix_integration/tests/cache_layer_test.rs @@ -137,6 +137,7 @@ async fn test_fixture(rsclient: KanidmClient) { .auth_simple_password("admin", ADMIN_TEST_PASSWORD) .await; debug!("auth_simple_password res: {:?}", res); + dbg!(&res); assert!(res.is_ok()); // Not recommended in production! rsclient