summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs1
-rw-r--r--src/push/handlers/mod.rs75
-rw-r--r--src/push/handlers/vapid.rs0
-rw-r--r--src/push/mod.rs1
-rw-r--r--src/push/pilcrow.dbbin0 -> 233472 bytes
-rw-r--r--src/routes.rs9
6 files changed, 84 insertions, 2 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 48572d3..59729e8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,6 +19,7 @@ mod name;
mod normalize;
mod routes;
mod setup;
+mod push;
#[cfg(test)]
mod test;
mod token;
diff --git a/src/push/handlers/mod.rs b/src/push/handlers/mod.rs
new file mode 100644
index 0000000..f9ba612
--- /dev/null
+++ b/src/push/handlers/mod.rs
@@ -0,0 +1,75 @@
+use std::env;
+
+use axum::{
+ extract::{Json},
+};
+
+use web_push::{
+ SubscriptionInfo,
+ VapidSignatureBuilder,
+ WebPushMessageBuilder,
+ ContentEncoding,
+ IsahcWebPushClient,
+};
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error(transparent)]
+ Database(#[from] sqlx::Error),
+}
+
+
+
+pub async fn vapid() -> String {
+ let vapid_public_key = env::var("VAPID_PUBLIC_KEY").is_ok();
+ String::from(vapid_public_key)
+}
+
+
+pub async fn register() -> String {
+ String::from("OK")
+}
+
+
+pub async fn unregister() -> String {
+ String::from("OK")
+}
+
+
+#[axum::debug_handler]
+pub async fn echo(
+ Json(echo): Json<Echo>,
+) -> Result<(), Error> {
+ // Look this up from a subscription record? Or get it from the client and trust?
+ let endpoint = "https://updates.push.services.mozilla.com/wpush/v1/...";
+ // Get these from client:
+ let p256dh = "key_from_browser_as_base64";
+ let auth = "auth_from_browser_as_base64";
+
+ // You would likely get this by deserializing a browser `pushSubscription` object.
+ let subscription_info = SubscriptionInfo::new(endpoint, p256dh, auth);
+
+ // This will need to come from the DB eventually.
+ let private_key = String::from(env::var("VAPID_PRIVATE_KEY").is_ok());
+ let mut sig_builder = VapidSignatureBuilder::from_pem(private_key, &subscription_info)?.build()?;
+
+ // Now add payload and encrypt.
+ let mut builder = WebPushMessageBuilder::new(&subscription_info);
+ // Eventually, this message will be something other than an echo:
+ let content = echo.msg.as_bytes();
+ builder.set_payload(ContentEncoding::Aes128Gcm, content);
+ builder.set_vapid_signature(sig_builder);
+
+ let client = IsahcWebPushClient::new()?;
+
+ // Finally, send the notification!
+ client.send(builder.build()?).await?;
+ // Fix up return type?
+ Ok(())
+}
+
+
+#[derive(serde::Deserialize)]
+pub struct Echo {
+ pub msg: String,
+}
diff --git a/src/push/handlers/vapid.rs b/src/push/handlers/vapid.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/push/handlers/vapid.rs
diff --git a/src/push/mod.rs b/src/push/mod.rs
new file mode 100644
index 0000000..c3d4495
--- /dev/null
+++ b/src/push/mod.rs
@@ -0,0 +1 @@
+pub mod handlers;
diff --git a/src/push/pilcrow.db b/src/push/pilcrow.db
new file mode 100644
index 0000000..978a002
--- /dev/null
+++ b/src/push/pilcrow.db
Binary files differ
diff --git a/src/routes.rs b/src/routes.rs
index 6993070..293dae3 100644
--- a/src/routes.rs
+++ b/src/routes.rs
@@ -4,7 +4,7 @@ use axum::{
routing::{delete, get, post},
};
-use crate::{app::App, boot, conversation, event, expire, invite, message, setup, ui, user};
+use crate::{app::App, boot, conversation, event, expire, invite, message, setup, push, ui, user};
pub fn routes(app: &App) -> Router<App> {
// UI routes that can be accessed before the administrator completes setup.
@@ -23,7 +23,12 @@ pub fn routes(app: &App) -> Router<App> {
.route_layer(crate::setup::Required(app.clone()).with_fallback(Redirect::to("/setup")));
// API routes that can run before the administrator completes setup.
- let api_bootstrap = Router::new().route("/api/setup", post(setup::handlers::setup));
+ let api_bootstrap = Router::new()
+ .route("/api/setup", post(setup::handlers::setup))
+ .route("/api/vapid", get(push::handlers::vapid))
+ .route("/api/register", post(push::handlers::register))
+ .route("/api/unregister", post(push::handlers::unregister))
+ .route("/api/echo", post(push::handlers::echo));
// API routes that require the administrator to complete setup first.
let api_setup_required = Router::new()