add flags (but need to expire the key)

This commit is contained in:
Brandon Thomas committed 2024-05-15 14:52:18 -07:00
1 parent 6d42b2bf44
commit 043f2dcc70
4 files changed
+210 -19

No files matched your search

@@ -0,0 +1,157 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n b.token as `token: tokens::tokens::beta_keys::BetaKeyToken`,\n\n b.product as `product: enums::by_table::beta_keys::beta_key_product::BetaKeyProduct`,\n b.key_value,\n\n b.maybe_referrer_user_token as `maybe_referrer_user_token: tokens::tokens::users::UserToken`,\n referrer.username as maybe_referrer_username,\n referrer.display_name as maybe_referrer_display_name,\n referrer.email_gravatar_hash as maybe_referrer_gravatar_hash,\n\n b.maybe_redeemer_user_token as `maybe_redeemer_user_token: tokens::tokens::users::UserToken`,\n redeemer.username as maybe_redeemer_username,\n redeemer.display_name as maybe_redeemer_display_name,\n redeemer.email_gravatar_hash as maybe_redeemer_gravatar_hash,\n\n b.created_at,\n b.maybe_redeemed_at\n\nFROM beta_keys AS b\n\nLEFT OUTER JOIN users AS referrer\n ON b.maybe_referrer_user_token = referrer.token\n\nLEFT OUTER JOIN users AS redeemer\n ON b.maybe_redeemer_user_token = redeemer.token\n\nWHERE\n b.key_value = ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "token: tokens::tokens::beta_keys::BetaKeyToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "product: enums::by_table::beta_keys::beta_key_product::BetaKeyProduct",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 2,
"name": "key_value",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "maybe_referrer_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_referrer_username",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 5,
"name": "maybe_referrer_display_name",
"type_info": {
"type": "VarString",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 6,
"name": "maybe_referrer_gravatar_hash",
"type_info": {
"type": "String",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_redeemer_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_redeemer_username",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 9,
"name": "maybe_redeemer_display_name",
"type_info": {
"type": "VarString",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 10,
"name": "maybe_redeemer_gravatar_hash",
"type_info": {
"type": "String",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 11,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 12,
"name": "maybe_redeemed_at",
"type_info": {
"type": "Timestamp",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
true,
false,
true
]
},
"hash": "74b401958826a7e640540f248114f57a941324787d023783f84251e8dd56eeb7"
}
@@ -1,16 +1,25 @@
use anyhow::anyhow;
use sqlx::MySqlPool;
use composite_identifiers::by_table::audit_logs::audit_log_entity::AuditLogEntity;
use enums::by_table::audit_logs::audit_log_entity_action::AuditLogEntityAction;
use errors::AnyhowResult;
use tokens::tokens::users::UserToken;
use crate::queries::audit_logs::insert_audit_log::{insert_audit_log, InsertAuditLogArgs};
pub struct SetUserFeatureFlagArgs<'a> {
// The action's target user token.
pub subject_user_token: &'a UserToken,
// Comma separated string of feature flags.
pub maybe_feature_flags: Option<&'a str>,
pub mod_user_token: &'a UserToken,
// Actor IP address.
pub ip_address: &'a str,
// If a moderator is changing the flags, the moderator user token
pub maybe_mod_user_token: Option<&'a UserToken>,
pub mysql_pool: &'a MySqlPool,
}
@@ -20,21 +29,32 @@ pub async fn set_user_feature_flags(args: SetUserFeatureFlagArgs<'_>) -> AnyhowR
UPDATE users
SET
maybe_feature_flags = ?,
maybe_mod_user_token = ?,
version = version + 1
WHERE users.token = ?
LIMIT 1
"#,
args.maybe_feature_flags,
args.mod_user_token,
args.subject_user_token,
)
.execute(args.mysql_pool)
.await;
match query_result {
Ok(_) => Ok(()),
Err(err) => Err(anyhow!("error with query: {:?}", err)),
if let Err(err) = query_result {
return Err(anyhow!("error with query: {:?}", err));
}
// NB: fail open
let _r = insert_audit_log(InsertAuditLogArgs {
entity: &AuditLogEntity::User(args.subject_user_token.clone()),
entity_action: AuditLogEntityAction::EditFeatures,
maybe_actor_user_token: args.maybe_mod_user_token,
maybe_actor_anonymous_visitor_token: None,
actor_ip_address: &args.ip_address,
is_actor_moderator: true,
mysql_executor: args.mysql_pool,
phantom: Default::default(),
}).await;
Ok(())
}
@@ -8,10 +8,12 @@ use log::warn;
use utoipa::ToSchema;
use enums::by_table::comments::comment_entity_type::CommentEntityType;
use enums::by_table::users::user_feature_flag::UserFeatureFlag;
use http_server_common::request::get_request_ip::get_request_ip;
use mysql_queries::queries::beta_keys::get_beta_key_by_value::get_beta_key_by_value;
use mysql_queries::queries::comments::comment_entity_token::CommentEntityToken;
use mysql_queries::queries::comments::insert_comment::{insert_comment, InsertCommentArgs};
use mysql_queries::queries::users::user::set_user_feature_flags::{set_user_feature_flags, SetUserFeatureFlagArgs};
use tokens::tokens::comments::CommentToken;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::model_weights::ModelWeightToken;
@@ -22,6 +24,7 @@ use tokens::tokens::w2l_results::W2lResultToken;
use tokens::tokens::w2l_templates::W2lTemplateToken;
use user_input_common::check_for_slurs::contains_slurs;
use user_input_common::markdown_to_html::markdown_to_html;
use users_component::session::lookup::user_session_feature_flags::UserSessionFeatureFlags;
use crate::http_server::endpoints::beta_keys::list_beta_keys_handler::ListBetaKeysError;
use crate::http_server::endpoints::moderation::user_feature_flags::edit_user_feature_flags_handler::EditUserFeatureFlagsError;
@@ -122,6 +125,28 @@ pub async fn redeem_beta_key_handler(
return Err(RedeemBetaKeyError::BadInput("beta key already redeemed".to_string()));
}
let mut user_feature_flags =
UserSessionFeatureFlags::new(user_session.maybe_feature_flags.as_deref());
user_feature_flags.add_flags([
UserFeatureFlag::Studio,
UserFeatureFlag::VideoStyleTransfer,
]);
let ip_address = get_request_ip(&http_request);
set_user_feature_flags(SetUserFeatureFlagArgs {
subject_user_token: &user_session.user_token,
maybe_feature_flags: user_feature_flags.maybe_serialize_string().as_deref(),
maybe_mod_user_token: None,
ip_address: &ip_address,
mysql_pool: &server_state.mysql_pool,
}).await
.map_err(|e| {
warn!("Could not set flags: {:?}", e);
RedeemBetaKeyError::ServerError
})?;
let response = RedeemBetaKeySuccessResponse {
success: true,
};
@@ -198,7 +198,8 @@ pub async fn edit_user_feature_flags_handler(
set_user_feature_flags(SetUserFeatureFlagArgs {
subject_user_token: &user_profile.user_token,
maybe_feature_flags: user_feature_flags.maybe_serialize_string().as_deref(),
mod_user_token: &user_session.user_token,
maybe_mod_user_token: Some(&user_session.user_token),
ip_address: &ip_address,
mysql_pool: &server_state.mysql_pool,
}).await
.map_err(|e| {
@@ -206,18 +207,6 @@ pub async fn edit_user_feature_flags_handler(
EditUserFeatureFlagsError::ServerError
})?;
// NB: fail open
let _r = insert_audit_log(InsertAuditLogArgs {
entity: &AuditLogEntity::User(user_profile.user_token),
entity_action: AuditLogEntityAction::EditFeatures,
maybe_actor_user_token: Some(&user_session.user_token),
maybe_actor_anonymous_visitor_token: None,
actor_ip_address: &ip_address,
is_actor_moderator: true,
mysql_executor: &server_state.mysql_pool,
phantom: Default::default(),
}).await;
//if let Ok(mut redis) = redis_ttl_cache.get_connection() {
// // TODO(bt,2024-04-20): This should be coordinated with other code.
// let cache_key = format!("cache:userProfile:{}", user_profile.username);