summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@elliehuxtable.com>2023-03-07 22:09:19 +0000
committerGitHub <noreply@github.com>2023-03-07 22:09:19 +0000
commitb978f9a4de662270a7874d16315f6827e58c2b0b (patch)
tree6668af01e951e31cd4320b1b2985d4506cbbdc3b
parentca5bbea0d4c4fd86eb80f99688bcb78f8ba68877 (diff)
Add register notification webhook (#764)
I find it super motivating when people use my stuff, so this makes it _even easier_ to know when someone new signs up!
-rw-r--r--Cargo.lock1
-rw-r--r--atuin-server/Cargo.toml4
-rw-r--r--atuin-server/src/handlers/user.rs44
-rw-r--r--atuin-server/src/settings.rs3
4 files changed, 49 insertions, 3 deletions
diff --git a/Cargo.lock b/Cargo.lock
index feb5dc5c..c4f0c8c2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -169,6 +169,7 @@ dependencies = [
"fs-err",
"http",
"rand",
+ "reqwest",
"serde",
"serde_json",
"sodiumoxide",
diff --git a/atuin-server/Cargo.toml b/atuin-server/Cargo.toml
index 9a9c2890..59afa0ac 100644
--- a/atuin-server/Cargo.toml
+++ b/atuin-server/Cargo.toml
@@ -35,3 +35,7 @@ fs-err = "2.9"
chronoutil = "0.2.3"
tower = "0.4"
tower-http = { version = "0.3", features = ["trace"] }
+reqwest = { version = "0.11", features = [
+ "json",
+ "rustls-tls-native-roots",
+], default-features = false }
diff --git a/atuin-server/src/handlers/user.rs b/atuin-server/src/handlers/user.rs
index 9e145d3c..61af989c 100644
--- a/atuin-server/src/handlers/user.rs
+++ b/atuin-server/src/handlers/user.rs
@@ -1,4 +1,6 @@
use std::borrow::Borrow;
+use std::collections::HashMap;
+use std::time::Duration;
use axum::{
extract::{Path, State},
@@ -6,7 +8,7 @@ use axum::{
};
use http::StatusCode;
use sodiumoxide::crypto::pwhash::argon2id13;
-use tracing::{debug, error, instrument};
+use tracing::{debug, error, info, instrument};
use uuid::Uuid;
use super::{ErrorResponse, ErrorResponseStatus, RespExt};
@@ -16,6 +18,8 @@ use crate::{
router::AppState,
};
+use reqwest::header::CONTENT_TYPE;
+
use atuin_common::api::*;
pub fn verify_str(secret: &str, verify: &str) -> bool {
@@ -32,6 +36,30 @@ pub fn verify_str(secret: &str, verify: &str) -> bool {
}
}
+// Try to send a Discord webhook once - if it fails, we don't retry. "At most once", and best effort.
+// Don't return the status because if this fails, we don't really care.
+async fn send_register_hook(url: &str, username: String, registered: String) {
+ let hook = HashMap::from([
+ ("username", username),
+ ("content", format!("{registered} has just signed up!")),
+ ]);
+
+ let client = reqwest::Client::new();
+
+ let resp = client
+ .post(url)
+ .timeout(Duration::new(5, 0))
+ .header(CONTENT_TYPE, "application/json")
+ .json(&hook)
+ .send()
+ .await;
+
+ match resp {
+ Ok(_) => info!("register webhook sent ok!"),
+ Err(e) => error!("failed to send register webhook: {}", e),
+ }
+}
+
#[instrument(skip_all, fields(user.username = username.as_str()))]
pub async fn get<DB: Database>(
Path(username): Path<String>,
@@ -71,8 +99,8 @@ pub async fn register<DB: Database>(
let hashed = hash_secret(&register.password);
let new_user = NewUser {
- email: register.email,
- username: register.username,
+ email: register.email.clone(),
+ username: register.username.clone(),
password: hashed,
};
@@ -94,6 +122,16 @@ pub async fn register<DB: Database>(
token: (&token).into(),
};
+ if let Some(url) = &state.settings.register_webhook_url {
+ // Could probs be run on another thread, but it's ok atm
+ send_register_hook(
+ url,
+ state.settings.register_webhook_username.clone(),
+ register.username,
+ )
+ .await;
+ }
+
match db.add_session(&new_session).await {
Ok(_) => Ok(Json(RegisterResponse { session: token })),
Err(e) => {
diff --git a/atuin-server/src/settings.rs b/atuin-server/src/settings.rs
index 8da0c0aa..b689983c 100644
--- a/atuin-server/src/settings.rs
+++ b/atuin-server/src/settings.rs
@@ -15,6 +15,8 @@ pub struct Settings {
pub db_uri: String,
pub open_registration: bool,
pub max_history_length: usize,
+ pub register_webhook_url: Option<String>,
+ pub register_webhook_username: String,
}
impl Settings {
@@ -37,6 +39,7 @@ impl Settings {
.set_default("open_registration", false)?
.set_default("max_history_length", 8192)?
.set_default("path", "")?
+ .set_default("register_webhook_username", "")?
.add_source(
Environment::with_prefix("atuin")
.prefix_separator("_")