mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 17:08:13 +00:00
insert beta keys should work
This commit is contained in:
1 parent
181efc0b94
commit
df3ec24d27
12 files changed
+269
-5
No files matched your search
Generated
+1
@@ -6355,6 +6355,7 @@ dependencies = [
|
||||
"config",
|
||||
"container_common",
|
||||
"cookies",
|
||||
"crockford",
|
||||
"data-encoding",
|
||||
"datetimes",
|
||||
"derive_more",
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Used in the `batch_generations` table in a `VARCHAR(32)` field named `entity_type`.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Ord, PartialOrd, ToSchema)]
|
||||
pub enum BetaKeyProduct {
|
||||
/// Media files
|
||||
/// This will probably be the only type supported, but we'll leave the possibility of future types.
|
||||
#[serde(rename = "studio")]
|
||||
Studio,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(BetaKeyProduct);
|
||||
impl_mysql_enum_coders!(BetaKeyProduct);
|
||||
impl_mysql_from_row!(BetaKeyProduct);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl BetaKeyProduct {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Studio => "studio",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"studio" => Ok(Self::Studio),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
// NB: BTreeSet is sorted
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
Self::Studio,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::beta_keys::beta_key_product::BetaKeyProduct;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(BetaKeyProduct::Studio, "studio");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(BetaKeyProduct::Studio.to_str(), "studio");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(BetaKeyProduct::from_str("studio").unwrap(), BetaKeyProduct::Studio);
|
||||
assert!(BetaKeyProduct::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
mod manual_variant_checks {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = BetaKeyProduct::all_variants();
|
||||
assert_eq!(variants.len(), 1);
|
||||
assert_eq!(variants.pop_first(), Some(BetaKeyProduct::Studio));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
}
|
||||
}
|
||||
|
||||
mod mechanical_checks {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn variant_length() {
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(BetaKeyProduct::all_variants().len(), BetaKeyProduct::iter().len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
for variant in BetaKeyProduct::all_variants() {
|
||||
assert_eq!(variant, BetaKeyProduct::from_str(variant.to_str()).unwrap());
|
||||
assert_eq!(variant, BetaKeyProduct::from_str(&format!("{}", variant)).unwrap());
|
||||
assert_eq!(variant, BetaKeyProduct::from_str(&format!("{:?}", variant)).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod beta_key_product;
|
||||
@@ -1,6 +1,7 @@
|
||||
// ===== MySql =====
|
||||
pub mod audit_logs;
|
||||
pub mod batch_generations;
|
||||
pub mod beta_keys;
|
||||
pub mod comments;
|
||||
pub mod email_sender_jobs;
|
||||
pub mod entity_stats;
|
||||
|
||||
@@ -25,6 +25,7 @@ pub(crate) enum TokenPrefix {
|
||||
AnonymousVisitorTracking, // AVTs are not stored as primary keys in any table, but an index in many tables.
|
||||
AuditLog,
|
||||
BatchGeneration,
|
||||
BetaKey,
|
||||
Comment,
|
||||
DownloadJob,
|
||||
EmailSenderJob,
|
||||
@@ -93,6 +94,7 @@ impl PrefixGenerator for TokenPrefix {
|
||||
Self::AnonymousVisitorTracking => "avt_",
|
||||
Self::AuditLog => "audit_",
|
||||
Self::BatchGeneration => "batch_g_",
|
||||
Self::BetaKey => "beta_key_",
|
||||
Self::Comment => "comment_",
|
||||
Self::DownloadJob => "jdown_", // NB: Previously "JGUP:"
|
||||
Self::EmailSenderJob => "email_job_",
|
||||
@@ -302,11 +304,12 @@ mod tests {
|
||||
fn test_all_prefixes_end_with_separator_length_one() {
|
||||
for prefix in get_all_prefixes().iter().map(|s| *s) {
|
||||
if prefix == "news_story_"
|
||||
|| prefix == "tts_task_"
|
||||
|| prefix == "INT_API:"
|
||||
|| prefix == "pw_reset_"
|
||||
|| prefix == "email_job_"
|
||||
|| prefix == "batch_g_"
|
||||
|| prefix == "beta_key_"
|
||||
|| prefix == "email_job_"
|
||||
|| prefix == "pw_reset_"
|
||||
|| prefix == "tts_task_"
|
||||
{
|
||||
// TODO/FIXME: I'm too tired at 5AM to replacen from the left. Make this test valid.
|
||||
// These tokens are from the AIChatBot sidecar, so asserting their validity is less important.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
|
||||
/// The primary key for Audit Logs.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct BetaKeyToken(pub String);
|
||||
|
||||
impl_crockford_generator!(BetaKeyToken, 32usize, TokenPrefix::BetaKey, CrockfordLower);
|
||||
impl_mysql_token_from_row!(BetaKeyToken);
|
||||
impl_string_token!(BetaKeyToken);
|
||||
@@ -3,6 +3,7 @@ pub mod api_tokens_external;
|
||||
pub mod api_tokens_internal;
|
||||
pub mod audit_logs;
|
||||
pub mod batch_generations;
|
||||
pub mod beta_keys;
|
||||
pub mod comments;
|
||||
pub mod email_sender_job_token;
|
||||
pub mod firehose_entries;
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
use anyhow::anyhow;
|
||||
use log::error;
|
||||
use sqlx::{MySql, MySqlPool, QueryBuilder, Transaction};
|
||||
|
||||
use composite_identifiers::by_table::batch_generations::batch_generation_entity::BatchGenerationEntity;
|
||||
use enums::by_table::beta_keys::beta_key_product::BetaKeyProduct;
|
||||
use errors::AnyhowResult;
|
||||
use tokens::tokens::batch_generations::BatchGenerationToken;
|
||||
use tokens::tokens::beta_keys::BetaKeyToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
pub struct BatchEntry {
|
||||
pub batch_token: BatchGenerationToken,
|
||||
pub entity: BatchGenerationEntity,
|
||||
}
|
||||
|
||||
pub struct InsertBatchArgs<'a> {
|
||||
pub product: BetaKeyProduct,
|
||||
pub maybe_referrer_user_token: Option<&'a UserToken>,
|
||||
pub beta_keys: &'a Vec<String>,
|
||||
pub mysql_pool: &'a MySqlPool,
|
||||
}
|
||||
|
||||
pub async fn insert_batch_beta_keys<'a, 'b>(args: InsertBatchArgs<'a>) -> AnyhowResult<()> {
|
||||
|
||||
let mut query_builder = QueryBuilder::new(r#"
|
||||
INSERT INTO beta_keys (
|
||||
token,
|
||||
product,
|
||||
key_value,
|
||||
maybe_referrer_user_token
|
||||
) VALUES
|
||||
"#);
|
||||
|
||||
for (i, beta_key) in args.beta_keys.iter().enumerate() {
|
||||
let token = BetaKeyToken::generate();
|
||||
|
||||
query_builder.push("(");
|
||||
|
||||
query_builder.push_bind(token.to_string());
|
||||
query_builder.push(",");
|
||||
|
||||
query_builder.push_bind(args.product.to_str());
|
||||
query_builder.push(",");
|
||||
|
||||
query_builder.push_bind(beta_key);
|
||||
query_builder.push(",");
|
||||
|
||||
query_builder.push_bind(args.maybe_referrer_user_token.map(|t| t.as_str()));
|
||||
|
||||
query_builder.push(")");
|
||||
|
||||
if i < args.beta_keys.len() - 1 {
|
||||
query_builder.push(",");
|
||||
}
|
||||
}
|
||||
|
||||
let query = query_builder.build();
|
||||
|
||||
let query_result = query.execute(args.mysql_pool).await;
|
||||
|
||||
match query_result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
error!("Error with batch generation query: {:?}", &err);
|
||||
Err(anyhow!("model category creation error: {:?}", &err))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// #[ignore]
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use sqlx::mysql::MySqlPoolOptions;
|
||||
//
|
||||
// use composite_identifiers::by_table::batch_generations::batch_generation_entity::BatchGenerationEntity;
|
||||
// use config::shared_constants::DEFAULT_MYSQL_CONNECTION_STRING;
|
||||
// use tokens::tokens::media_files::MediaFileToken;
|
||||
//
|
||||
// use crate::queries::batch_generations::insert_batch_generation_records::{insert_batch_generation_records, InsertBatchArgs};
|
||||
//
|
||||
// async fn setup() -> sqlx::Pool<sqlx::MySql> {
|
||||
// MySqlPoolOptions::new()
|
||||
// .max_connections(3)
|
||||
// .connect(&DEFAULT_MYSQL_CONNECTION_STRING).await
|
||||
// .unwrap()
|
||||
// }
|
||||
//
|
||||
// #[ignore]
|
||||
// #[tokio::test]
|
||||
// async fn test() {
|
||||
// let pool = setup().await;
|
||||
//
|
||||
// let mut transaction = pool.begin().await.unwrap();
|
||||
//
|
||||
// let entries = vec![
|
||||
// BatchGenerationEntity::MediaFile(MediaFileToken::new_from_str("media_foo")),
|
||||
// BatchGenerationEntity::MediaFile(MediaFileToken::new_from_str("media_bar")),
|
||||
// BatchGenerationEntity::MediaFile(MediaFileToken::new_from_str("media_baz")),
|
||||
// ];
|
||||
//
|
||||
// let r = insert_batch_generation_records(InsertBatchArgs {
|
||||
// entries,
|
||||
// maybe_existing_batch_token: None,
|
||||
// transaction: &mut transaction,
|
||||
// }).await;
|
||||
//
|
||||
// transaction.commit().await.unwrap();
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1 @@
|
||||
pub mod insert_batch_beta_keys;
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod api_tokens;
|
||||
pub mod audit_logs;
|
||||
pub mod batch_generations;
|
||||
pub mod beta_keys;
|
||||
pub mod billing;
|
||||
pub mod comments;
|
||||
pub mod email_sender_jobs;
|
||||
|
||||
@@ -34,6 +34,7 @@ composite_identifiers = { path = "../../../_types/composite_identifiers" }
|
||||
config = { path = "../../../lib/deprecated/config" }
|
||||
container_common = { path = "../../../lib/deprecated/container_common" }
|
||||
cookies = { path = "../../../lib/cookies" }
|
||||
crockford = { path = "../../../lib/data/crockford" }
|
||||
datetimes = { path = "../../../lib/data/datetimes" }
|
||||
easyenv = { path = "../../../lib/easyenv" }
|
||||
elasticsearch_schema = { path = "../../../lib/elasticsearch_schema" }
|
||||
|
||||
+21
-2
@@ -7,8 +7,11 @@ use actix_web::http::StatusCode;
|
||||
use log::warn;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crockford::crockford_entropy_lower;
|
||||
use enums::by_table::beta_keys::beta_key_product::BetaKeyProduct;
|
||||
use enums::by_table::comments::comment_entity_type::CommentEntityType;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use mysql_queries::queries::beta_keys::insert_batch_beta_keys::{insert_batch_beta_keys, InsertBatchArgs};
|
||||
use mysql_queries::queries::comments::comment_entity_token::CommentEntityToken;
|
||||
use mysql_queries::queries::comments::insert_comment::{insert_comment, InsertCommentArgs};
|
||||
use tokens::tokens::comments::CommentToken;
|
||||
@@ -27,6 +30,8 @@ use crate::http_server::web_utils::require_moderator::{require_moderator, Requir
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::server_state::ServerState;
|
||||
|
||||
const MAXIMUM_KEYS : u32 = 100;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct CreateBetaKeysRequest {
|
||||
uuid_idempotency_token: String,
|
||||
@@ -102,11 +107,25 @@ pub async fn create_beta_keys_handler(
|
||||
RequireModeratorError::NotAuthorized => CreateBetaKeysError::NotAuthorized,
|
||||
})?;
|
||||
|
||||
// TODO(bt,2024-05-13): Create beta key records
|
||||
let number_of_keys = request.number_of_keys.min(MAXIMUM_KEYS);
|
||||
|
||||
let beta_keys = (0..number_of_keys).map(|_| {
|
||||
crockford_entropy_lower(8)
|
||||
}).collect::<Vec::<String>>();
|
||||
|
||||
insert_batch_beta_keys(InsertBatchArgs {
|
||||
product: BetaKeyProduct::Studio,
|
||||
maybe_referrer_user_token: None,
|
||||
beta_keys: &beta_keys,
|
||||
mysql_pool: &server_state.mysql_pool,
|
||||
}).await.map_err(|err| {
|
||||
warn!("Error inserting beta keys: {:?}", err);
|
||||
CreateBetaKeysError::ServerError
|
||||
})?;
|
||||
|
||||
let response = CreateBetaKeysSuccessResponse {
|
||||
success: true,
|
||||
beta_keys: Vec::new(),
|
||||
beta_keys,
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
|
||||
Reference in new issue
Block a user