Auth plugins (#155)

This commit is contained in:
Gregory Schier
2025-01-17 05:53:03 -08:00
committed by GitHub
parent e21df98a30
commit bd322162c8
56 changed files with 5468 additions and 1474 deletions

View File

@@ -39,8 +39,8 @@ pub enum InternalEventPayload {
BootRequest(BootRequest),
BootResponse(BootResponse),
ReloadRequest,
ReloadResponse,
ReloadRequest(EmptyPayload),
ReloadResponse(EmptyPayload),
TerminateRequest,
TerminateResponse,
@@ -57,15 +57,22 @@ pub enum InternalEventPayload {
SendHttpRequestRequest(SendHttpRequestRequest),
SendHttpRequestResponse(SendHttpRequestResponse),
GetHttpRequestActionsRequest(GetHttpRequestActionsRequest),
// Request Actions
GetHttpRequestActionsRequest(EmptyPayload),
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
// Template Functions
GetTemplateFunctionsRequest,
GetTemplateFunctionsResponse(GetTemplateFunctionsResponse),
CallTemplateFunctionRequest(CallTemplateFunctionRequest),
CallTemplateFunctionResponse(CallTemplateFunctionResponse),
GetHttpAuthenticationRequest(EmptyPayload),
GetHttpAuthenticationResponse(GetHttpAuthenticationResponse),
CallHttpAuthenticationRequest(CallHttpAuthenticationRequest),
CallHttpAuthenticationResponse(CallHttpAuthenticationResponse),
CopyTextRequest(CopyTextRequest),
RenderHttpRequestRequest(RenderHttpRequestRequest),
@@ -87,9 +94,14 @@ pub enum InternalEventPayload {
/// Returned when a plugin doesn't get run, just so the server
/// has something to listen for
EmptyResponse,
EmptyResponse(EmptyPayload),
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default)]
#[ts(export, type = "{}", export_to = "events.ts")]
pub struct EmptyPayload {}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
@@ -281,6 +293,41 @@ pub enum Icon {
_Unknown(String),
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct GetHttpAuthenticationResponse {
pub name: String,
pub plugin_name: String,
pub config: Vec<FormInput>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct CallHttpAuthenticationRequest {
pub config: serde_json::Map<String, serde_json::Value>,
pub method: String,
pub url: String,
pub headers: Vec<HttpHeader>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct HttpHeader {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct CallHttpAuthenticationResponse {
pub url: String,
pub headers: Vec<HttpHeader>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
@@ -301,25 +348,24 @@ pub struct TemplateFunction {
/// tags when changing the `name` property
#[ts(optional)]
pub aliases: Option<Vec<String>>,
pub args: Vec<TemplateFunctionArg>,
pub args: Vec<FormInput>,
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "snake_case", tag = "type")]
#[ts(export, export_to = "events.ts")]
pub enum TemplateFunctionArg {
Text(TemplateFunctionTextArg),
Select(TemplateFunctionSelectArg),
Checkbox(TemplateFunctionCheckboxArg),
HttpRequest(TemplateFunctionHttpRequestArg),
File(TemplateFunctionFileArg),
pub enum FormInput {
Text(FormInputText),
Select(FormInputSelect),
Checkbox(FormInputCheckbox),
File(FormInputFile),
HttpRequest(FormInputHttpRequest),
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct TemplateFunctionBaseArg {
/// The name of the argument. Should be `camelCase` format
pub struct FormInputBase {
pub name: String,
/// Whether the user must fill in the argument
@@ -338,29 +384,29 @@ pub struct TemplateFunctionBaseArg {
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct TemplateFunctionTextArg {
pub struct FormInputText {
#[serde(flatten)]
pub base: TemplateFunctionBaseArg,
pub base: FormInputBase,
/// Placeholder for the text input
#[ts(optional)]
#[ts(optional = nullable)]
pub placeholder: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct TemplateFunctionHttpRequestArg {
pub struct FormInputHttpRequest {
#[serde(flatten)]
pub base: TemplateFunctionBaseArg,
pub base: FormInputBase,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct TemplateFunctionFileArg {
pub struct FormInputFile {
#[serde(flatten)]
pub base: TemplateFunctionBaseArg,
pub base: FormInputBase,
/// The title of the file selection window
pub title: String,
@@ -379,13 +425,13 @@ pub struct TemplateFunctionFileArg {
// Specify to only allow selection of certain file extensions
#[ts(optional)]
pub filters: Option<Vec<OpenFileFilter>>,
pub filters: Option<Vec<FileFilter>>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct OpenFileFilter {
pub struct FileFilter {
pub name: String,
/// File extensions to require
pub extensions: Vec<String>,
@@ -394,27 +440,27 @@ pub struct OpenFileFilter {
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct TemplateFunctionSelectArg {
pub struct FormInputSelect {
#[serde(flatten)]
pub base: TemplateFunctionBaseArg,
pub base: FormInputBase,
/// The options that will be available in the select input
pub options: Vec<TemplateFunctionSelectOption>,
pub options: Vec<FormInputSelectOption>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct TemplateFunctionCheckboxArg {
pub struct FormInputCheckbox {
#[serde(flatten)]
pub base: TemplateFunctionBaseArg,
pub base: FormInputBase,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct TemplateFunctionSelectOption {
pub label: String,
pub struct FormInputSelectOption {
pub name: String,
pub value: String,
}

View File

@@ -1,9 +1,10 @@
use crate::error::Error::{ClientNotInitializedErr, PluginErr, PluginNotFoundErr, UnknownEventErr};
use crate::error::Result;
use crate::events::{
BootRequest, CallHttpRequestActionRequest, CallTemplateFunctionArgs,
CallTemplateFunctionRequest, CallTemplateFunctionResponse, FilterRequest, FilterResponse,
GetHttpRequestActionsRequest, GetHttpRequestActionsResponse, GetTemplateFunctionsResponse,
BootRequest, CallHttpAuthenticationRequest, CallHttpAuthenticationResponse,
CallHttpRequestActionRequest, CallTemplateFunctionArgs, CallTemplateFunctionRequest,
CallTemplateFunctionResponse, EmptyPayload, FilterRequest, FilterResponse,
GetHttpAuthenticationResponse, GetHttpRequestActionsResponse, GetTemplateFunctionsResponse,
ImportRequest, ImportResponse, InternalEvent, InternalEventPayload, RenderPurpose,
WindowContext,
};
@@ -402,9 +403,7 @@ impl PluginManager {
let reply_events = self
.send_and_wait(
WindowContext::from_window(window),
&InternalEventPayload::GetHttpRequestActionsRequest(
GetHttpRequestActionsRequest {},
),
&InternalEventPayload::GetHttpRequestActionsRequest(EmptyPayload {}),
)
.await?;
@@ -460,6 +459,54 @@ impl PluginManager {
Ok(())
}
pub async fn get_http_authentication<R: Runtime>(
&self,
window: &WebviewWindow<R>,
) -> Result<Vec<GetHttpAuthenticationResponse>> {
let window_context = WindowContext::from_window(window);
let reply_events = self
.send_and_wait(
window_context,
&InternalEventPayload::GetHttpAuthenticationRequest(EmptyPayload {}),
)
.await?;
let mut results = Vec::new();
for event in reply_events {
if let InternalEventPayload::GetHttpAuthenticationResponse(resp) = event.payload {
results.push(resp.clone());
}
}
Ok(results)
}
pub async fn call_http_authentication<R: Runtime>(
&self,
window: &WebviewWindow<R>,
plugin_name: &str,
req: CallHttpAuthenticationRequest,
) -> Result<CallHttpAuthenticationResponse> {
let plugin = self
.get_plugin_by_name(plugin_name)
.await
.ok_or(PluginNotFoundErr(plugin_name.to_string()))?;
let event = self
.send_to_plugin_and_wait(
WindowContext::from_window(window),
&plugin,
&InternalEventPayload::CallHttpAuthenticationRequest(req),
)
.await?;
match event.payload {
InternalEventPayload::CallHttpAuthenticationResponse(resp) => Ok(resp),
InternalEventPayload::EmptyResponse(_) => {
Err(PluginErr("Auth plugin returned empty".to_string()))
}
e => Err(PluginErr(format!("Auth plugin returned invalid event {:?}", e))),
}
}
pub async fn call_template_function(
&self,
window_context: WindowContext,
@@ -552,7 +599,7 @@ impl PluginManager {
match event.payload {
InternalEventPayload::FilterResponse(resp) => Ok(resp),
InternalEventPayload::EmptyResponse => {
InternalEventPayload::EmptyResponse(_) => {
Err(PluginErr("Filter returned empty".to_string()))
}
e => Err(PluginErr(format!("Export returned invalid event {:?}", e))),