From 5b96bc5c5f6f554433fe8b6682f0d71031cdb376 Mon Sep 17 00:00:00 2001 From: HeavenVR Date: Mon, 16 Mar 2026 13:59:18 +0100 Subject: [PATCH 1/2] Add support for Wellturn T330 shocker --- ...20260316125819_AddWellturnT330.Designer.cs | 1461 +++++++++++++++++ .../20260316125819_AddWellturnT330.cs | 809 +++++++++ .../OpenShockContextModelSnapshot.cs | 29 +- Common/Models/ShockerModelType.cs | 1 + Common/OpenShockDb/OpenShockContext.cs | 2 +- Directory.Packages.props | 2 +- LiveControlGateway/Mappers/FbsMapper.cs | 1 + 7 files changed, 2287 insertions(+), 18 deletions(-) create mode 100644 Common/Migrations/20260316125819_AddWellturnT330.Designer.cs create mode 100644 Common/Migrations/20260316125819_AddWellturnT330.cs diff --git a/Common/Migrations/20260316125819_AddWellturnT330.Designer.cs b/Common/Migrations/20260316125819_AddWellturnT330.Designer.cs new file mode 100644 index 00000000..0c330593 --- /dev/null +++ b/Common/Migrations/20260316125819_AddWellturnT330.Designer.cs @@ -0,0 +1,1461 @@ +// +using System; +using System.Net; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using OpenShock.Common.OpenShockDb; + +#nullable disable + +namespace OpenShock.Common.Migrations +{ + [DbContext(typeof(OpenShockContext))] + [Migration("20260316125819_AddWellturnT330")] + partial class AddWellturnT330 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:CollationDefinition:public.ndcoll", "und-u-ks-level2,und-u-ks-level2,icu,False") + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "configuration_value_type", new[] { "string", "bool", "int", "float", "json" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "control_type", new[] { "sound", "vibrate", "shock", "stop" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "match_type_enum", new[] { "exact", "contains" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "ota_update_status", new[] { "started", "running", "finished", "error", "timeout" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "password_encryption_type", new[] { "pbkdf2", "bcrypt_enhanced" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "permission_type", new[] { "shockers.use", "shockers.edit", "shockers.pause", "devices.edit", "devices.auth" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "role_type", new[] { "support", "staff", "admin", "system" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "shocker_model_type", new[] { "caiXianlin", "petTrainer", "petrainer998DR", "wellturnT330" }); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FriendlyName") + .HasColumnType("text"); + + b.Property("Xml") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.AdminUsersView", b => + { + b.Property("ActivatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("activated_at"); + + b.Property("ApiTokenCount") + .HasColumnType("integer") + .HasColumnName("api_token_count"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeactivatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deactivated_at"); + + b.Property("DeactivatedByUserId") + .HasColumnType("uuid") + .HasColumnName("deactivated_by_user_id"); + + b.Property("DeviceCount") + .HasColumnType("integer") + .HasColumnName("device_count"); + + b.Property("Email") + .IsRequired() + .HasColumnType("character varying") + .HasColumnName("email"); + + b.Property("EmailChangeRequestCount") + .HasColumnType("integer") + .HasColumnName("email_change_request_count"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying") + .HasColumnName("name"); + + b.Property("NameChangeRequestCount") + .HasColumnType("integer") + .HasColumnName("name_change_request_count"); + + b.Property("PasswordHashType") + .HasColumnType("character varying") + .HasColumnName("password_hash_type"); + + b.Property("PasswordResetCount") + .HasColumnType("integer") + .HasColumnName("password_reset_count"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("role_type[]") + .HasColumnName("roles"); + + b.Property("ShockerControlLogCount") + .HasColumnType("integer") + .HasColumnName("shocker_control_log_count"); + + b.Property("ShockerCount") + .HasColumnType("integer") + .HasColumnName("shocker_count"); + + b.Property("ShockerPublicShareCount") + .HasColumnType("integer") + .HasColumnName("shocker_public_share_count"); + + b.Property("ShockerUserShareCount") + .HasColumnType("integer") + .HasColumnName("shocker_user_share_count"); + + b.ToTable((string)null); + + b.ToView("admin_users_view", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ApiToken", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedByIp") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("created_by_ip"); + + b.Property("LastUsed") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_used") + .HasDefaultValueSql("'-infinity'::timestamp without time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("name"); + + b.PrimitiveCollection("Permissions") + .IsRequired() + .HasColumnType("permission_type[]") + .HasColumnName("permissions"); + + b.Property("TokenHash") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("token_hash") + .UseCollation("C"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("ValidUntil") + .HasColumnType("timestamp with time zone") + .HasColumnName("valid_until"); + + b.HasKey("Id") + .HasName("api_tokens_pkey"); + + b.HasIndex("TokenHash") + .IsUnique(); + + b.HasIndex("UserId"); + + b.HasIndex("ValidUntil"); + + b.ToTable("api_tokens", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ApiTokenReport", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AffectedCount") + .HasColumnType("integer") + .HasColumnName("affected_count"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("IpAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("ip_address"); + + b.Property("IpCountry") + .HasColumnType("text") + .HasColumnName("ip_country"); + + b.Property("SubmittedCount") + .HasColumnType("integer") + .HasColumnName("submitted_count"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("api_token_reports_pkey"); + + b.HasIndex("UserId"); + + b.ToTable("api_token_reports", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ConfigurationItem", b => + { + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name") + .UseCollation("C"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("Name") + .HasName("configuration_pkey"); + + b.ToTable("configuration", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.Device", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("uuid") + .HasColumnName("owner_id"); + + b.Property("Token") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("token") + .UseCollation("C"); + + b.HasKey("Id") + .HasName("devices_pkey"); + + b.HasIndex("OwnerId"); + + b.HasIndex("Token") + .IsUnique(); + + b.ToTable("devices", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.DeviceOtaUpdate", b => + { + b.Property("DeviceId") + .HasColumnType("uuid") + .HasColumnName("device_id"); + + b.Property("UpdateId") + .HasColumnType("integer") + .HasColumnName("update_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Message") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("message"); + + b.Property("Status") + .HasColumnType("ota_update_status") + .HasColumnName("status"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("version"); + + b.HasKey("DeviceId", "UpdateId") + .HasName("device_ota_updates_pkey"); + + b.HasIndex(new[] { "CreatedAt" }, "device_ota_updates_created_at_idx"); + + b.ToTable("device_ota_updates", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.DiscordWebhook", b => + { + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("WebhookId") + .HasColumnType("bigint") + .HasColumnName("webhook_id"); + + b.Property("WebhookToken") + .IsRequired() + .HasColumnType("text") + .HasColumnName("webhook_token"); + + b.HasKey("Name") + .HasName("discord_webhooks_pkey"); + + b.ToTable("discord_webhooks", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.EmailProviderBlacklist", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Domain") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("domain") + .UseCollation("ndcoll"); + + b.HasKey("Id") + .HasName("email_provider_blacklist_pkey"); + + b.HasIndex("Domain") + .IsUnique(); + + NpgsqlIndexBuilderExtensions.UseCollation(b.HasIndex("Domain"), new[] { "ndcoll" }); + + b.ToTable("email_provider_blacklist", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.PublicShare", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("uuid") + .HasColumnName("owner_id"); + + b.HasKey("Id") + .HasName("public_shares_pkey"); + + b.HasIndex("OwnerId"); + + b.ToTable("public_shares", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.PublicShareShocker", b => + { + b.Property("PublicShareId") + .HasColumnType("uuid") + .HasColumnName("public_share_id"); + + b.Property("ShockerId") + .HasColumnType("uuid") + .HasColumnName("shocker_id"); + + b.Property("AllowLiveControl") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("allow_livecontrol"); + + b.Property("AllowShock") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_shock"); + + b.Property("AllowSound") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_sound"); + + b.Property("AllowVibrate") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_vibrate"); + + b.Property("Cooldown") + .HasColumnType("integer") + .HasColumnName("cooldown"); + + b.Property("IsPaused") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("is_paused"); + + b.Property("MaxDuration") + .HasColumnType("integer") + .HasColumnName("max_duration"); + + b.Property("MaxIntensity") + .HasColumnType("smallint") + .HasColumnName("max_intensity"); + + b.HasKey("PublicShareId", "ShockerId") + .HasName("public_share_shockers_pkey"); + + b.HasIndex("ShockerId"); + + b.ToTable("public_share_shockers", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.Shocker", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DeviceId") + .HasColumnType("uuid") + .HasColumnName("device_id"); + + b.Property("IsPaused") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("is_paused"); + + b.Property("Model") + .HasColumnType("shocker_model_type") + .HasColumnName("model"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("name"); + + b.Property("RfId") + .HasColumnType("integer") + .HasColumnName("rf_id"); + + b.HasKey("Id") + .HasName("shockers_pkey"); + + b.HasIndex("DeviceId"); + + b.ToTable("shockers", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ShockerControlLog", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ControlledByUserId") + .HasColumnType("uuid") + .HasColumnName("controlled_by_user_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CustomName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("custom_name"); + + b.Property("Duration") + .HasColumnType("bigint") + .HasColumnName("duration"); + + b.Property("Intensity") + .HasColumnType("smallint") + .HasColumnName("intensity"); + + b.Property("LiveControl") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("live_control"); + + b.Property("ShockerId") + .HasColumnType("uuid") + .HasColumnName("shocker_id"); + + b.Property("Type") + .HasColumnType("control_type") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("shocker_control_logs_pkey"); + + b.HasIndex("ControlledByUserId"); + + b.HasIndex("ShockerId"); + + b.ToTable("shocker_control_logs", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ShockerShareCode", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AllowLiveControl") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_livecontrol"); + + b.Property("AllowShock") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_shock"); + + b.Property("AllowSound") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_sound"); + + b.Property("AllowVibrate") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_vibrate"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("IsPaused") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("is_paused"); + + b.Property("MaxDuration") + .HasColumnType("integer") + .HasColumnName("max_duration"); + + b.Property("MaxIntensity") + .HasColumnType("smallint") + .HasColumnName("max_intensity"); + + b.Property("ShockerId") + .HasColumnType("uuid") + .HasColumnName("shocker_id"); + + b.HasKey("Id") + .HasName("shocker_share_codes_pkey"); + + b.HasIndex("ShockerId"); + + b.ToTable("shocker_share_codes", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.User", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ActivatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("activated_at"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("character varying(320)") + .HasColumnName("email"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("name") + .UseCollation("ndcoll"); + + b.Property("PasswordHash") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("password_hash") + .UseCollation("C"); + + b.PrimitiveCollection("Roles") + .IsRequired() + .HasColumnType("role_type[]") + .HasColumnName("roles"); + + b.HasKey("Id") + .HasName("users_pkey"); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("Name") + .IsUnique(); + + NpgsqlIndexBuilderExtensions.UseCollation(b.HasIndex("Name"), new[] { "ndcoll" }); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserActivationRequest", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("EmailSendAttempts") + .HasColumnType("integer") + .HasColumnName("email_send_attempts"); + + b.Property("TokenHash") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("token_hash") + .UseCollation("C"); + + b.HasKey("UserId") + .HasName("user_activation_requests_pkey"); + + b.HasIndex("TokenHash") + .IsUnique(); + + b.ToTable("user_activation_requests", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserDeactivation", b => + { + b.Property("DeactivatedUserId") + .HasColumnType("uuid") + .HasColumnName("deactivated_user_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DeactivatedByUserId") + .HasColumnType("uuid") + .HasColumnName("deactivated_by_user_id"); + + b.Property("DeleteLater") + .HasColumnType("boolean") + .HasColumnName("delete_later"); + + b.Property("UserModerationId") + .HasColumnType("uuid") + .HasColumnName("user_moderation_id"); + + b.HasKey("DeactivatedUserId") + .HasName("user_deactivations_pkey"); + + b.HasIndex("DeactivatedByUserId"); + + b.ToTable("user_deactivations", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserEmailChange", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("NewEmail") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("character varying(320)") + .HasColumnName("email_new"); + + b.Property("OldEmail") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("character varying(320)") + .HasColumnName("email_old"); + + b.Property("TokenHash") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("token_hash") + .UseCollation("C"); + + b.Property("UsedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("used_at"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("user_email_changes_pkey"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UsedAt"); + + b.HasIndex("UserId"); + + b.ToTable("user_email_changes", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserNameBlacklist", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("MatchType") + .HasColumnType("integer") + .HasColumnName("match_type"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("value") + .UseCollation("ndcoll"); + + b.HasKey("Id") + .HasName("user_name_blacklist_pkey"); + + b.HasIndex("Value") + .IsUnique(); + + NpgsqlIndexBuilderExtensions.UseCollation(b.HasIndex("Value"), new[] { "ndcoll" }); + + b.ToTable("user_name_blacklist", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserNameChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityAlwaysColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("OldName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("old_name"); + + b.HasKey("Id", "UserId") + .HasName("user_name_changes_pkey"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("OldName"); + + b.HasIndex("UserId"); + + b.ToTable("user_name_changes", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserOAuthConnection", b => + { + b.Property("ProviderKey") + .HasColumnType("text") + .HasColumnName("provider_key") + .UseCollation("C"); + + b.Property("ExternalId") + .HasColumnType("text") + .HasColumnName("external_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("ProviderKey", "ExternalId") + .HasName("user_oauth_connections_pkey"); + + b.HasIndex("UserId"); + + b.ToTable("user_oauth_connections", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserPasswordReset", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("TokenHash") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("token_hash") + .UseCollation("C"); + + b.Property("UsedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("used_at"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("user_password_resets_pkey"); + + b.HasIndex("UserId"); + + b.ToTable("user_password_resets", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserShare", b => + { + b.Property("SharedWithUserId") + .HasColumnType("uuid") + .HasColumnName("shared_with_user_id"); + + b.Property("ShockerId") + .HasColumnType("uuid") + .HasColumnName("shocker_id"); + + b.Property("AllowLiveControl") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_livecontrol"); + + b.Property("AllowShock") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_shock"); + + b.Property("AllowSound") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_sound"); + + b.Property("AllowVibrate") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_vibrate"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("IsPaused") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("is_paused"); + + b.Property("MaxDuration") + .HasColumnType("integer") + .HasColumnName("max_duration"); + + b.Property("MaxIntensity") + .HasColumnType("smallint") + .HasColumnName("max_intensity"); + + b.HasKey("SharedWithUserId", "ShockerId") + .HasName("user_shares_pkey"); + + b.HasIndex("SharedWithUserId"); + + b.HasIndex("ShockerId"); + + b.ToTable("user_shares", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserShareInvite", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("OwnerId") + .HasColumnType("uuid") + .HasColumnName("owner_id"); + + b.Property("RecipientUserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("user_share_invites_pkey"); + + b.HasIndex("OwnerId"); + + b.HasIndex("RecipientUserId"); + + b.ToTable("user_share_invites", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserShareInviteShocker", b => + { + b.Property("InviteId") + .HasColumnType("uuid") + .HasColumnName("invite_id"); + + b.Property("ShockerId") + .HasColumnType("uuid") + .HasColumnName("shocker_id"); + + b.Property("AllowLiveControl") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_livecontrol"); + + b.Property("AllowShock") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_shock"); + + b.Property("AllowSound") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_sound"); + + b.Property("AllowVibrate") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("allow_vibrate"); + + b.Property("IsPaused") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("is_paused"); + + b.Property("MaxDuration") + .HasColumnType("integer") + .HasColumnName("max_duration"); + + b.Property("MaxIntensity") + .HasColumnType("smallint") + .HasColumnName("max_intensity"); + + b.HasKey("InviteId", "ShockerId") + .HasName("user_share_invite_shockers_pkey"); + + b.HasIndex("ShockerId"); + + b.ToTable("user_share_invite_shockers", (string)null); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ApiToken", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "User") + .WithMany("ApiTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_tokens_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ApiTokenReport", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "ReportedByUser") + .WithMany("ReportedApiTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_token_reports_reported_by_user_id"); + + b.Navigation("ReportedByUser"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.Device", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "Owner") + .WithMany("Devices") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_devices_owner_id"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.DeviceOtaUpdate", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.Device", "Device") + .WithMany("OtaUpdates") + .HasForeignKey("DeviceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_device_ota_updates_device_id"); + + b.Navigation("Device"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.PublicShare", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "Owner") + .WithMany("OwnedPublicShares") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_public_shares_owner_id"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.PublicShareShocker", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.PublicShare", "PublicShare") + .WithMany("ShockerMappings") + .HasForeignKey("PublicShareId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_public_share_shockers_public_share_id"); + + b.HasOne("OpenShock.Common.OpenShockDb.Shocker", "Shocker") + .WithMany("PublicShareMappings") + .HasForeignKey("ShockerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_public_share_shockers_shocker_id"); + + b.Navigation("PublicShare"); + + b.Navigation("Shocker"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.Shocker", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.Device", "Device") + .WithMany("Shockers") + .HasForeignKey("DeviceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_shockers_device_id"); + + b.Navigation("Device"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ShockerControlLog", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "ControlledByUser") + .WithMany("ShockerControlLogs") + .HasForeignKey("ControlledByUserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_shocker_control_logs_controlled_by_user_id"); + + b.HasOne("OpenShock.Common.OpenShockDb.Shocker", "Shocker") + .WithMany("ShockerControlLogs") + .HasForeignKey("ShockerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_shocker_control_logs_shocker_id"); + + b.Navigation("ControlledByUser"); + + b.Navigation("Shocker"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.ShockerShareCode", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.Shocker", "Shocker") + .WithMany("ShockerShareCodes") + .HasForeignKey("ShockerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_shocker_share_codes_shocker_id"); + + b.Navigation("Shocker"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserActivationRequest", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "User") + .WithOne("UserActivationRequest") + .HasForeignKey("OpenShock.Common.OpenShockDb.UserActivationRequest", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_activation_requests_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserDeactivation", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "DeactivatedByUser") + .WithMany() + .HasForeignKey("DeactivatedByUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_deactivations_deactivated_by_user_id"); + + b.HasOne("OpenShock.Common.OpenShockDb.User", "DeactivatedUser") + .WithOne("UserDeactivation") + .HasForeignKey("OpenShock.Common.OpenShockDb.UserDeactivation", "DeactivatedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_deactivations_deactivated_user_id"); + + b.Navigation("DeactivatedByUser"); + + b.Navigation("DeactivatedUser"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserEmailChange", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "User") + .WithMany("EmailChanges") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_email_changes_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserNameChange", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "User") + .WithMany("NameChanges") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_name_changes_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserOAuthConnection", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "User") + .WithMany("OAuthConnections") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_oauth_connections_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserPasswordReset", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "User") + .WithMany("PasswordResets") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_password_resets_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserShare", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "SharedWithUser") + .WithMany("IncomingUserShares") + .HasForeignKey("SharedWithUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_shares_shared_with_user_id"); + + b.HasOne("OpenShock.Common.OpenShockDb.Shocker", "Shocker") + .WithMany("UserShares") + .HasForeignKey("ShockerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_shares_shocker_id"); + + b.Navigation("SharedWithUser"); + + b.Navigation("Shocker"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserShareInvite", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.User", "Owner") + .WithMany("OutgoingUserShareInvites") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_share_invites_owner_id"); + + b.HasOne("OpenShock.Common.OpenShockDb.User", "RecipientUser") + .WithMany("IncomingUserShareInvites") + .HasForeignKey("RecipientUserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_user_share_invites_recipient_user_id"); + + b.Navigation("Owner"); + + b.Navigation("RecipientUser"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserShareInviteShocker", b => + { + b.HasOne("OpenShock.Common.OpenShockDb.UserShareInvite", "Invite") + .WithMany("ShockerMappings") + .HasForeignKey("InviteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_share_invite_shockers_invite_id"); + + b.HasOne("OpenShock.Common.OpenShockDb.Shocker", "Shocker") + .WithMany("UserShareInviteShockerMappings") + .HasForeignKey("ShockerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_share_invite_shockers_shocker_id"); + + b.Navigation("Invite"); + + b.Navigation("Shocker"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.Device", b => + { + b.Navigation("OtaUpdates"); + + b.Navigation("Shockers"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.PublicShare", b => + { + b.Navigation("ShockerMappings"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.Shocker", b => + { + b.Navigation("PublicShareMappings"); + + b.Navigation("ShockerControlLogs"); + + b.Navigation("ShockerShareCodes"); + + b.Navigation("UserShareInviteShockerMappings"); + + b.Navigation("UserShares"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.User", b => + { + b.Navigation("ApiTokens"); + + b.Navigation("Devices"); + + b.Navigation("EmailChanges"); + + b.Navigation("IncomingUserShareInvites"); + + b.Navigation("IncomingUserShares"); + + b.Navigation("NameChanges"); + + b.Navigation("OAuthConnections"); + + b.Navigation("OutgoingUserShareInvites"); + + b.Navigation("OwnedPublicShares"); + + b.Navigation("PasswordResets"); + + b.Navigation("ReportedApiTokens"); + + b.Navigation("ShockerControlLogs"); + + b.Navigation("UserActivationRequest"); + + b.Navigation("UserDeactivation"); + }); + + modelBuilder.Entity("OpenShock.Common.OpenShockDb.UserShareInvite", b => + { + b.Navigation("ShockerMappings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Common/Migrations/20260316125819_AddWellturnT330.cs b/Common/Migrations/20260316125819_AddWellturnT330.cs new file mode 100644 index 00000000..d5eb96ec --- /dev/null +++ b/Common/Migrations/20260316125819_AddWellturnT330.cs @@ -0,0 +1,809 @@ +using System; +using System.Net; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace OpenShock.Common.Migrations +{ + /// + public partial class AddWellturnT330 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("Npgsql:CollationDefinition:public.ndcoll", "und-u-ks-level2,und-u-ks-level2,icu,False") + .Annotation("Npgsql:Enum:configuration_value_type", "string,bool,int,float,json") + .Annotation("Npgsql:Enum:control_type", "sound,vibrate,shock,stop") + .Annotation("Npgsql:Enum:match_type_enum", "exact,contains") + .Annotation("Npgsql:Enum:ota_update_status", "started,running,finished,error,timeout") + .Annotation("Npgsql:Enum:password_encryption_type", "pbkdf2,bcrypt_enhanced") + .Annotation("Npgsql:Enum:permission_type", "shockers.use,shockers.edit,shockers.pause,devices.edit,devices.auth") + .Annotation("Npgsql:Enum:role_type", "support,staff,admin,system") + .Annotation("Npgsql:Enum:shocker_model_type", "caiXianlin,petTrainer,petrainer998DR,wellturnT330"); + + migrationBuilder.CreateTable( + name: "configuration", + columns: table => new + { + name = table.Column(type: "text", nullable: false, collation: "C"), + description = table.Column(type: "text", nullable: false), + type = table.Column(type: "integer", nullable: false), + value = table.Column(type: "text", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("configuration_pkey", x => x.name); + }); + + migrationBuilder.CreateTable( + name: "DataProtectionKeys", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + FriendlyName = table.Column(type: "text", nullable: true), + Xml = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_DataProtectionKeys", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "discord_webhooks", + columns: table => new + { + name = table.Column(type: "text", nullable: false), + id = table.Column(type: "uuid", nullable: false), + webhook_id = table.Column(type: "bigint", nullable: false), + webhook_token = table.Column(type: "text", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("discord_webhooks_pkey", x => x.name); + }); + + migrationBuilder.CreateTable( + name: "email_provider_blacklist", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + domain = table.Column(type: "character varying(255)", maxLength: 255, nullable: false, collation: "ndcoll"), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("email_provider_blacklist_pkey", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "user_name_blacklist", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + value = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, collation: "ndcoll"), + match_type = table.Column(type: "integer", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_name_blacklist_pkey", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "users", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, collation: "ndcoll"), + email = table.Column(type: "character varying(320)", maxLength: 320, nullable: false), + password_hash = table.Column(type: "character varying(100)", maxLength: 100, nullable: true, collation: "C"), + roles = table.Column(type: "role_type[]", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + activated_at = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("users_pkey", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "api_token_reports", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + submitted_count = table.Column(type: "integer", nullable: false), + affected_count = table.Column(type: "integer", nullable: false), + user_id = table.Column(type: "uuid", nullable: false), + ip_address = table.Column(type: "inet", nullable: false), + ip_country = table.Column(type: "text", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("api_token_reports_pkey", x => x.id); + table.ForeignKey( + name: "fk_api_token_reports_reported_by_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "api_tokens", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + user_id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + token_hash = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, collation: "C"), + created_by_ip = table.Column(type: "inet", nullable: false), + permissions = table.Column(type: "permission_type[]", nullable: false), + valid_until = table.Column(type: "timestamp with time zone", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + last_used = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "'-infinity'::timestamp without time zone") + }, + constraints: table => + { + table.PrimaryKey("api_tokens_pkey", x => x.id); + table.ForeignKey( + name: "fk_api_tokens_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "devices", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + owner_id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + token = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, collation: "C"), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("devices_pkey", x => x.id); + table.ForeignKey( + name: "fk_devices_owner_id", + column: x => x.owner_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "public_shares", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + owner_id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + expires_at = table.Column(type: "timestamp with time zone", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("public_shares_pkey", x => x.id); + table.ForeignKey( + name: "fk_public_shares_owner_id", + column: x => x.owner_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_activation_requests", + columns: table => new + { + user_id = table.Column(type: "uuid", nullable: false), + token_hash = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, collation: "C"), + email_send_attempts = table.Column(type: "integer", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_activation_requests_pkey", x => x.user_id); + table.ForeignKey( + name: "fk_user_activation_requests_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_deactivations", + columns: table => new + { + deactivated_user_id = table.Column(type: "uuid", nullable: false), + deactivated_by_user_id = table.Column(type: "uuid", nullable: false), + delete_later = table.Column(type: "boolean", nullable: false), + user_moderation_id = table.Column(type: "uuid", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_deactivations_pkey", x => x.deactivated_user_id); + table.ForeignKey( + name: "fk_user_deactivations_deactivated_by_user_id", + column: x => x.deactivated_by_user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_user_deactivations_deactivated_user_id", + column: x => x.deactivated_user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_email_changes", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + user_id = table.Column(type: "uuid", nullable: false), + email_old = table.Column(type: "character varying(320)", maxLength: 320, nullable: false), + email_new = table.Column(type: "character varying(320)", maxLength: 320, nullable: false), + token_hash = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, collation: "C"), + used_at = table.Column(type: "timestamp with time zone", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_email_changes_pkey", x => x.id); + table.ForeignKey( + name: "fk_user_email_changes_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_name_changes", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn), + user_id = table.Column(type: "uuid", nullable: false), + old_name = table.Column(type: "character varying(32)", maxLength: 32, nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_name_changes_pkey", x => new { x.id, x.user_id }); + table.ForeignKey( + name: "fk_user_name_changes_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_oauth_connections", + columns: table => new + { + provider_key = table.Column(type: "text", nullable: false, collation: "C"), + external_id = table.Column(type: "text", nullable: false), + user_id = table.Column(type: "uuid", nullable: false), + display_name = table.Column(type: "text", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_oauth_connections_pkey", x => new { x.provider_key, x.external_id }); + table.ForeignKey( + name: "fk_user_oauth_connections_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_password_resets", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + user_id = table.Column(type: "uuid", nullable: false), + token_hash = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, collation: "C"), + used_at = table.Column(type: "timestamp with time zone", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_password_resets_pkey", x => x.id); + table.ForeignKey( + name: "fk_user_password_resets_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_share_invites", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + owner_id = table.Column(type: "uuid", nullable: false), + user_id = table.Column(type: "uuid", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("user_share_invites_pkey", x => x.id); + table.ForeignKey( + name: "fk_user_share_invites_owner_id", + column: x => x.owner_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_user_share_invites_recipient_user_id", + column: x => x.user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "device_ota_updates", + columns: table => new + { + device_id = table.Column(type: "uuid", nullable: false), + update_id = table.Column(type: "integer", nullable: false), + status = table.Column(type: "ota_update_status", nullable: false), + version = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + message = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("device_ota_updates_pkey", x => new { x.device_id, x.update_id }); + table.ForeignKey( + name: "fk_device_ota_updates_device_id", + column: x => x.device_id, + principalTable: "devices", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "shockers", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + model = table.Column(type: "shocker_model_type", nullable: false), + rf_id = table.Column(type: "integer", nullable: false), + device_id = table.Column(type: "uuid", nullable: false), + is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("shockers_pkey", x => x.id); + table.ForeignKey( + name: "fk_shockers_device_id", + column: x => x.device_id, + principalTable: "devices", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "public_share_shockers", + columns: table => new + { + public_share_id = table.Column(type: "uuid", nullable: false), + shocker_id = table.Column(type: "uuid", nullable: false), + cooldown = table.Column(type: "integer", nullable: true), + allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: false), + max_intensity = table.Column(type: "smallint", nullable: true), + max_duration = table.Column(type: "integer", nullable: true), + is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) + }, + constraints: table => + { + table.PrimaryKey("public_share_shockers_pkey", x => new { x.public_share_id, x.shocker_id }); + table.ForeignKey( + name: "fk_public_share_shockers_public_share_id", + column: x => x.public_share_id, + principalTable: "public_shares", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_public_share_shockers_shocker_id", + column: x => x.shocker_id, + principalTable: "shockers", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "shocker_control_logs", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + shocker_id = table.Column(type: "uuid", nullable: false), + controlled_by_user_id = table.Column(type: "uuid", nullable: true), + intensity = table.Column(type: "smallint", nullable: false), + duration = table.Column(type: "bigint", nullable: false), + type = table.Column(type: "control_type", nullable: false), + custom_name = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + live_control = table.Column(type: "boolean", nullable: false, defaultValue: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") + }, + constraints: table => + { + table.PrimaryKey("shocker_control_logs_pkey", x => x.id); + table.ForeignKey( + name: "fk_shocker_control_logs_controlled_by_user_id", + column: x => x.controlled_by_user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_shocker_control_logs_shocker_id", + column: x => x.shocker_id, + principalTable: "shockers", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "shocker_share_codes", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + shocker_id = table.Column(type: "uuid", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: true), + max_intensity = table.Column(type: "smallint", nullable: true), + max_duration = table.Column(type: "integer", nullable: true), + is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) + }, + constraints: table => + { + table.PrimaryKey("shocker_share_codes_pkey", x => x.id); + table.ForeignKey( + name: "fk_shocker_share_codes_shocker_id", + column: x => x.shocker_id, + principalTable: "shockers", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_share_invite_shockers", + columns: table => new + { + invite_id = table.Column(type: "uuid", nullable: false), + shocker_id = table.Column(type: "uuid", nullable: false), + allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: true), + max_intensity = table.Column(type: "smallint", nullable: true), + max_duration = table.Column(type: "integer", nullable: true), + is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) + }, + constraints: table => + { + table.PrimaryKey("user_share_invite_shockers_pkey", x => new { x.invite_id, x.shocker_id }); + table.ForeignKey( + name: "fk_user_share_invite_shockers_invite_id", + column: x => x.invite_id, + principalTable: "user_share_invites", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_user_share_invite_shockers_shocker_id", + column: x => x.shocker_id, + principalTable: "shockers", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_shares", + columns: table => new + { + shared_with_user_id = table.Column(type: "uuid", nullable: false), + shocker_id = table.Column(type: "uuid", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), + allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: true), + max_intensity = table.Column(type: "smallint", nullable: true), + max_duration = table.Column(type: "integer", nullable: true), + is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) + }, + constraints: table => + { + table.PrimaryKey("user_shares_pkey", x => new { x.shared_with_user_id, x.shocker_id }); + table.ForeignKey( + name: "fk_user_shares_shared_with_user_id", + column: x => x.shared_with_user_id, + principalTable: "users", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_user_shares_shocker_id", + column: x => x.shocker_id, + principalTable: "shockers", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_api_token_reports_user_id", + table: "api_token_reports", + column: "user_id"); + + migrationBuilder.CreateIndex( + name: "IX_api_tokens_token_hash", + table: "api_tokens", + column: "token_hash", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_api_tokens_user_id", + table: "api_tokens", + column: "user_id"); + + migrationBuilder.CreateIndex( + name: "IX_api_tokens_valid_until", + table: "api_tokens", + column: "valid_until"); + + migrationBuilder.CreateIndex( + name: "device_ota_updates_created_at_idx", + table: "device_ota_updates", + column: "created_at"); + + migrationBuilder.CreateIndex( + name: "IX_devices_owner_id", + table: "devices", + column: "owner_id"); + + migrationBuilder.CreateIndex( + name: "IX_devices_token", + table: "devices", + column: "token", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_email_provider_blacklist_domain", + table: "email_provider_blacklist", + column: "domain", + unique: true) + .Annotation("Relational:Collation", new[] { "ndcoll" }); + + migrationBuilder.CreateIndex( + name: "IX_public_share_shockers_shocker_id", + table: "public_share_shockers", + column: "shocker_id"); + + migrationBuilder.CreateIndex( + name: "IX_public_shares_owner_id", + table: "public_shares", + column: "owner_id"); + + migrationBuilder.CreateIndex( + name: "IX_shocker_control_logs_controlled_by_user_id", + table: "shocker_control_logs", + column: "controlled_by_user_id"); + + migrationBuilder.CreateIndex( + name: "IX_shocker_control_logs_shocker_id", + table: "shocker_control_logs", + column: "shocker_id"); + + migrationBuilder.CreateIndex( + name: "IX_shocker_share_codes_shocker_id", + table: "shocker_share_codes", + column: "shocker_id"); + + migrationBuilder.CreateIndex( + name: "IX_shockers_device_id", + table: "shockers", + column: "device_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_activation_requests_token_hash", + table: "user_activation_requests", + column: "token_hash", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_user_deactivations_deactivated_by_user_id", + table: "user_deactivations", + column: "deactivated_by_user_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_email_changes_created_at", + table: "user_email_changes", + column: "created_at"); + + migrationBuilder.CreateIndex( + name: "IX_user_email_changes_used_at", + table: "user_email_changes", + column: "used_at"); + + migrationBuilder.CreateIndex( + name: "IX_user_email_changes_user_id", + table: "user_email_changes", + column: "user_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_name_blacklist_value", + table: "user_name_blacklist", + column: "value", + unique: true) + .Annotation("Relational:Collation", new[] { "ndcoll" }); + + migrationBuilder.CreateIndex( + name: "IX_user_name_changes_created_at", + table: "user_name_changes", + column: "created_at"); + + migrationBuilder.CreateIndex( + name: "IX_user_name_changes_old_name", + table: "user_name_changes", + column: "old_name"); + + migrationBuilder.CreateIndex( + name: "IX_user_name_changes_user_id", + table: "user_name_changes", + column: "user_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_oauth_connections_user_id", + table: "user_oauth_connections", + column: "user_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_password_resets_user_id", + table: "user_password_resets", + column: "user_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_share_invite_shockers_shocker_id", + table: "user_share_invite_shockers", + column: "shocker_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_share_invites_owner_id", + table: "user_share_invites", + column: "owner_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_share_invites_user_id", + table: "user_share_invites", + column: "user_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_shares_shared_with_user_id", + table: "user_shares", + column: "shared_with_user_id"); + + migrationBuilder.CreateIndex( + name: "IX_user_shares_shocker_id", + table: "user_shares", + column: "shocker_id"); + + migrationBuilder.CreateIndex( + name: "IX_users_email", + table: "users", + column: "email", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_users_name", + table: "users", + column: "name", + unique: true) + .Annotation("Relational:Collation", new[] { "ndcoll" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "api_token_reports"); + + migrationBuilder.DropTable( + name: "api_tokens"); + + migrationBuilder.DropTable( + name: "configuration"); + + migrationBuilder.DropTable( + name: "DataProtectionKeys"); + + migrationBuilder.DropTable( + name: "device_ota_updates"); + + migrationBuilder.DropTable( + name: "discord_webhooks"); + + migrationBuilder.DropTable( + name: "email_provider_blacklist"); + + migrationBuilder.DropTable( + name: "public_share_shockers"); + + migrationBuilder.DropTable( + name: "shocker_control_logs"); + + migrationBuilder.DropTable( + name: "shocker_share_codes"); + + migrationBuilder.DropTable( + name: "user_activation_requests"); + + migrationBuilder.DropTable( + name: "user_deactivations"); + + migrationBuilder.DropTable( + name: "user_email_changes"); + + migrationBuilder.DropTable( + name: "user_name_blacklist"); + + migrationBuilder.DropTable( + name: "user_name_changes"); + + migrationBuilder.DropTable( + name: "user_oauth_connections"); + + migrationBuilder.DropTable( + name: "user_password_resets"); + + migrationBuilder.DropTable( + name: "user_share_invite_shockers"); + + migrationBuilder.DropTable( + name: "user_shares"); + + migrationBuilder.DropTable( + name: "public_shares"); + + migrationBuilder.DropTable( + name: "user_share_invites"); + + migrationBuilder.DropTable( + name: "shockers"); + + migrationBuilder.DropTable( + name: "devices"); + + migrationBuilder.DropTable( + name: "users"); + } + } +} diff --git a/Common/Migrations/OpenShockContextModelSnapshot.cs b/Common/Migrations/OpenShockContextModelSnapshot.cs index 645c590e..bede77ef 100644 --- a/Common/Migrations/OpenShockContextModelSnapshot.cs +++ b/Common/Migrations/OpenShockContextModelSnapshot.cs @@ -1,19 +1,17 @@ // using System; -using System.Collections.Generic; using System.Net; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using OpenShock.Common.Models; using OpenShock.Common.OpenShockDb; #nullable disable namespace OpenShock.Common.Migrations { - [DbContext(typeof(MigrationOpenShockContext))] + [DbContext(typeof(OpenShockContext))] partial class OpenShockContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) @@ -21,7 +19,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Npgsql:CollationDefinition:public.ndcoll", "und-u-ks-level2,und-u-ks-level2,icu,False") - .HasAnnotation("ProductVersion", "9.0.8") + .HasAnnotation("ProductVersion", "10.0.5") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "configuration_value_type", new[] { "string", "bool", "int", "float", "json" }); @@ -31,7 +29,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "password_encryption_type", new[] { "pbkdf2", "bcrypt_enhanced" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "permission_type", new[] { "shockers.use", "shockers.edit", "shockers.pause", "devices.edit", "devices.auth" }); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "role_type", new[] { "support", "staff", "admin", "system" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "shocker_model_type", new[] { "caiXianlin", "petTrainer", "petrainer998DR" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "shocker_model_type", new[] { "caiXianlin", "petTrainer", "petrainer998DR", "wellturnT330" }); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => @@ -102,7 +100,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("name_change_request_count"); b.Property("PasswordHashType") - .IsRequired() .HasColumnType("character varying") .HasColumnName("password_hash_type"); @@ -110,7 +107,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer") .HasColumnName("password_reset_count"); - b.Property("Roles") + b.Property("Roles") .IsRequired() .HasColumnType("role_type[]") .HasColumnName("roles"); @@ -165,7 +162,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(64)") .HasColumnName("name"); - b.PrimitiveCollection>("Permissions") + b.PrimitiveCollection("Permissions") .IsRequired() .HasColumnType("permission_type[]") .HasColumnName("permissions"); @@ -257,8 +254,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("description"); - b.Property("Type") - .HasColumnType("configuration_value_type") + b.Property("Type") + .HasColumnType("integer") .HasColumnName("type"); b.Property("UpdatedAt") @@ -337,7 +334,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(128)") .HasColumnName("message"); - b.Property("Status") + b.Property("Status") .HasColumnType("ota_update_status") .HasColumnName("status"); @@ -532,7 +529,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasDefaultValue(false) .HasColumnName("is_paused"); - b.Property("Model") + b.Property("Model") .HasColumnType("shocker_model_type") .HasColumnName("model"); @@ -593,7 +590,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("shocker_id"); - b.Property("Type") + b.Property("Type") .HasColumnType("control_type") .HasColumnName("type"); @@ -704,7 +701,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("password_hash") .UseCollation("C"); - b.PrimitiveCollection>("Roles") + b.PrimitiveCollection("Roles") .IsRequired() .HasColumnType("role_type[]") .HasColumnName("roles"); @@ -850,8 +847,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("created_at") .HasDefaultValueSql("CURRENT_TIMESTAMP"); - b.Property("MatchType") - .HasColumnType("match_type_enum") + b.Property("MatchType") + .HasColumnType("integer") .HasColumnName("match_type"); b.Property("Value") diff --git a/Common/Models/ShockerModelType.cs b/Common/Models/ShockerModelType.cs index 6ce4e64a..84690157 100644 --- a/Common/Models/ShockerModelType.cs +++ b/Common/Models/ShockerModelType.cs @@ -7,4 +7,5 @@ public enum ShockerModelType [PgName("caiXianlin")] CaiXianlin = 0, [PgName("petTrainer")] PetTrainer = 1, // Misspelled, should be "petrainer", [PgName("petrainer998DR")] Petrainer998DR = 2, + [PgName("wellturnT330")] WellturnT330 = 3, } \ No newline at end of file diff --git a/Common/OpenShockDb/OpenShockContext.cs b/Common/OpenShockDb/OpenShockContext.cs index 823cbfd4..2ad4b77f 100644 --- a/Common/OpenShockDb/OpenShockContext.cs +++ b/Common/OpenShockDb/OpenShockContext.cs @@ -146,7 +146,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasPostgresEnum("permission_type", ["shockers.use", "shockers.edit", "shockers.pause", "devices.edit", "devices.auth"]) .HasPostgresEnum("role_type", ["support", "staff", "admin", "system"]) - .HasPostgresEnum("shocker_model_type", ["caiXianlin", "petTrainer", "petrainer998DR"]) + .HasPostgresEnum("shocker_model_type", ["caiXianlin", "petTrainer", "petrainer998DR", "wellturnT330"]) .HasPostgresEnum("match_type_enum", ["exact", "contains"]) .HasPostgresEnum("configuration_value_type", ["string", "bool", "int", "float", "json"]) .HasCollation("public", "ndcoll", "und-u-ks-level2", "icu", false); // Add case-insensitive, accent-sensitive comparison collation diff --git a/Directory.Packages.props b/Directory.Packages.props index fbe580b1..1324c9a5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -26,7 +26,7 @@ - + diff --git a/LiveControlGateway/Mappers/FbsMapper.cs b/LiveControlGateway/Mappers/FbsMapper.cs index 3497a772..11c54de6 100644 --- a/LiveControlGateway/Mappers/FbsMapper.cs +++ b/LiveControlGateway/Mappers/FbsMapper.cs @@ -14,6 +14,7 @@ public static Serialization.Types.ShockerModelType ToFbsModelType(Common.Models. Common.Models.ShockerModelType.CaiXianlin => Serialization.Types.ShockerModelType.CaiXianlin, Common.Models.ShockerModelType.PetTrainer => Serialization.Types.ShockerModelType.Petrainer, Common.Models.ShockerModelType.Petrainer998DR => Serialization.Types.ShockerModelType.Petrainer998DR, + Common.Models.ShockerModelType.WellturnT330 => Serialization.Types.ShockerModelType.WellturnT330, _ => throw new NotImplementedException(), }; } From e070a7bf82401d487843025336b9bc155d78ed44 Mon Sep 17 00:00:00 2001 From: HeavenVR Date: Mon, 16 Mar 2026 14:06:31 +0100 Subject: [PATCH 2/2] Fix migration --- ...20260316125819_AddWellturnT330.Designer.cs | 24 +- .../20260316125819_AddWellturnT330.cs | 811 +----------------- .../OpenShockContextModelSnapshot.cs | 24 +- 3 files changed, 56 insertions(+), 803 deletions(-) diff --git a/Common/Migrations/20260316125819_AddWellturnT330.Designer.cs b/Common/Migrations/20260316125819_AddWellturnT330.Designer.cs index 0c330593..8723bb6c 100644 --- a/Common/Migrations/20260316125819_AddWellturnT330.Designer.cs +++ b/Common/Migrations/20260316125819_AddWellturnT330.Designer.cs @@ -1,18 +1,20 @@ // using System; +using System.Collections.Generic; using System.Net; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using OpenShock.Common.Models; using OpenShock.Common.OpenShockDb; #nullable disable namespace OpenShock.Common.Migrations { - [DbContext(typeof(OpenShockContext))] + [DbContext(typeof(MigrationOpenShockContext))] [Migration("20260316125819_AddWellturnT330")] partial class AddWellturnT330 { @@ -110,7 +112,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("integer") .HasColumnName("password_reset_count"); - b.Property("Roles") + b.Property("Roles") .IsRequired() .HasColumnType("role_type[]") .HasColumnName("roles"); @@ -165,7 +167,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("character varying(64)") .HasColumnName("name"); - b.PrimitiveCollection("Permissions") + b.PrimitiveCollection>("Permissions") .IsRequired() .HasColumnType("permission_type[]") .HasColumnName("permissions"); @@ -257,8 +259,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("description"); - b.Property("Type") - .HasColumnType("integer") + b.Property("Type") + .HasColumnType("configuration_value_type") .HasColumnName("type"); b.Property("UpdatedAt") @@ -337,7 +339,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("character varying(128)") .HasColumnName("message"); - b.Property("Status") + b.Property("Status") .HasColumnType("ota_update_status") .HasColumnName("status"); @@ -532,7 +534,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasDefaultValue(false) .HasColumnName("is_paused"); - b.Property("Model") + b.Property("Model") .HasColumnType("shocker_model_type") .HasColumnName("model"); @@ -593,7 +595,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("shocker_id"); - b.Property("Type") + b.Property("Type") .HasColumnType("control_type") .HasColumnName("type"); @@ -704,7 +706,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnName("password_hash") .UseCollation("C"); - b.PrimitiveCollection("Roles") + b.PrimitiveCollection>("Roles") .IsRequired() .HasColumnType("role_type[]") .HasColumnName("roles"); @@ -850,8 +852,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnName("created_at") .HasDefaultValueSql("CURRENT_TIMESTAMP"); - b.Property("MatchType") - .HasColumnType("integer") + b.Property("MatchType") + .HasColumnType("match_type_enum") .HasColumnName("match_type"); b.Property("Value") diff --git a/Common/Migrations/20260316125819_AddWellturnT330.cs b/Common/Migrations/20260316125819_AddWellturnT330.cs index d5eb96ec..cef83c92 100644 --- a/Common/Migrations/20260316125819_AddWellturnT330.cs +++ b/Common/Migrations/20260316125819_AddWellturnT330.cs @@ -1,7 +1,4 @@ -using System; -using System.Net; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; #nullable disable @@ -22,788 +19,40 @@ protected override void Up(MigrationBuilder migrationBuilder) .Annotation("Npgsql:Enum:password_encryption_type", "pbkdf2,bcrypt_enhanced") .Annotation("Npgsql:Enum:permission_type", "shockers.use,shockers.edit,shockers.pause,devices.edit,devices.auth") .Annotation("Npgsql:Enum:role_type", "support,staff,admin,system") - .Annotation("Npgsql:Enum:shocker_model_type", "caiXianlin,petTrainer,petrainer998DR,wellturnT330"); - - migrationBuilder.CreateTable( - name: "configuration", - columns: table => new - { - name = table.Column(type: "text", nullable: false, collation: "C"), - description = table.Column(type: "text", nullable: false), - type = table.Column(type: "integer", nullable: false), - value = table.Column(type: "text", nullable: false), - updated_at = table.Column(type: "timestamp with time zone", nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("configuration_pkey", x => x.name); - }); - - migrationBuilder.CreateTable( - name: "DataProtectionKeys", - columns: table => new - { - Id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - FriendlyName = table.Column(type: "text", nullable: true), - Xml = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_DataProtectionKeys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "discord_webhooks", - columns: table => new - { - name = table.Column(type: "text", nullable: false), - id = table.Column(type: "uuid", nullable: false), - webhook_id = table.Column(type: "bigint", nullable: false), - webhook_token = table.Column(type: "text", nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("discord_webhooks_pkey", x => x.name); - }); - - migrationBuilder.CreateTable( - name: "email_provider_blacklist", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - domain = table.Column(type: "character varying(255)", maxLength: 255, nullable: false, collation: "ndcoll"), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("email_provider_blacklist_pkey", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "user_name_blacklist", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - value = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, collation: "ndcoll"), - match_type = table.Column(type: "integer", nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_name_blacklist_pkey", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "users", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - name = table.Column(type: "character varying(32)", maxLength: 32, nullable: false, collation: "ndcoll"), - email = table.Column(type: "character varying(320)", maxLength: 320, nullable: false), - password_hash = table.Column(type: "character varying(100)", maxLength: 100, nullable: true, collation: "C"), - roles = table.Column(type: "role_type[]", nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - activated_at = table.Column(type: "timestamp with time zone", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("users_pkey", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "api_token_reports", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - submitted_count = table.Column(type: "integer", nullable: false), - affected_count = table.Column(type: "integer", nullable: false), - user_id = table.Column(type: "uuid", nullable: false), - ip_address = table.Column(type: "inet", nullable: false), - ip_country = table.Column(type: "text", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("api_token_reports_pkey", x => x.id); - table.ForeignKey( - name: "fk_api_token_reports_reported_by_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "api_tokens", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - user_id = table.Column(type: "uuid", nullable: false), - name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - token_hash = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, collation: "C"), - created_by_ip = table.Column(type: "inet", nullable: false), - permissions = table.Column(type: "permission_type[]", nullable: false), - valid_until = table.Column(type: "timestamp with time zone", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - last_used = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "'-infinity'::timestamp without time zone") - }, - constraints: table => - { - table.PrimaryKey("api_tokens_pkey", x => x.id); - table.ForeignKey( - name: "fk_api_tokens_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "devices", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - owner_id = table.Column(type: "uuid", nullable: false), - name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - token = table.Column(type: "character varying(256)", maxLength: 256, nullable: false, collation: "C"), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("devices_pkey", x => x.id); - table.ForeignKey( - name: "fk_devices_owner_id", - column: x => x.owner_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "public_shares", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - owner_id = table.Column(type: "uuid", nullable: false), - name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - expires_at = table.Column(type: "timestamp with time zone", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("public_shares_pkey", x => x.id); - table.ForeignKey( - name: "fk_public_shares_owner_id", - column: x => x.owner_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_activation_requests", - columns: table => new - { - user_id = table.Column(type: "uuid", nullable: false), - token_hash = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, collation: "C"), - email_send_attempts = table.Column(type: "integer", nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_activation_requests_pkey", x => x.user_id); - table.ForeignKey( - name: "fk_user_activation_requests_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_deactivations", - columns: table => new - { - deactivated_user_id = table.Column(type: "uuid", nullable: false), - deactivated_by_user_id = table.Column(type: "uuid", nullable: false), - delete_later = table.Column(type: "boolean", nullable: false), - user_moderation_id = table.Column(type: "uuid", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_deactivations_pkey", x => x.deactivated_user_id); - table.ForeignKey( - name: "fk_user_deactivations_deactivated_by_user_id", - column: x => x.deactivated_by_user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_user_deactivations_deactivated_user_id", - column: x => x.deactivated_user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_email_changes", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - user_id = table.Column(type: "uuid", nullable: false), - email_old = table.Column(type: "character varying(320)", maxLength: 320, nullable: false), - email_new = table.Column(type: "character varying(320)", maxLength: 320, nullable: false), - token_hash = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, collation: "C"), - used_at = table.Column(type: "timestamp with time zone", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_email_changes_pkey", x => x.id); - table.ForeignKey( - name: "fk_user_email_changes_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_name_changes", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn), - user_id = table.Column(type: "uuid", nullable: false), - old_name = table.Column(type: "character varying(32)", maxLength: 32, nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_name_changes_pkey", x => new { x.id, x.user_id }); - table.ForeignKey( - name: "fk_user_name_changes_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_oauth_connections", - columns: table => new - { - provider_key = table.Column(type: "text", nullable: false, collation: "C"), - external_id = table.Column(type: "text", nullable: false), - user_id = table.Column(type: "uuid", nullable: false), - display_name = table.Column(type: "text", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_oauth_connections_pkey", x => new { x.provider_key, x.external_id }); - table.ForeignKey( - name: "fk_user_oauth_connections_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_password_resets", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - user_id = table.Column(type: "uuid", nullable: false), - token_hash = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, collation: "C"), - used_at = table.Column(type: "timestamp with time zone", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_password_resets_pkey", x => x.id); - table.ForeignKey( - name: "fk_user_password_resets_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_share_invites", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - owner_id = table.Column(type: "uuid", nullable: false), - user_id = table.Column(type: "uuid", nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("user_share_invites_pkey", x => x.id); - table.ForeignKey( - name: "fk_user_share_invites_owner_id", - column: x => x.owner_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_user_share_invites_recipient_user_id", - column: x => x.user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "device_ota_updates", - columns: table => new - { - device_id = table.Column(type: "uuid", nullable: false), - update_id = table.Column(type: "integer", nullable: false), - status = table.Column(type: "ota_update_status", nullable: false), - version = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - message = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("device_ota_updates_pkey", x => new { x.device_id, x.update_id }); - table.ForeignKey( - name: "fk_device_ota_updates_device_id", - column: x => x.device_id, - principalTable: "devices", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "shockers", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - model = table.Column(type: "shocker_model_type", nullable: false), - rf_id = table.Column(type: "integer", nullable: false), - device_id = table.Column(type: "uuid", nullable: false), - is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("shockers_pkey", x => x.id); - table.ForeignKey( - name: "fk_shockers_device_id", - column: x => x.device_id, - principalTable: "devices", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "public_share_shockers", - columns: table => new - { - public_share_id = table.Column(type: "uuid", nullable: false), - shocker_id = table.Column(type: "uuid", nullable: false), - cooldown = table.Column(type: "integer", nullable: true), - allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: false), - max_intensity = table.Column(type: "smallint", nullable: true), - max_duration = table.Column(type: "integer", nullable: true), - is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) - }, - constraints: table => - { - table.PrimaryKey("public_share_shockers_pkey", x => new { x.public_share_id, x.shocker_id }); - table.ForeignKey( - name: "fk_public_share_shockers_public_share_id", - column: x => x.public_share_id, - principalTable: "public_shares", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_public_share_shockers_shocker_id", - column: x => x.shocker_id, - principalTable: "shockers", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "shocker_control_logs", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - shocker_id = table.Column(type: "uuid", nullable: false), - controlled_by_user_id = table.Column(type: "uuid", nullable: true), - intensity = table.Column(type: "smallint", nullable: false), - duration = table.Column(type: "bigint", nullable: false), - type = table.Column(type: "control_type", nullable: false), - custom_name = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), - live_control = table.Column(type: "boolean", nullable: false, defaultValue: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") - }, - constraints: table => - { - table.PrimaryKey("shocker_control_logs_pkey", x => x.id); - table.ForeignKey( - name: "fk_shocker_control_logs_controlled_by_user_id", - column: x => x.controlled_by_user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_shocker_control_logs_shocker_id", - column: x => x.shocker_id, - principalTable: "shockers", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "shocker_share_codes", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - shocker_id = table.Column(type: "uuid", nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: true), - max_intensity = table.Column(type: "smallint", nullable: true), - max_duration = table.Column(type: "integer", nullable: true), - is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) - }, - constraints: table => - { - table.PrimaryKey("shocker_share_codes_pkey", x => x.id); - table.ForeignKey( - name: "fk_shocker_share_codes_shocker_id", - column: x => x.shocker_id, - principalTable: "shockers", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_share_invite_shockers", - columns: table => new - { - invite_id = table.Column(type: "uuid", nullable: false), - shocker_id = table.Column(type: "uuid", nullable: false), - allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: true), - max_intensity = table.Column(type: "smallint", nullable: true), - max_duration = table.Column(type: "integer", nullable: true), - is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) - }, - constraints: table => - { - table.PrimaryKey("user_share_invite_shockers_pkey", x => new { x.invite_id, x.shocker_id }); - table.ForeignKey( - name: "fk_user_share_invite_shockers_invite_id", - column: x => x.invite_id, - principalTable: "user_share_invites", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_user_share_invite_shockers_shocker_id", - column: x => x.shocker_id, - principalTable: "shockers", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_shares", - columns: table => new - { - shared_with_user_id = table.Column(type: "uuid", nullable: false), - shocker_id = table.Column(type: "uuid", nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - allow_shock = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_vibrate = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_sound = table.Column(type: "boolean", nullable: false, defaultValue: true), - allow_livecontrol = table.Column(type: "boolean", nullable: false, defaultValue: true), - max_intensity = table.Column(type: "smallint", nullable: true), - max_duration = table.Column(type: "integer", nullable: true), - is_paused = table.Column(type: "boolean", nullable: false, defaultValue: false) - }, - constraints: table => - { - table.PrimaryKey("user_shares_pkey", x => new { x.shared_with_user_id, x.shocker_id }); - table.ForeignKey( - name: "fk_user_shares_shared_with_user_id", - column: x => x.shared_with_user_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_user_shares_shocker_id", - column: x => x.shocker_id, - principalTable: "shockers", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_api_token_reports_user_id", - table: "api_token_reports", - column: "user_id"); - - migrationBuilder.CreateIndex( - name: "IX_api_tokens_token_hash", - table: "api_tokens", - column: "token_hash", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_api_tokens_user_id", - table: "api_tokens", - column: "user_id"); - - migrationBuilder.CreateIndex( - name: "IX_api_tokens_valid_until", - table: "api_tokens", - column: "valid_until"); - - migrationBuilder.CreateIndex( - name: "device_ota_updates_created_at_idx", - table: "device_ota_updates", - column: "created_at"); - - migrationBuilder.CreateIndex( - name: "IX_devices_owner_id", - table: "devices", - column: "owner_id"); - - migrationBuilder.CreateIndex( - name: "IX_devices_token", - table: "devices", - column: "token", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_email_provider_blacklist_domain", - table: "email_provider_blacklist", - column: "domain", - unique: true) - .Annotation("Relational:Collation", new[] { "ndcoll" }); - - migrationBuilder.CreateIndex( - name: "IX_public_share_shockers_shocker_id", - table: "public_share_shockers", - column: "shocker_id"); - - migrationBuilder.CreateIndex( - name: "IX_public_shares_owner_id", - table: "public_shares", - column: "owner_id"); - - migrationBuilder.CreateIndex( - name: "IX_shocker_control_logs_controlled_by_user_id", - table: "shocker_control_logs", - column: "controlled_by_user_id"); - - migrationBuilder.CreateIndex( - name: "IX_shocker_control_logs_shocker_id", - table: "shocker_control_logs", - column: "shocker_id"); - - migrationBuilder.CreateIndex( - name: "IX_shocker_share_codes_shocker_id", - table: "shocker_share_codes", - column: "shocker_id"); - - migrationBuilder.CreateIndex( - name: "IX_shockers_device_id", - table: "shockers", - column: "device_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_activation_requests_token_hash", - table: "user_activation_requests", - column: "token_hash", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_user_deactivations_deactivated_by_user_id", - table: "user_deactivations", - column: "deactivated_by_user_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_email_changes_created_at", - table: "user_email_changes", - column: "created_at"); - - migrationBuilder.CreateIndex( - name: "IX_user_email_changes_used_at", - table: "user_email_changes", - column: "used_at"); - - migrationBuilder.CreateIndex( - name: "IX_user_email_changes_user_id", - table: "user_email_changes", - column: "user_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_name_blacklist_value", - table: "user_name_blacklist", - column: "value", - unique: true) - .Annotation("Relational:Collation", new[] { "ndcoll" }); - - migrationBuilder.CreateIndex( - name: "IX_user_name_changes_created_at", - table: "user_name_changes", - column: "created_at"); - - migrationBuilder.CreateIndex( - name: "IX_user_name_changes_old_name", - table: "user_name_changes", - column: "old_name"); - - migrationBuilder.CreateIndex( - name: "IX_user_name_changes_user_id", - table: "user_name_changes", - column: "user_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_oauth_connections_user_id", - table: "user_oauth_connections", - column: "user_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_password_resets_user_id", - table: "user_password_resets", - column: "user_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_share_invite_shockers_shocker_id", - table: "user_share_invite_shockers", - column: "shocker_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_share_invites_owner_id", - table: "user_share_invites", - column: "owner_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_share_invites_user_id", - table: "user_share_invites", - column: "user_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_shares_shared_with_user_id", - table: "user_shares", - column: "shared_with_user_id"); - - migrationBuilder.CreateIndex( - name: "IX_user_shares_shocker_id", - table: "user_shares", - column: "shocker_id"); - - migrationBuilder.CreateIndex( - name: "IX_users_email", - table: "users", - column: "email", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_users_name", - table: "users", - column: "name", - unique: true) - .Annotation("Relational:Collation", new[] { "ndcoll" }); + .Annotation("Npgsql:Enum:shocker_model_type", "caiXianlin,petTrainer,petrainer998DR,wellturnT330") + .OldAnnotation("Npgsql:CollationDefinition:public.ndcoll", "und-u-ks-level2,und-u-ks-level2,icu,False") + .OldAnnotation("Npgsql:Enum:configuration_value_type", "string,bool,int,float,json") + .OldAnnotation("Npgsql:Enum:control_type", "sound,vibrate,shock,stop") + .OldAnnotation("Npgsql:Enum:match_type_enum", "exact,contains") + .OldAnnotation("Npgsql:Enum:ota_update_status", "started,running,finished,error,timeout") + .OldAnnotation("Npgsql:Enum:password_encryption_type", "pbkdf2,bcrypt_enhanced") + .OldAnnotation("Npgsql:Enum:permission_type", "shockers.use,shockers.edit,shockers.pause,devices.edit,devices.auth") + .OldAnnotation("Npgsql:Enum:role_type", "support,staff,admin,system") + .OldAnnotation("Npgsql:Enum:shocker_model_type", "caiXianlin,petTrainer,petrainer998DR"); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropTable( - name: "api_token_reports"); - - migrationBuilder.DropTable( - name: "api_tokens"); - - migrationBuilder.DropTable( - name: "configuration"); - - migrationBuilder.DropTable( - name: "DataProtectionKeys"); - - migrationBuilder.DropTable( - name: "device_ota_updates"); - - migrationBuilder.DropTable( - name: "discord_webhooks"); - - migrationBuilder.DropTable( - name: "email_provider_blacklist"); - - migrationBuilder.DropTable( - name: "public_share_shockers"); - - migrationBuilder.DropTable( - name: "shocker_control_logs"); - - migrationBuilder.DropTable( - name: "shocker_share_codes"); - - migrationBuilder.DropTable( - name: "user_activation_requests"); - - migrationBuilder.DropTable( - name: "user_deactivations"); - - migrationBuilder.DropTable( - name: "user_email_changes"); - - migrationBuilder.DropTable( - name: "user_name_blacklist"); - - migrationBuilder.DropTable( - name: "user_name_changes"); - - migrationBuilder.DropTable( - name: "user_oauth_connections"); - - migrationBuilder.DropTable( - name: "user_password_resets"); - - migrationBuilder.DropTable( - name: "user_share_invite_shockers"); - - migrationBuilder.DropTable( - name: "user_shares"); - - migrationBuilder.DropTable( - name: "public_shares"); - - migrationBuilder.DropTable( - name: "user_share_invites"); - - migrationBuilder.DropTable( - name: "shockers"); - - migrationBuilder.DropTable( - name: "devices"); - - migrationBuilder.DropTable( - name: "users"); + migrationBuilder.AlterDatabase() + .Annotation("Npgsql:CollationDefinition:public.ndcoll", "und-u-ks-level2,und-u-ks-level2,icu,False") + .Annotation("Npgsql:Enum:configuration_value_type", "string,bool,int,float,json") + .Annotation("Npgsql:Enum:control_type", "sound,vibrate,shock,stop") + .Annotation("Npgsql:Enum:match_type_enum", "exact,contains") + .Annotation("Npgsql:Enum:ota_update_status", "started,running,finished,error,timeout") + .Annotation("Npgsql:Enum:password_encryption_type", "pbkdf2,bcrypt_enhanced") + .Annotation("Npgsql:Enum:permission_type", "shockers.use,shockers.edit,shockers.pause,devices.edit,devices.auth") + .Annotation("Npgsql:Enum:role_type", "support,staff,admin,system") + .Annotation("Npgsql:Enum:shocker_model_type", "caiXianlin,petTrainer,petrainer998DR") + .OldAnnotation("Npgsql:CollationDefinition:public.ndcoll", "und-u-ks-level2,und-u-ks-level2,icu,False") + .OldAnnotation("Npgsql:Enum:configuration_value_type", "string,bool,int,float,json") + .OldAnnotation("Npgsql:Enum:control_type", "sound,vibrate,shock,stop") + .OldAnnotation("Npgsql:Enum:match_type_enum", "exact,contains") + .OldAnnotation("Npgsql:Enum:ota_update_status", "started,running,finished,error,timeout") + .OldAnnotation("Npgsql:Enum:password_encryption_type", "pbkdf2,bcrypt_enhanced") + .OldAnnotation("Npgsql:Enum:permission_type", "shockers.use,shockers.edit,shockers.pause,devices.edit,devices.auth") + .OldAnnotation("Npgsql:Enum:role_type", "support,staff,admin,system") + .OldAnnotation("Npgsql:Enum:shocker_model_type", "caiXianlin,petTrainer,petrainer998DR,wellturnT330"); } } } diff --git a/Common/Migrations/OpenShockContextModelSnapshot.cs b/Common/Migrations/OpenShockContextModelSnapshot.cs index bede77ef..194008aa 100644 --- a/Common/Migrations/OpenShockContextModelSnapshot.cs +++ b/Common/Migrations/OpenShockContextModelSnapshot.cs @@ -1,17 +1,19 @@ // using System; +using System.Collections.Generic; using System.Net; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using OpenShock.Common.Models; using OpenShock.Common.OpenShockDb; #nullable disable namespace OpenShock.Common.Migrations { - [DbContext(typeof(OpenShockContext))] + [DbContext(typeof(MigrationOpenShockContext))] partial class OpenShockContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) @@ -107,7 +109,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer") .HasColumnName("password_reset_count"); - b.Property("Roles") + b.Property("Roles") .IsRequired() .HasColumnType("role_type[]") .HasColumnName("roles"); @@ -162,7 +164,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(64)") .HasColumnName("name"); - b.PrimitiveCollection("Permissions") + b.PrimitiveCollection>("Permissions") .IsRequired() .HasColumnType("permission_type[]") .HasColumnName("permissions"); @@ -254,8 +256,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("description"); - b.Property("Type") - .HasColumnType("integer") + b.Property("Type") + .HasColumnType("configuration_value_type") .HasColumnName("type"); b.Property("UpdatedAt") @@ -334,7 +336,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(128)") .HasColumnName("message"); - b.Property("Status") + b.Property("Status") .HasColumnType("ota_update_status") .HasColumnName("status"); @@ -529,7 +531,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasDefaultValue(false) .HasColumnName("is_paused"); - b.Property("Model") + b.Property("Model") .HasColumnType("shocker_model_type") .HasColumnName("model"); @@ -590,7 +592,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("shocker_id"); - b.Property("Type") + b.Property("Type") .HasColumnType("control_type") .HasColumnName("type"); @@ -701,7 +703,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("password_hash") .UseCollation("C"); - b.PrimitiveCollection("Roles") + b.PrimitiveCollection>("Roles") .IsRequired() .HasColumnType("role_type[]") .HasColumnName("roles"); @@ -847,8 +849,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("created_at") .HasDefaultValueSql("CURRENT_TIMESTAMP"); - b.Property("MatchType") - .HasColumnType("integer") + b.Property("MatchType") + .HasColumnType("match_type_enum") .HasColumnName("match_type"); b.Property("Value")