From 1331426f759e40274c26f85cfaea7851be0dd944 Mon Sep 17 00:00:00 2001 From: Aaron Leopold <36278431+aaronleopold@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:09:38 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Enforce=20case-insensitive=20use?= =?UTF-8?q?rname=20uniqueness=20=20(#557)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add migration for case insensitive username * fix form validation --- .../migration.sql | 24 +++++++++++++++++++ .../server/users/create-or-update/schema.ts | 2 +- packages/i18n/src/locales/en.json | 5 +++- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 core/prisma/migrations/20250108021921_case_insensitive_usernames/migration.sql diff --git a/core/prisma/migrations/20250108021921_case_insensitive_usernames/migration.sql b/core/prisma/migrations/20250108021921_case_insensitive_usernames/migration.sql new file mode 100644 index 000000000..100c5aaeb --- /dev/null +++ b/core/prisma/migrations/20250108021921_case_insensitive_usernames/migration.sql @@ -0,0 +1,24 @@ +-- RedefineTables +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_users" ( + "id" TEXT NOT NULL PRIMARY KEY, + "username" TEXT NOT NULL COLLATE NOCASE, + "hashed_password" TEXT NOT NULL, + "is_server_owner" BOOLEAN NOT NULL DEFAULT false, + "avatar_url" TEXT, + "last_login" DATETIME, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted_at" DATETIME, + "is_locked" BOOLEAN NOT NULL DEFAULT false, + "max_sessions_allowed" INTEGER, + "permissions" TEXT, + "user_preferences_id" TEXT, + CONSTRAINT "users_user_preferences_id_fkey" FOREIGN KEY ("user_preferences_id") REFERENCES "user_preferences" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_users" ("avatar_url", "created_at", "deleted_at", "hashed_password", "id", "is_locked", "is_server_owner", "last_login", "max_sessions_allowed", "permissions", "user_preferences_id", "username") SELECT "avatar_url", "created_at", "deleted_at", "hashed_password", "id", "is_locked", "is_server_owner", "last_login", "max_sessions_allowed", "permissions", "user_preferences_id", "username" FROM "users"; +DROP TABLE "users"; +ALTER TABLE "new_users" RENAME TO "users"; +CREATE UNIQUE INDEX "users_username_key" ON "users"("username"); +CREATE UNIQUE INDEX "users_user_preferences_id_key" ON "users"("user_preferences_id"); +PRAGMA foreign_key_check; +PRAGMA foreign_keys=ON; diff --git a/packages/browser/src/scenes/settings/server/users/create-or-update/schema.ts b/packages/browser/src/scenes/settings/server/users/create-or-update/schema.ts index f4be9804d..13c5c0dbe 100644 --- a/packages/browser/src/scenes/settings/server/users/create-or-update/schema.ts +++ b/packages/browser/src/scenes/settings/server/users/create-or-update/schema.ts @@ -71,7 +71,7 @@ export const buildSchema = ( .refine( (value) => (!!editingUser && value === editingUser.username) || - existingUsers.every((user) => user.username !== value), + existingUsers.every((user) => user.username.toLowerCase() !== value.toLowerCase()), () => ({ message: t( 'settingsScene.server/users.createOrUpdateForm.validation.usernameAlreadyExists', diff --git a/packages/i18n/src/locales/en.json b/packages/i18n/src/locales/en.json index 0778922c5..afe7c5d69 100644 --- a/packages/i18n/src/locales/en.json +++ b/packages/i18n/src/locales/en.json @@ -1582,7 +1582,10 @@ } }, "validation": { - "ageRestrictionTooLow": "Age restriction cannot be less than 0" + "ageRestrictionTooLow": "Age restriction cannot be less than 0", + "missingUsername": "Username is required", + "missingPassword": "Password is required", + "usernameAlreadyExists": "Username already exists" }, "createSubmitButton": "Create user", "updateSubmitButton": "Update user"