Our Personal Data Server from scratch!
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: allow setting up SSO with environment

This is particularly useful in nix to avoid having to put secrets in
your configuration (or use some workaround) - but is probably quite
useful in other environments too and is a nice part of allowing either
environment or toml configuration.

To do this, I've had to split up the providers so as to provide
individual environment keys - I'm sure there's some clever macro that
could do this in fewer lines and more complexity

authored by

Skyler Grey and committed by tangled.org 559cbc10 18cdb612

+213 -50
+191 -50
crates/tranquil-config/src/lib.rs
··· 258 258 // -- SSO providers ---------------------------------------------------- 259 259 self.validate_sso_provider("sso.github", &self.sso.github, &mut errors); 260 260 self.validate_sso_provider("sso.google", &self.sso.google, &mut errors); 261 - self.validate_sso_discord(&mut errors); 261 + self.validate_sso_provider("sso.discord", &self.sso.discord, &mut errors); 262 262 self.validate_sso_with_issuer("sso.gitlab", &self.sso.gitlab, &mut errors); 263 263 self.validate_sso_with_issuer("sso.oidc", &self.sso.oidc, &mut errors); 264 264 self.validate_sso_apple(&mut errors); ··· 300 300 } 301 301 } 302 302 303 - fn validate_sso_provider(&self, prefix: &str, p: &SsoProviderConfig, errors: &mut Vec<String>) { 304 - if p.enabled { 305 - if p.client_id.is_none() { 303 + fn validate_sso_provider( 304 + &self, 305 + prefix: &str, 306 + p: &impl SsoProviderConfig, 307 + errors: &mut Vec<String>, 308 + ) { 309 + if p.get_enabled() { 310 + if p.get_client_id().is_none() { 306 311 errors.push(format!( 307 312 "{prefix}.client_id is required when {prefix}.enabled = true" 308 313 )); 309 314 } 310 - if p.client_secret.is_none() { 315 + if p.get_client_secret().is_none() { 311 316 errors.push(format!( 312 317 "{prefix}.client_secret is required when {prefix}.enabled = true" 313 318 )); ··· 315 320 } 316 321 } 317 322 318 - fn validate_sso_discord(&self, errors: &mut Vec<String>) { 319 - let p = &self.sso.discord; 320 - if p.enabled { 321 - if p.client_id.is_none() { 322 - errors.push( 323 - "sso.discord.client_id is required when sso.discord.enabled = true".to_string(), 324 - ); 325 - } 326 - if p.client_secret.is_none() { 327 - errors.push( 328 - "sso.discord.client_secret is required when sso.discord.enabled = true" 329 - .to_string(), 330 - ); 331 - } 332 - } 333 - } 334 - 335 323 fn validate_sso_with_issuer( 336 324 &self, 337 325 prefix: &str, 338 - p: &SsoProviderWithIssuerConfig, 326 + p: &(impl SsoProviderConfig + SsoProviderIssuerConfig), 339 327 errors: &mut Vec<String>, 340 328 ) { 341 - if p.enabled { 342 - if p.client_id.is_none() { 343 - errors.push(format!( 344 - "{prefix}.client_id is required when {prefix}.enabled = true" 345 - )); 346 - } 347 - if p.client_secret.is_none() { 348 - errors.push(format!( 349 - "{prefix}.client_secret is required when {prefix}.enabled = true" 350 - )); 351 - } 352 - if p.issuer.is_none() { 329 + self.validate_sso_provider(prefix, p, errors); 330 + if p.get_enabled() { 331 + if p.get_issuer().is_none() { 353 332 errors.push(format!( 354 333 "{prefix}.issuer is required when {prefix}.enabled = true" 355 334 )); ··· 772 751 pub batch_size: i64, 773 752 } 774 753 754 + pub trait SsoProviderConfig { 755 + fn get_enabled(&self) -> bool; 756 + fn get_client_id(&self) -> &Option<String>; 757 + fn get_client_secret(&self) -> &Option<String>; 758 + fn get_display_name(&self) -> &Option<String>; 759 + } 760 + 761 + pub trait SsoProviderIssuerConfig { 762 + fn get_issuer(&self) -> &Option<String>; 763 + } 764 + 775 765 #[derive(Debug, Config)] 776 766 pub struct SsoConfig { 777 767 #[config(nested)] 778 - pub github: SsoProviderConfig, 768 + pub github: SsoGitHubConfig, 779 769 780 770 #[config(nested)] 781 - pub discord: SsoDiscordProviderConfig, 771 + pub discord: SsoDiscordConfig, 782 772 783 773 #[config(nested)] 784 - pub google: SsoProviderConfig, 774 + pub google: SsoGoogleConfig, 785 775 786 776 #[config(nested)] 787 - pub gitlab: SsoProviderWithIssuerConfig, 777 + pub gitlab: SsoGitLabConfig, 788 778 789 779 #[config(nested)] 790 - pub oidc: SsoProviderWithIssuerConfig, 780 + pub oidc: SsoOidcConfig, 791 781 792 782 #[config(nested)] 793 783 pub apple: SsoAppleConfig, 794 784 } 795 785 796 - // Generic SSO provider (GitHub, Google) 797 786 #[derive(Debug, Config)] 798 - pub struct SsoProviderConfig { 799 - #[config(default = false)] 787 + pub struct SsoGitHubConfig { 788 + #[config(env = "SSO_GITHUB_ENABLED", default = false)] 800 789 pub enabled: bool, 790 + 791 + #[config(env = "SSO_GITHUB_CLIENT_ID")] 801 792 pub client_id: Option<String>, 793 + 794 + #[config(env = "SSO_GITHUB_CLIENT_SECRET")] 802 795 pub client_secret: Option<String>, 796 + 797 + #[config(env = "SSO_GITHUB_DISPLAY_NAME")] 803 798 pub display_name: Option<String>, 804 799 } 805 800 806 - // SSO provider with custom env prefixes for Discord 807 - // (since the nested TOML key is `sso.discord` but env vars are `SSO_DISCORD_*`) 801 + impl SsoProviderConfig for SsoGitHubConfig { 802 + fn get_enabled(&self) -> bool { 803 + self.enabled 804 + } 805 + 806 + fn get_client_id(&self) -> &Option<String> { 807 + &self.client_id 808 + } 809 + 810 + fn get_client_secret(&self) -> &Option<String> { 811 + &self.client_secret 812 + } 813 + 814 + fn get_display_name(&self) -> &Option<String> { 815 + &self.display_name 816 + } 817 + } 818 + 808 819 #[derive(Debug, Config)] 809 - pub struct SsoDiscordProviderConfig { 810 - #[config(default = false)] 820 + pub struct SsoDiscordConfig { 821 + #[config(env = "SSO_DISCORD_ENABLED", default = false)] 811 822 pub enabled: bool, 823 + 824 + #[config(env = "SSO_DISCORD_CLIENT_ID")] 812 825 pub client_id: Option<String>, 826 + 827 + #[config(env = "SSO_DISCORD_CLIENT_SECRET")] 813 828 pub client_secret: Option<String>, 829 + 830 + #[config(env = "SSO_DISCORD_DISPLAY_NAME")] 814 831 pub display_name: Option<String>, 815 832 } 816 833 817 - // SSO providers that require an issuer URL (GitLab, OIDC) 834 + impl SsoProviderConfig for SsoDiscordConfig { 835 + fn get_enabled(&self) -> bool { 836 + self.enabled 837 + } 838 + 839 + fn get_client_id(&self) -> &Option<String> { 840 + &self.client_id 841 + } 842 + 843 + fn get_client_secret(&self) -> &Option<String> { 844 + &self.client_secret 845 + } 846 + 847 + fn get_display_name(&self) -> &Option<String> { 848 + &self.display_name 849 + } 850 + } 851 + 818 852 #[derive(Debug, Config)] 819 - pub struct SsoProviderWithIssuerConfig { 820 - #[config(default = false)] 853 + pub struct SsoGoogleConfig { 854 + #[config(env = "SSO_GOOGLE_ENABLED", default = false)] 821 855 pub enabled: bool, 856 + 857 + #[config(env = "SSO_GOOGLE_CLIENT_ID")] 822 858 pub client_id: Option<String>, 859 + 860 + #[config(env = "SSO_GOOGLE_CLIENT_SECRET")] 823 861 pub client_secret: Option<String>, 862 + 863 + #[config(env = "SSO_GOOGLE_DISPLAY_NAME")] 864 + pub display_name: Option<String>, 865 + } 866 + 867 + impl SsoProviderConfig for SsoGoogleConfig { 868 + fn get_enabled(&self) -> bool { 869 + self.enabled 870 + } 871 + 872 + fn get_client_id(&self) -> &Option<String> { 873 + &self.client_id 874 + } 875 + 876 + fn get_client_secret(&self) -> &Option<String> { 877 + &self.client_secret 878 + } 879 + 880 + fn get_display_name(&self) -> &Option<String> { 881 + &self.display_name 882 + } 883 + } 884 + 885 + #[derive(Debug, Config)] 886 + pub struct SsoGitLabConfig { 887 + #[config(env = "SSO_GITLAB_ENABLED", default = false)] 888 + pub enabled: bool, 889 + 890 + #[config(env = "SSO_GITLAB_CLIENT_ID")] 891 + pub client_id: Option<String>, 892 + 893 + #[config(env = "SSO_GITLAB_CLIENT_SECRET")] 894 + pub client_secret: Option<String>, 895 + 896 + #[config(env = "SSO_GITLAB_ISSUER")] 824 897 pub issuer: Option<String>, 898 + 899 + #[config(env = "SSO_GITLAB_DISPLAY_NAME")] 825 900 pub display_name: Option<String>, 901 + } 902 + 903 + impl SsoProviderConfig for SsoGitLabConfig { 904 + fn get_enabled(&self) -> bool { 905 + self.enabled 906 + } 907 + 908 + fn get_client_id(&self) -> &Option<String> { 909 + &self.client_id 910 + } 911 + 912 + fn get_client_secret(&self) -> &Option<String> { 913 + &self.client_secret 914 + } 915 + 916 + fn get_display_name(&self) -> &Option<String> { 917 + &self.display_name 918 + } 919 + } 920 + 921 + impl SsoProviderIssuerConfig for SsoGitLabConfig { 922 + fn get_issuer(&self) -> &Option<String> { 923 + &self.issuer 924 + } 925 + } 926 + 927 + #[derive(Debug, Config)] 928 + pub struct SsoOidcConfig { 929 + #[config(env = "SSO_OIDC_ENABLED", default = false)] 930 + pub enabled: bool, 931 + 932 + #[config(env = "SSO_OIDC_CLIENT_ID")] 933 + pub client_id: Option<String>, 934 + 935 + #[config(env = "SSO_OIDC_CLIENT_SECRET")] 936 + pub client_secret: Option<String>, 937 + 938 + #[config(env = "SSO_OIDC_ISSUER")] 939 + pub issuer: Option<String>, 940 + 941 + #[config(env = "SSO_OIDC_DISPLAY_NAME")] 942 + pub display_name: Option<String>, 943 + } 944 + 945 + impl SsoProviderConfig for SsoOidcConfig { 946 + fn get_enabled(&self) -> bool { 947 + self.enabled 948 + } 949 + 950 + fn get_client_id(&self) -> &Option<String> { 951 + &self.client_id 952 + } 953 + 954 + fn get_client_secret(&self) -> &Option<String> { 955 + &self.client_secret 956 + } 957 + 958 + fn get_display_name(&self) -> &Option<String> { 959 + &self.display_name 960 + } 961 + } 962 + 963 + impl SsoProviderIssuerConfig for SsoOidcConfig { 964 + fn get_issuer(&self) -> &Option<String> { 965 + &self.issuer 966 + } 826 967 } 827 968 828 969 #[derive(Debug, Config)]
+22
example.toml
··· 390 390 391 391 [sso] 392 392 [sso.github] 393 + # Can also be specified via environment variable `SSO_GITHUB_ENABLED`. 393 394 # Default value: false 394 395 #enabled = false 395 396 397 + # Can also be specified via environment variable `SSO_GITHUB_CLIENT_ID`. 396 398 #client_id = 397 399 400 + # Can also be specified via environment variable `SSO_GITHUB_CLIENT_SECRET`. 398 401 #client_secret = 399 402 403 + # Can also be specified via environment variable `SSO_GITHUB_DISPLAY_NAME`. 400 404 #display_name = 401 405 402 406 [sso.discord] 407 + # Can also be specified via environment variable `SSO_DISCORD_ENABLED`. 403 408 # Default value: false 404 409 #enabled = false 405 410 411 + # Can also be specified via environment variable `SSO_DISCORD_CLIENT_ID`. 406 412 #client_id = 407 413 414 + # Can also be specified via environment variable `SSO_DISCORD_CLIENT_SECRET`. 408 415 #client_secret = 409 416 417 + # Can also be specified via environment variable `SSO_DISCORD_DISPLAY_NAME`. 410 418 #display_name = 411 419 412 420 [sso.google] 421 + # Can also be specified via environment variable `SSO_GOOGLE_ENABLED`. 413 422 # Default value: false 414 423 #enabled = false 415 424 425 + # Can also be specified via environment variable `SSO_GOOGLE_CLIENT_ID`. 416 426 #client_id = 417 427 428 + # Can also be specified via environment variable `SSO_GOOGLE_CLIENT_SECRET`. 418 429 #client_secret = 419 430 431 + # Can also be specified via environment variable `SSO_GOOGLE_DISPLAY_NAME`. 420 432 #display_name = 421 433 422 434 [sso.gitlab] 435 + # Can also be specified via environment variable `SSO_GITLAB_ENABLED`. 423 436 # Default value: false 424 437 #enabled = false 425 438 439 + # Can also be specified via environment variable `SSO_GITLAB_CLIENT_ID`. 426 440 #client_id = 427 441 442 + # Can also be specified via environment variable `SSO_GITLAB_CLIENT_SECRET`. 428 443 #client_secret = 429 444 445 + # Can also be specified via environment variable `SSO_GITLAB_ISSUER`. 430 446 #issuer = 431 447 448 + # Can also be specified via environment variable `SSO_GITLAB_DISPLAY_NAME`. 432 449 #display_name = 433 450 434 451 [sso.oidc] 452 + # Can also be specified via environment variable `SSO_OIDC_ENABLED`. 435 453 # Default value: false 436 454 #enabled = false 437 455 456 + # Can also be specified via environment variable `SSO_OIDC_CLIENT_ID`. 438 457 #client_id = 439 458 459 + # Can also be specified via environment variable `SSO_OIDC_CLIENT_SECRET`. 440 460 #client_secret = 441 461 462 + # Can also be specified via environment variable `SSO_OIDC_ISSUER`. 442 463 #issuer = 443 464 465 + # Can also be specified via environment variable `SSO_OIDC_DISPLAY_NAME`. 444 466 #display_name = 445 467 446 468 [sso.apple]