Skip to content

Commit f2c0815

Browse files
committed
refactor: replace shared secret types with domain-specific value objects
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
1 parent 009c701 commit f2c0815

15 files changed

Lines changed: 184 additions & 120 deletions

File tree

rsworkspace/crates/trogon-gateway/src/config.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ use std::time::Duration;
44

55
use confique::Config;
66
use trogon_nats::{NatsAuth, NatsToken};
7-
use trogon_std::{BotToken, SigningSecret, WebhookSecret};
7+
use trogon_source_discord::config::DiscordBotToken;
8+
use trogon_source_github::config::GitHubWebhookSecret;
9+
use trogon_source_gitlab::config::GitLabWebhookSecret;
10+
use trogon_source_linear::config::LinearWebhookSecret;
11+
use trogon_source_slack::config::SlackSigningSecret;
12+
use trogon_source_telegram::config::TelegramWebhookSecret;
813

914
#[derive(Debug)]
1015
pub enum ConfigError {
@@ -32,19 +37,17 @@ impl std::error::Error for ConfigError {}
3237
#[derive(Config)]
3338
struct GatewayConfig {
3439
#[config(nested)]
35-
server: ServerConfig,
40+
http_server: HttpServerConfig,
3641
#[config(nested)]
3742
nats: NatsConfig,
3843
#[config(nested)]
3944
sources: SourcesConfig,
4045
}
4146

4247
#[derive(Config)]
43-
struct ServerConfig {
48+
struct HttpServerConfig {
4449
#[config(env = "TROGON_GATEWAY_PORT", default = 8080)]
4550
port: u16,
46-
#[config(env = "TROGON_GATEWAY_BODY_LIMIT_BYTES", default = 2_097_152)]
47-
body_limit_bytes: usize,
4851
}
4952

5053
#[derive(Config)]
@@ -175,13 +178,12 @@ struct LinearConfig {
175178
timestamp_tolerance_secs: u64,
176179
}
177180

178-
pub struct ResolvedServerConfig {
181+
pub struct ResolvedHttpServerConfig {
179182
pub port: u16,
180-
pub body_limit_bytes: usize,
181183
}
182184

183185
pub struct ResolvedConfig {
184-
pub server: ResolvedServerConfig,
186+
pub http_server: ResolvedHttpServerConfig,
185187
pub nats: trogon_nats::NatsConfig,
186188
pub github: Option<trogon_source_github::GithubConfig>,
187189
pub discord: Option<trogon_source_discord::DiscordConfig>,
@@ -227,9 +229,8 @@ fn resolve(cfg: GatewayConfig) -> Result<ResolvedConfig, ConfigError> {
227229
}
228230

229231
Ok(ResolvedConfig {
230-
server: ResolvedServerConfig {
231-
port: cfg.server.port,
232-
body_limit_bytes: cfg.server.body_limit_bytes,
232+
http_server: ResolvedHttpServerConfig {
233+
port: cfg.http_server.port,
233234
},
234235
nats,
235236
github,
@@ -279,7 +280,7 @@ fn resolve_github(
279280
) -> Option<trogon_source_github::GithubConfig> {
280281
let secret_str = section.webhook_secret.filter(|s| !s.is_empty())?;
281282

282-
let webhook_secret = match WebhookSecret::new(secret_str) {
283+
let webhook_secret = match GitHubWebhookSecret::new(secret_str) {
283284
Ok(s) => s,
284285
Err(e) => {
285286
errors.push(format!("github: invalid webhook_secret: {e}"));
@@ -325,7 +326,7 @@ fn resolve_discord(
325326
return None;
326327
};
327328

328-
let bot_token = match BotToken::new(token_str) {
329+
let bot_token = match DiscordBotToken::new(token_str) {
329330
Ok(s) => s,
330331
Err(e) => {
331332
errors.push(format!("discord: invalid bot_token: {e}"));
@@ -404,7 +405,7 @@ fn resolve_slack(
404405
) -> Option<trogon_source_slack::SlackConfig> {
405406
let secret_str = section.signing_secret.filter(|s| !s.is_empty())?;
406407

407-
let signing_secret = match SigningSecret::new(secret_str) {
408+
let signing_secret = match SlackSigningSecret::new(secret_str) {
408409
Ok(s) => s,
409410
Err(e) => {
410411
errors.push(format!("slack: invalid signing_secret: {e}"));
@@ -444,7 +445,7 @@ fn resolve_telegram(
444445
) -> Option<trogon_source_telegram::TelegramSourceConfig> {
445446
let secret_str = section.webhook_secret.filter(|s| !s.is_empty())?;
446447

447-
let webhook_secret = match WebhookSecret::new(secret_str) {
448+
let webhook_secret = match TelegramWebhookSecret::new(secret_str) {
448449
Ok(s) => s,
449450
Err(e) => {
450451
errors.push(format!("telegram: invalid webhook_secret: {e}"));
@@ -483,7 +484,7 @@ fn resolve_gitlab(
483484
) -> Option<trogon_source_gitlab::GitlabConfig> {
484485
let webhook_secret_str = section.webhook_secret.filter(|s| !s.is_empty())?;
485486

486-
let webhook_secret = match WebhookSecret::new(webhook_secret_str) {
487+
let webhook_secret = match GitLabWebhookSecret::new(webhook_secret_str) {
487488
Ok(s) => s,
488489
Err(e) => {
489490
errors.push(format!("gitlab: invalid webhook_secret: {e}"));
@@ -522,7 +523,7 @@ fn resolve_linear(
522523
) -> Option<trogon_source_linear::LinearConfig> {
523524
let secret_str = section.webhook_secret.filter(|s| !s.is_empty())?;
524525

525-
let webhook_secret = match WebhookSecret::new(secret_str) {
526+
let webhook_secret = match LinearWebhookSecret::new(secret_str) {
526527
Ok(s) => s,
527528
Err(e) => {
528529
errors.push(format!("linear: invalid webhook_secret: {e}"));

rsworkspace/crates/trogon-gateway/src/serve.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,11 @@ where
7171

7272
provision_streams(&client, &resolved).await?;
7373

74-
let port = resolved.server.port;
75-
let body_limit = resolved.server.body_limit_bytes;
76-
let mut app = Router::new()
77-
.route(
78-
"/health",
79-
axum::routing::get(|| async { axum::http::StatusCode::OK }),
80-
)
81-
.layer(axum::extract::DefaultBodyLimit::max(body_limit));
74+
let port = resolved.http_server.port;
75+
let mut app = Router::new().route(
76+
"/health",
77+
axum::routing::get(|| async { axum::http::StatusCode::OK }),
78+
);
8279
let mut join_set: JoinSet<SourceResult> = JoinSet::new();
8380

8481
mount_sources(

rsworkspace/crates/trogon-source-discord/src/config.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,31 @@ use std::time::Duration;
33

44
use ed25519_dalek::VerifyingKey;
55
use trogon_nats::NatsToken;
6-
use trogon_std::BotToken;
6+
use trogon_std::{EmptySecret, SecretString};
7+
8+
#[derive(Clone)]
9+
pub struct DiscordBotToken(SecretString);
10+
11+
impl DiscordBotToken {
12+
pub fn new(s: impl AsRef<str>) -> Result<Self, EmptySecret> {
13+
SecretString::new(s).map(Self)
14+
}
15+
16+
pub fn as_str(&self) -> &str {
17+
self.0.as_str()
18+
}
19+
}
20+
21+
impl fmt::Debug for DiscordBotToken {
22+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23+
f.write_str("DiscordBotToken(****)")
24+
}
25+
}
726
use twilight_model::gateway::Intents;
827

928
pub enum SourceMode {
1029
Gateway {
11-
bot_token: BotToken,
30+
bot_token: DiscordBotToken,
1231
intents: Intents,
1332
},
1433
Webhook {

rsworkspace/crates/trogon-source-github/src/config.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,30 @@
1+
use std::fmt;
12
use std::time::Duration;
23

34
use trogon_nats::NatsToken;
4-
use trogon_std::WebhookSecret;
5+
use trogon_std::{EmptySecret, SecretString};
6+
7+
#[derive(Clone)]
8+
pub struct GitHubWebhookSecret(SecretString);
9+
10+
impl GitHubWebhookSecret {
11+
pub fn new(s: impl AsRef<str>) -> Result<Self, EmptySecret> {
12+
SecretString::new(s).map(Self)
13+
}
14+
15+
pub fn as_str(&self) -> &str {
16+
self.0.as_str()
17+
}
18+
}
19+
20+
impl fmt::Debug for GitHubWebhookSecret {
21+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22+
f.write_str("GitHubWebhookSecret(****)")
23+
}
24+
}
525

626
pub struct GithubConfig {
7-
pub webhook_secret: WebhookSecret,
27+
pub webhook_secret: GitHubWebhookSecret,
828
pub subject_prefix: NatsToken,
929
pub stream_name: NatsToken,
1030
pub stream_max_age: Duration,

rsworkspace/crates/trogon-source-github/src/server.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fmt;
22
use std::time::Duration;
33

4+
use crate::config::GitHubWebhookSecret;
45
use crate::config::GithubConfig;
56
use crate::constants::{
67
HEADER_DELIVERY, HEADER_EVENT, HEADER_SIGNATURE, HTTP_BODY_SIZE_MAX, NATS_HEADER_DELIVERY,
@@ -18,7 +19,6 @@ use trogon_nats::NatsToken;
1819
use trogon_nats::jetstream::{
1920
ClaimCheckPublisher, JetStreamContext, JetStreamPublisher, ObjectStorePut, PublishOutcome,
2021
};
21-
use trogon_std::WebhookSecret;
2222

2323
fn outcome_to_status<E: fmt::Display>(outcome: PublishOutcome<E>) -> StatusCode {
2424
if outcome.is_ok() {
@@ -33,7 +33,7 @@ fn outcome_to_status<E: fmt::Display>(outcome: PublishOutcome<E>) -> StatusCode
3333
#[derive(Clone)]
3434
struct AppState<P: JetStreamPublisher, S: ObjectStorePut> {
3535
publisher: ClaimCheckPublisher<P, S>,
36-
webhook_secret: WebhookSecret,
36+
webhook_secret: GitHubWebhookSecret,
3737
subject_prefix: NatsToken,
3838
nats_ack_timeout: Duration,
3939
}
@@ -183,7 +183,7 @@ mod tests {
183183

184184
fn test_config() -> GithubConfig {
185185
GithubConfig {
186-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
186+
webhook_secret: GitHubWebhookSecret::new(TEST_SECRET).unwrap(),
187187
subject_prefix: NatsToken::new("github").unwrap(),
188188
stream_name: NatsToken::new("GITHUB").unwrap(),
189189
stream_max_age: Duration::from_secs(3600),
@@ -376,7 +376,7 @@ mod tests {
376376

377377
let state = AppState {
378378
publisher: wrap_publisher(publisher.clone()),
379-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
379+
webhook_secret: GitHubWebhookSecret::new(TEST_SECRET).unwrap(),
380380
subject_prefix: NatsToken::new("custom").unwrap(),
381381
nats_ack_timeout: Duration::from_secs(10),
382382
};
@@ -532,7 +532,7 @@ mod tests {
532532
"test-bucket".to_string(),
533533
MaxPayload::from_server_limit(usize::MAX),
534534
),
535-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
535+
webhook_secret: GitHubWebhookSecret::new(TEST_SECRET).unwrap(),
536536
subject_prefix: NatsToken::new("github").unwrap(),
537537
nats_ack_timeout: Duration::from_secs(10),
538538
};
@@ -567,7 +567,7 @@ mod tests {
567567
"test-bucket".to_string(),
568568
MaxPayload::from_server_limit(usize::MAX),
569569
),
570-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
570+
webhook_secret: GitHubWebhookSecret::new(TEST_SECRET).unwrap(),
571571
subject_prefix: NatsToken::new("github").unwrap(),
572572
nats_ack_timeout: Duration::from_millis(10),
573573
};

rsworkspace/crates/trogon-source-gitlab/src/config.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,30 @@
1+
use std::fmt;
12
use std::time::Duration;
23

34
use trogon_nats::NatsToken;
4-
use trogon_std::WebhookSecret;
5+
use trogon_std::{EmptySecret, SecretString};
6+
7+
#[derive(Clone)]
8+
pub struct GitLabWebhookSecret(SecretString);
9+
10+
impl GitLabWebhookSecret {
11+
pub fn new(s: impl AsRef<str>) -> Result<Self, EmptySecret> {
12+
SecretString::new(s).map(Self)
13+
}
14+
15+
pub fn as_str(&self) -> &str {
16+
self.0.as_str()
17+
}
18+
}
19+
20+
impl fmt::Debug for GitLabWebhookSecret {
21+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22+
f.write_str("GitLabWebhookSecret(****)")
23+
}
24+
}
525

626
pub struct GitlabConfig {
7-
pub webhook_secret: WebhookSecret,
27+
pub webhook_secret: GitLabWebhookSecret,
828
pub subject_prefix: NatsToken,
929
pub stream_name: NatsToken,
1030
pub stream_max_age: Duration,

rsworkspace/crates/trogon-source-gitlab/src/server.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fmt;
22
use std::time::Duration;
33

4+
use crate::config::GitLabWebhookSecret;
45
use crate::config::GitlabConfig;
56
use crate::constants::{
67
HEADER_EVENT, HEADER_EVENT_UUID, HEADER_IDEMPOTENCY_KEY, HEADER_INSTANCE, HEADER_TOKEN,
@@ -19,7 +20,6 @@ use trogon_nats::NatsToken;
1920
use trogon_nats::jetstream::{
2021
ClaimCheckPublisher, JetStreamContext, JetStreamPublisher, ObjectStorePut, PublishOutcome,
2122
};
22-
use trogon_std::WebhookSecret;
2323

2424
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2525
enum RejectReason {
@@ -73,7 +73,7 @@ fn outcome_to_status<E: fmt::Display>(outcome: PublishOutcome<E>) -> StatusCode
7373
#[derive(Clone)]
7474
struct AppState<P: JetStreamPublisher, S: ObjectStorePut> {
7575
publisher: ClaimCheckPublisher<P, S>,
76-
webhook_secret: WebhookSecret,
76+
webhook_secret: GitLabWebhookSecret,
7777
subject_prefix: NatsToken,
7878
nats_ack_timeout: Duration,
7979
}
@@ -243,7 +243,7 @@ mod tests {
243243

244244
fn test_config() -> GitlabConfig {
245245
GitlabConfig {
246-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
246+
webhook_secret: GitLabWebhookSecret::new(TEST_SECRET).unwrap(),
247247
subject_prefix: NatsToken::new("gitlab").unwrap(),
248248
stream_name: NatsToken::new("GITLAB").unwrap(),
249249
stream_max_age: Duration::from_secs(3600),
@@ -464,7 +464,7 @@ mod tests {
464464

465465
let state = AppState {
466466
publisher: wrap_publisher(publisher.clone()),
467-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
467+
webhook_secret: GitLabWebhookSecret::new(TEST_SECRET).unwrap(),
468468
subject_prefix: NatsToken::new("custom").unwrap(),
469469
nats_ack_timeout: Duration::from_secs(10),
470470
};
@@ -508,7 +508,7 @@ mod tests {
508508

509509
let state = AppState {
510510
publisher: wrap_publisher(publisher.clone()),
511-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
511+
webhook_secret: GitLabWebhookSecret::new(TEST_SECRET).unwrap(),
512512
subject_prefix: NatsToken::new("gitlab").unwrap(),
513513
nats_ack_timeout: Duration::from_secs(10),
514514
};
@@ -668,7 +668,7 @@ mod tests {
668668
"test-bucket".to_string(),
669669
MaxPayload::from_server_limit(usize::MAX),
670670
),
671-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
671+
webhook_secret: GitLabWebhookSecret::new(TEST_SECRET).unwrap(),
672672
subject_prefix: NatsToken::new("gitlab").unwrap(),
673673
nats_ack_timeout: Duration::from_secs(10),
674674
};
@@ -701,7 +701,7 @@ mod tests {
701701
"test-bucket".to_string(),
702702
MaxPayload::from_server_limit(usize::MAX),
703703
),
704-
webhook_secret: WebhookSecret::new(TEST_SECRET).unwrap(),
704+
webhook_secret: GitLabWebhookSecret::new(TEST_SECRET).unwrap(),
705705
subject_prefix: NatsToken::new("gitlab").unwrap(),
706706
nats_ack_timeout: Duration::from_millis(10),
707707
};

0 commit comments

Comments
 (0)