feature flag for referrals (#1513)

This commit is contained in:
Brandon Thomas authored and GitHub committed 2026-05-13 22:45:11 -04:00
1 parent 2de8ce7044
commit b1101b1ac8
3 files changed
+24 -1

No files matched your search

@@ -40,6 +40,10 @@ pub enum UserFeatureFlag {
/// Access to Happy Horse (with a rate limit)
#[serde(rename = "hh_rl")]
HappyHorseRateLimit,
/// Access to the referrals program
#[serde(rename = "referrals")]
ReferralsProgram,
}
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
@@ -58,6 +62,7 @@ impl UserFeatureFlag {
Self::SeedanceWhitelist => "sd_wl",
Self::HappyHorse => "hh",
Self::HappyHorseRateLimit => "hh_rl",
Self::ReferralsProgram => "referrals",
}
}
@@ -70,6 +75,7 @@ impl UserFeatureFlag {
"sd_wl" => Ok(Self::SeedanceWhitelist),
"hh" => Ok(Self::HappyHorse),
"hh_rl" => Ok(Self::HappyHorseRateLimit),
"referrals" => Ok(Self::ReferralsProgram),
_ => Err(format!("invalid value: {:?}", value)),
}
}
@@ -83,6 +89,7 @@ impl UserFeatureFlag {
Self::SeedanceWhitelist => "DO NOT USE: Seedance Whitelist (legacy)",
Self::HappyHorse => "Happy Horse (no Rate Limit)",
Self::HappyHorseRateLimit => "Happy Horse (with Rate Limit)",
Self::ReferralsProgram => "Referrals Program",
}
}
@@ -95,6 +102,7 @@ impl UserFeatureFlag {
Self::SeedanceWhitelist => "DO NOT USE THIS. IT WILL BREAK ACCOUNTS.",
Self::HappyHorse => "Access to Happy Horse (without a rate limit - dangerous)",
Self::HappyHorseRateLimit => "Access to Happy Horse (with a rate limit)",
Self::ReferralsProgram => "Access to the referrals program",
}
}
@@ -109,6 +117,7 @@ impl UserFeatureFlag {
Self::SeedanceWhitelist,
Self::HappyHorse,
Self::HappyHorseRateLimit,
Self::ReferralsProgram,
])
}
}
@@ -130,6 +139,7 @@ mod tests {
assert_serialization(UserFeatureFlag::SeedanceWhitelist, "sd_wl");
assert_serialization(UserFeatureFlag::HappyHorse, "hh");
assert_serialization(UserFeatureFlag::HappyHorseRateLimit, "hh_rl");
assert_serialization(UserFeatureFlag::ReferralsProgram, "referrals");
}
#[test]
@@ -141,6 +151,7 @@ mod tests {
assert_eq!(UserFeatureFlag::SeedanceWhitelist.to_str(), "sd_wl");
assert_eq!(UserFeatureFlag::HappyHorse.to_str(), "hh");
assert_eq!(UserFeatureFlag::HappyHorseRateLimit.to_str(), "hh_rl");
assert_eq!(UserFeatureFlag::ReferralsProgram.to_str(), "referrals");
}
#[test]
@@ -152,13 +163,14 @@ mod tests {
assert_eq!(UserFeatureFlag::from_str("sd_wl").unwrap(), UserFeatureFlag::SeedanceWhitelist);
assert_eq!(UserFeatureFlag::from_str("hh").unwrap(), UserFeatureFlag::HappyHorse);
assert_eq!(UserFeatureFlag::from_str("hh_rl").unwrap(), UserFeatureFlag::HappyHorseRateLimit);
assert_eq!(UserFeatureFlag::from_str("referrals").unwrap(), UserFeatureFlag::ReferralsProgram);
assert!(UserFeatureFlag::from_str("foo").is_err());
}
#[test]
fn all_variants() {
let mut variants = UserFeatureFlag::all_variants();
assert_eq!(variants.len(), 7);
assert_eq!(variants.len(), 8);
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::ExploreMedia));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::Studio));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::Upload3d));
@@ -166,6 +178,7 @@ mod tests {
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::SeedanceWhitelist));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::HappyHorse));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::HappyHorseRateLimit));
assert_eq!(variants.pop_first(), Some(UserFeatureFlag::ReferralsProgram));
assert_eq!(variants.pop_first(), None);
}
}
@@ -7,6 +7,7 @@ use utoipa::ToSchema;
use artcraft_api_defs::user_referral_codes::create_referral_code::{CreateReferralCodeRequest, CreateReferralCodeResponse};
use crate::http_server::common_responses::advanced_common_web_error::AdvancedCommonWebError;
use crate::http_server::session::lookup::user_session_feature_flags::UserSessionFeatureFlags;
use crate::state::server_state::ServerState;
use mysql_queries::errors::database_insert_error::DatabaseInsertError;
use mysql_queries::queries::user_referral_codes::create_referral_code::{create_referral_code, CreateReferralCodeArgs};
@@ -49,6 +50,11 @@ pub async fn create_referral_code_handler(
_ => return Err(AdvancedCommonWebError::NotAuthorized),
};
let feature_flags = UserSessionFeatureFlags::new(user_session.maybe_feature_flags.as_deref());
if !feature_flags.can_use_referrals_program() {
return Err(AdvancedCommonWebError::NotAuthorized);
}
let user_token = &user_session.user_token;
// Validate code: trim, check length, check characters.
@@ -97,6 +97,10 @@ impl UserSessionFeatureFlags {
pub fn can_use_happy_horse_rate_limited(&self) -> bool {
self.feature_flags.contains(&UserFeatureFlag::HappyHorseRateLimit)
}
pub fn can_use_referrals_program(&self) -> bool {
self.feature_flags.contains(&UserFeatureFlag::ReferralsProgram)
}
}
#[cfg(test)]