From 8c5cda1ebcc5ca57e104eb1bd9cfcfcf110f56d2 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Fri, 29 Mar 2024 17:40:02 -0700 Subject: [PATCH] Adding two factor code generation. --- drizzle/0008_amusing_franklin_richards.sql | 1 + drizzle/meta/0008_snapshot.json | 1526 +++++++++++++++++ drizzle/meta/_journal.json | 7 + package.json | 3 +- pnpm-lock.yaml | 240 ++- src/lib/validations/account.ts | 7 + .../(app)/(protected)/profile/+page.svelte | 6 +- .../security}/password/change/+page.server.ts | 32 +- .../security}/password/change/+page.svelte | 4 +- .../security/two-factor/+page.server.ts | 121 ++ .../profile/security/two-factor/+page.svelte | 29 + .../password/reset/+page.server.ts | 0 .../password/reset/+page.svelte | 0 ....timestamp-1711754490936-95fcefbe88e73.mjs | 44 + 14 files changed, 1955 insertions(+), 65 deletions(-) create mode 100644 drizzle/0008_amusing_franklin_richards.sql create mode 100644 drizzle/meta/0008_snapshot.json rename src/routes/(app)/(protected)/{ => profile/security}/password/change/+page.server.ts (79%) rename src/routes/(app)/(protected)/{ => profile/security}/password/change/+page.svelte (94%) create mode 100644 src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts create mode 100644 src/routes/(app)/(protected)/profile/security/two-factor/+page.svelte rename src/routes/{(app)/(protected) => (auth)}/password/reset/+page.server.ts (100%) rename src/routes/{(app)/(protected) => (auth)}/password/reset/+page.svelte (100%) create mode 100644 vite.config.ts.timestamp-1711754490936-95fcefbe88e73.mjs diff --git a/drizzle/0008_amusing_franklin_richards.sql b/drizzle/0008_amusing_franklin_richards.sql new file mode 100644 index 0000000..3239973 --- /dev/null +++ b/drizzle/0008_amusing_franklin_richards.sql @@ -0,0 +1 @@ +ALTER TABLE "users" ADD COLUMN "two_factor_secret" text; \ No newline at end of file diff --git a/drizzle/meta/0008_snapshot.json b/drizzle/meta/0008_snapshot.json new file mode 100644 index 0000000..97fc28d --- /dev/null +++ b/drizzle/meta/0008_snapshot.json @@ -0,0 +1,1526 @@ +{ + "id": "0b2ae1c1-86b0-4925-af3e-24d0c095fd7b", + "prevId": "70ee75d5-d697-49e0-9821-d3a1ac83aaef", + "version": "5", + "dialect": "pg", + "tables": { + "categories": { + "name": "categories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "categories_cuid_unique": { + "name": "categories_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "categories_to_external_ids": { + "name": "categories_to_external_ids", + "schema": "", + "columns": { + "category_id": { + "name": "category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "categories_to_external_ids_category_id_categories_id_fk": { + "name": "categories_to_external_ids_category_id_categories_id_fk", + "tableFrom": "categories_to_external_ids", + "tableTo": "categories", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "categories_to_external_ids_external_id_external_ids_id_fk": { + "name": "categories_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "categories_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "categories_to_external_ids_category_id_external_id_pk": { + "name": "categories_to_external_ids_category_id_external_id_pk", + "columns": [ + "category_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "categories_to_games": { + "name": "categories_to_games", + "schema": "", + "columns": { + "category_id": { + "name": "category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "categories_to_games_category_id_categories_id_fk": { + "name": "categories_to_games_category_id_categories_id_fk", + "tableFrom": "categories_to_games", + "tableTo": "categories", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "categories_to_games_game_id_games_id_fk": { + "name": "categories_to_games_game_id_games_id_fk", + "tableFrom": "categories_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "categories_to_games_category_id_game_id_pk": { + "name": "categories_to_games_category_id_game_id_pk", + "columns": [ + "category_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "collection_items": { + "name": "collection_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "collection_id": { + "name": "collection_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "times_played": { + "name": "times_played", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "collection_items_collection_id_collections_id_fk": { + "name": "collection_items_collection_id_collections_id_fk", + "tableFrom": "collection_items", + "tableTo": "collections", + "columnsFrom": [ + "collection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "collection_items_game_id_games_id_fk": { + "name": "collection_items_game_id_games_id_fk", + "tableFrom": "collection_items", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "collection_items_cuid_unique": { + "name": "collection_items_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "collections": { + "name": "collections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "collections_user_id_users_id_fk": { + "name": "collections_user_id_users_id_fk", + "tableFrom": "collections", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "collections_cuid_unique": { + "name": "collections_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "expansions": { + "name": "expansions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "base_game_id": { + "name": "base_game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "expansions_base_game_id_games_id_fk": { + "name": "expansions_base_game_id_games_id_fk", + "tableFrom": "expansions", + "tableTo": "games", + "columnsFrom": [ + "base_game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "expansions_game_id_games_id_fk": { + "name": "expansions_game_id_games_id_fk", + "tableFrom": "expansions", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "expansions_cuid_unique": { + "name": "expansions_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "external_ids": { + "name": "external_ids", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "external_id_type", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "external_ids_cuid_unique": { + "name": "external_ids_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "games": { + "name": "games", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "year_published": { + "name": "year_published", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_players": { + "name": "min_players", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "max_players": { + "name": "max_players", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "playtime": { + "name": "playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_playtime": { + "name": "min_playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "max_playtime": { + "name": "max_playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_age": { + "name": "min_age", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "image_url": { + "name": "image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "thumb_url": { + "name": "thumb_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "text_searchable_index": { + "name": "text_searchable_index", + "type": "tsvector", + "primaryKey": false, + "notNull": false + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "text_searchable_idx": { + "name": "text_searchable_idx", + "columns": [ + "text_searchable_index" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "games_cuid_unique": { + "name": "games_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "games_to_external_ids": { + "name": "games_to_external_ids", + "schema": "", + "columns": { + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "games_to_external_ids_game_id_games_id_fk": { + "name": "games_to_external_ids_game_id_games_id_fk", + "tableFrom": "games_to_external_ids", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "games_to_external_ids_external_id_external_ids_id_fk": { + "name": "games_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "games_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "games_to_external_ids_game_id_external_id_pk": { + "name": "games_to_external_ids_game_id_external_id_pk", + "columns": [ + "game_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "mechanics": { + "name": "mechanics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mechanics_cuid_unique": { + "name": "mechanics_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "mechanics_to_external_ids": { + "name": "mechanics_to_external_ids", + "schema": "", + "columns": { + "mechanic_id": { + "name": "mechanic_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { + "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", + "tableFrom": "mechanics_to_external_ids", + "tableTo": "mechanics", + "columnsFrom": [ + "mechanic_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "mechanics_to_external_ids_external_id_external_ids_id_fk": { + "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "mechanics_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "mechanics_to_external_ids_mechanic_id_external_id_pk": { + "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", + "columns": [ + "mechanic_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "mechanics_to_games": { + "name": "mechanics_to_games", + "schema": "", + "columns": { + "mechanic_id": { + "name": "mechanic_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mechanics_to_games_mechanic_id_mechanics_id_fk": { + "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", + "tableFrom": "mechanics_to_games", + "tableTo": "mechanics", + "columnsFrom": [ + "mechanic_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "mechanics_to_games_game_id_games_id_fk": { + "name": "mechanics_to_games_game_id_games_id_fk", + "tableFrom": "mechanics_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "mechanics_to_games_mechanic_id_game_id_pk": { + "name": "mechanics_to_games_mechanic_id_game_id_pk", + "columns": [ + "mechanic_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "password_reset_tokens": { + "name": "password_reset_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "password_reset_tokens_user_id_users_id_fk": { + "name": "password_reset_tokens_user_id_users_id_fk", + "tableFrom": "password_reset_tokens", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "publishers": { + "name": "publishers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "publishers_cuid_unique": { + "name": "publishers_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "publishers_to_external_ids": { + "name": "publishers_to_external_ids", + "schema": "", + "columns": { + "publisher_id": { + "name": "publisher_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "publishers_to_external_ids_publisher_id_publishers_id_fk": { + "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", + "tableFrom": "publishers_to_external_ids", + "tableTo": "publishers", + "columnsFrom": [ + "publisher_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "publishers_to_external_ids_external_id_external_ids_id_fk": { + "name": "publishers_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "publishers_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "publishers_to_external_ids_publisher_id_external_id_pk": { + "name": "publishers_to_external_ids_publisher_id_external_id_pk", + "columns": [ + "publisher_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "publishers_to_games": { + "name": "publishers_to_games", + "schema": "", + "columns": { + "publisher_id": { + "name": "publisher_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "publishers_to_games_publisher_id_publishers_id_fk": { + "name": "publishers_to_games_publisher_id_publishers_id_fk", + "tableFrom": "publishers_to_games", + "tableTo": "publishers", + "columnsFrom": [ + "publisher_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "publishers_to_games_game_id_games_id_fk": { + "name": "publishers_to_games_game_id_games_id_fk", + "tableFrom": "publishers_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "publishers_to_games_publisher_id_game_id_pk": { + "name": "publishers_to_games_publisher_id_game_id_pk", + "columns": [ + "publisher_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "roles": { + "name": "roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "roles_cuid_unique": { + "name": "roles_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "roles_name_unique": { + "name": "roles_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + } + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ip_country": { + "name": "ip_country", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_roles": { + "name": "user_roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "primary": { + "name": "primary", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_roles_user_id_users_id_fk": { + "name": "user_roles_user_id_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_role_id_roles_id_fk": { + "name": "user_roles_role_id_roles_id_fk", + "tableFrom": "user_roles", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_roles_cuid_unique": { + "name": "user_roles_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "hashed_password": { + "name": "hashed_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "receive_email": { + "name": "receive_email", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'system'" + }, + "two_factor_secret": { + "name": "two_factor_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_cuid_unique": { + "name": "users_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "users_username_unique": { + "name": "users_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + }, + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "wishlist_items": { + "name": "wishlist_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "wishlist_id": { + "name": "wishlist_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "wishlist_items_wishlist_id_wishlists_id_fk": { + "name": "wishlist_items_wishlist_id_wishlists_id_fk", + "tableFrom": "wishlist_items", + "tableTo": "wishlists", + "columnsFrom": [ + "wishlist_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "wishlist_items_game_id_games_id_fk": { + "name": "wishlist_items_game_id_games_id_fk", + "tableFrom": "wishlist_items", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "wishlist_items_cuid_unique": { + "name": "wishlist_items_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "wishlists": { + "name": "wishlists", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "wishlists_user_id_users_id_fk": { + "name": "wishlists_user_id_users_id_fk", + "tableFrom": "wishlists", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "wishlists_cuid_unique": { + "name": "wishlists_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + } + }, + "enums": { + "external_id_type": { + "name": "external_id_type", + "values": { + "game": "game", + "category": "category", + "mechanic": "mechanic", + "publisher": "publisher", + "designer": "designer", + "artist": "artist" + } + } + }, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 820bdd3..be102db 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -57,6 +57,13 @@ "when": 1710905572670, "tag": "0007_large_miss_america", "breakpoints": true + }, + { + "idx": 8, + "version": "5", + "when": 1711757183163, + "tag": "0008_amusing_franklin_richards", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package.json b/package.json index e8ff13c..04efc7e 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@melt-ui/pp": "^0.3.0", "@melt-ui/svelte": "^0.76.2", "@playwright/test": "^1.42.1", - "@resvg/resvg-js": "^2.6.0", + "@resvg/resvg-js": "^2.6.1", "@sveltejs/adapter-auto": "^3.1.1", "@sveltejs/enhanced-img": "^0.1.9", "@sveltejs/kit": "^2.5.4", @@ -106,6 +106,7 @@ "oslo": "^1.1.3", "pg": "^8.11.3", "postgres": "^3.4.4", + "qrcode": "^1.5.3", "radix-svelte": "^0.9.0", "svelte-french-toast": "^1.2.0", "svelte-lazy-loader": "^1.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1117f0..4f65723 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ dependencies: postgres: specifier: ^3.4.4 version: 3.4.4 + qrcode: + specifier: ^1.5.3 + version: 1.5.3 radix-svelte: specifier: ^0.9.0 version: 0.9.0(svelte@4.2.12) @@ -131,8 +134,8 @@ devDependencies: specifier: ^1.42.1 version: 1.42.1 '@resvg/resvg-js': - specifier: ^2.6.0 - version: 2.6.0 + specifier: ^2.6.1 + version: 2.6.1 '@sveltejs/adapter-auto': specifier: ^3.1.1 version: 3.1.1(@sveltejs/kit@2.5.4) @@ -2736,8 +2739,8 @@ packages: requiresBuild: true optional: true - /@resvg/resvg-js-android-arm-eabi@2.6.0: - resolution: {integrity: sha512-lJnZ/2P5aMocrFMW7HWhVne5gH82I8xH6zsfH75MYr4+/JOaVcGCTEQ06XFohGMdYRP3v05SSPLPvTM/RHjxfA==} + /@resvg/resvg-js-android-arm-eabi@2.6.1: + resolution: {integrity: sha512-oXmXUUqTzinvXwkVBDdNKocAeF1zLGJYasTNRmoqF3gyOm04qRYT1On0m6oK2jbTiUAOUTqi0ZSizcecnwcSDA==} engines: {node: '>= 10'} cpu: [arm] os: [android] @@ -2745,8 +2748,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-android-arm64@2.6.0: - resolution: {integrity: sha512-N527f529bjMwYWShZYfBD60dXA4Fux+D695QsHQ93BDYZSHUoOh1CUGUyICevnTxs7VgEl98XpArmUWBZQVMfQ==} + /@resvg/resvg-js-android-arm64@2.6.1: + resolution: {integrity: sha512-vcCZoBx8s/3/+t6nDd9fB/LL70I4B2YmgDT7uP6wyqVCUPniNeLR9VYIuvpMHw6oVyL5Mpt8F2YXV1zQE2X2hw==} engines: {node: '>= 10'} cpu: [arm64] os: [android] @@ -2754,8 +2757,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-darwin-arm64@2.6.0: - resolution: {integrity: sha512-MabUKLVayEwlPo0mIqAmMt+qESN8LltCvv5+GLgVga1avpUrkxj/fkU1TKm8kQegutUjbP/B0QuMuUr0uhF8ew==} + /@resvg/resvg-js-darwin-arm64@2.6.1: + resolution: {integrity: sha512-uO0WvEQqQlAL8u7nI7k1yL5wSsZYU2YCSsN1hAhr1LjyvmWmyC09xUEdWPUVVT1nL2YK4Ueh0LR+pxOT3QlCng==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -2763,8 +2766,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-darwin-x64@2.6.0: - resolution: {integrity: sha512-zrFetdnSw/suXjmyxSjfDV7i61hahv6DDG6kM7BYN2yJ3Es5+BZtqYZTcIWogPJedYKmzN1YTMWGd/3f0ubFiA==} + /@resvg/resvg-js-darwin-x64@2.6.1: + resolution: {integrity: sha512-aW15HMQSk85GPHE4gsc56G0Fqi2IGVkDfPWEWHEyDBpCZ17RKweAwg5V3ioz9aGX1nmhjQa9tJ2xgVwX+sqIjw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -2772,8 +2775,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-linux-arm-gnueabihf@2.6.0: - resolution: {integrity: sha512-sH4gxXt7v7dGwjGyzLwn7SFGvwZG6DQqLaZ11MmzbCwd9Zosy1TnmrMJfn6TJ7RHezmQMgBPi18bl55FZ1AT4A==} + /@resvg/resvg-js-linux-arm-gnueabihf@2.6.1: + resolution: {integrity: sha512-7vpBFzCMONnRzK0uCBT5h+Dmsa8dWsoLFqB6xgutNfKkldjuCOiLNe0tT7hneGF8tw5H+W6hX/VLx2ktDwsS4Q==} engines: {node: '>= 10'} cpu: [arm] os: [linux] @@ -2781,8 +2784,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-linux-arm64-gnu@2.6.0: - resolution: {integrity: sha512-fCyMncqCJtrlANADIduYF4IfnWQ295UKib7DAxFXQhBsM9PLDTpizr0qemZcCNadcwSVHnAIzL4tliZhCM8P6A==} + /@resvg/resvg-js-linux-arm64-gnu@2.6.1: + resolution: {integrity: sha512-+Gi3OIOJFFiCdm72AsDa7KPnkogitLQ6yfF1O/J25adUrlWjvKAM9+8b5sTI9waeLERZHNJpIVESpdIxI2/5sQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -2790,8 +2793,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-linux-arm64-musl@2.6.0: - resolution: {integrity: sha512-ouLjTgBQHQyxLht4FdMPTvuY8xzJigM9EM2Tlu0llWkN1mKyTQrvYWi6TA6XnKdzDJHy7ZLpWpjZi7F5+Pg+Vg==} + /@resvg/resvg-js-linux-arm64-musl@2.6.1: + resolution: {integrity: sha512-lnRGWG/LwpX6UsV1neHAavPnek3WlCnGMdBZ/7JbpamK5VmtDZmsV2esOFpME6pKnWL40UX4WjPsCBtKkhMUMA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -2799,8 +2802,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-linux-x64-gnu@2.6.0: - resolution: {integrity: sha512-n3zC8DWsvxC1AwxpKFclIPapDFibs5XdIRoV/mcIlxlh0vseW1F49b97F33BtJQRmlntsqqN6GMMqx8byB7B+Q==} + /@resvg/resvg-js-linux-x64-gnu@2.6.1: + resolution: {integrity: sha512-2S1N7fHl5480AUrUtxsfjFOh3t8NQ2qKavROZRDKWJqFXBrNOUsirDa33LtpFGDkFW18SjP/FCs1xfHLzzz43g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -2808,8 +2811,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-linux-x64-musl@2.6.0: - resolution: {integrity: sha512-n4tasK1HOlAxdTEROgYA1aCfsEKk0UOFDNd/AQTTZlTmCbHKXPq+O8npaaKlwXquxlVK8vrkcWbksbiGqbCAcw==} + /@resvg/resvg-js-linux-x64-musl@2.6.1: + resolution: {integrity: sha512-G5GMmpvFiyclkp44eVPVWnN2lhLx9eMIcxGnBFWjnpI3TxrjBt7aVic2N8CsZ0vt2rrnJkQI0IKjUQQIi138Hw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -2817,8 +2820,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-win32-arm64-msvc@2.6.0: - resolution: {integrity: sha512-X2+EoBJFwDI5LDVb51Sk7ldnVLitMGr9WwU/i21i3fAeAXZb3hM16k67DeTy16OYkT2dk/RfU1tP1wG+rWbz2Q==} + /@resvg/resvg-js-win32-arm64-msvc@2.6.1: + resolution: {integrity: sha512-m9TBMrGs2tML0oz14D/x40tPedqCgNFy/DH7/z/bvnP9bH59fivaInmHTjd8oSFfGRZ/DasXMFcAL+LS1+hfSQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -2826,8 +2829,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-win32-ia32-msvc@2.6.0: - resolution: {integrity: sha512-L7oevWjQoUgK5W1fCKn0euSVemhDXVhrjtwqpc7MwBKKimYeiOshO1Li1pa8bBt5PESahenhWgdB6lav9O0fEg==} + /@resvg/resvg-js-win32-ia32-msvc@2.6.1: + resolution: {integrity: sha512-Ma+MJXesViT0A7JqTobsB9DOCO0AkfmLxsgkvxq0IiWkpU9Z4Gp+RkDsFQbMhJwVXaz7b8L6y+EIvf95iCbJQw==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -2835,8 +2838,8 @@ packages: dev: true optional: true - /@resvg/resvg-js-win32-x64-msvc@2.6.0: - resolution: {integrity: sha512-8lJlghb+Unki5AyKgsnFbRJwkEj9r1NpwyuBG8yEJiG1W9eEGl03R3I7bsVa3haof/3J1NlWf0rzSa1G++A2iw==} + /@resvg/resvg-js-win32-x64-msvc@2.6.1: + resolution: {integrity: sha512-mWIlgEuFWBrlldCbhLPvG4tt0r0D1RZ8eR2+zxTtQ15d/lbVjwnGpw2l1noV3zhV5S6mAVzoZeQ1emoov63Y/A==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2844,22 +2847,22 @@ packages: dev: true optional: true - /@resvg/resvg-js@2.6.0: - resolution: {integrity: sha512-Tf3YpbBKcQn991KKcw/vg7vZf98v01seSv6CVxZBbRkL/xyjnoYB6KgrFL6zskT1A4dWC/vg77KyNOW+ePaNlA==} + /@resvg/resvg-js@2.6.1: + resolution: {integrity: sha512-CVGUWPvgr3b96+PooncXCsvu93CMwfEoueqIxIJr9AuUA8OaIPcZjOgFhas62fcHRdWMmxQqF1Rp+89bQsj/RA==} engines: {node: '>= 10'} optionalDependencies: - '@resvg/resvg-js-android-arm-eabi': 2.6.0 - '@resvg/resvg-js-android-arm64': 2.6.0 - '@resvg/resvg-js-darwin-arm64': 2.6.0 - '@resvg/resvg-js-darwin-x64': 2.6.0 - '@resvg/resvg-js-linux-arm-gnueabihf': 2.6.0 - '@resvg/resvg-js-linux-arm64-gnu': 2.6.0 - '@resvg/resvg-js-linux-arm64-musl': 2.6.0 - '@resvg/resvg-js-linux-x64-gnu': 2.6.0 - '@resvg/resvg-js-linux-x64-musl': 2.6.0 - '@resvg/resvg-js-win32-arm64-msvc': 2.6.0 - '@resvg/resvg-js-win32-ia32-msvc': 2.6.0 - '@resvg/resvg-js-win32-x64-msvc': 2.6.0 + '@resvg/resvg-js-android-arm-eabi': 2.6.1 + '@resvg/resvg-js-android-arm64': 2.6.1 + '@resvg/resvg-js-darwin-arm64': 2.6.1 + '@resvg/resvg-js-darwin-x64': 2.6.1 + '@resvg/resvg-js-linux-arm-gnueabihf': 2.6.1 + '@resvg/resvg-js-linux-arm64-gnu': 2.6.1 + '@resvg/resvg-js-linux-arm64-musl': 2.6.1 + '@resvg/resvg-js-linux-x64-gnu': 2.6.1 + '@resvg/resvg-js-linux-x64-musl': 2.6.1 + '@resvg/resvg-js-win32-arm64-msvc': 2.6.1 + '@resvg/resvg-js-win32-ia32-msvc': 2.6.1 + '@resvg/resvg-js-win32-x64-msvc': 2.6.1 dev: true /@resvg/resvg-wasm@2.6.0: @@ -3216,8 +3219,8 @@ packages: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true - /@sinclair/typebox@0.32.19: - resolution: {integrity: sha512-AUphm4Py6t+q5b6TU8OA9YRgeGfogsWy2oZvYLRCxt6d+mPkT0Mc4j+BusQYMGJH47DJe3/fKkLtmWPrKP1nzQ==} + /@sinclair/typebox@0.32.20: + resolution: {integrity: sha512-ziK497ILSIYMxD/thl496idIb03IZPlha04itLQu1xAFQbumWZ+Dj4PMMCkDRpAYhvVSdmRlTjGu2B2MA5RplQ==} requiresBuild: true optional: true @@ -3683,7 +3686,6 @@ packages: engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - dev: true /ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} @@ -3888,6 +3890,11 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: false + /camelcase@7.0.1: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} @@ -3992,6 +3999,14 @@ packages: timers-ext: 0.1.7 dev: true + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: false + /clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -4016,7 +4031,6 @@ packages: engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 - dev: true /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -4172,6 +4186,11 @@ packages: dependencies: ms: 2.1.2 + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: false + /deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} @@ -4243,6 +4262,10 @@ packages: heap: 0.2.7 dev: true + /dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dev: false + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -4389,6 +4412,10 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: false + /encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + dev: false + /env-paths@3.0.0: resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4834,6 +4861,14 @@ packages: dependencies: to-regex-range: 5.0.1 + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: false + /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -4929,6 +4964,11 @@ packages: wide-align: 1.1.5 dev: false + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + /get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} dev: true @@ -5417,6 +5457,13 @@ packages: /locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: false + /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -5836,6 +5883,13 @@ packages: '@node-rs/bcrypt': 1.9.0 dev: false + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: false + /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -5849,12 +5903,24 @@ packages: yocto-queue: 1.0.0 dev: true + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: false + /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} dependencies: p-limit: 3.1.0 + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: false + /packet-reader@1.0.0: resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==} dev: false @@ -6041,6 +6107,11 @@ packages: fsevents: 2.3.2 dev: true + /pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + dev: false + /postcss-attribute-case-insensitive@6.0.3(postcss@8.4.38): resolution: {integrity: sha512-KHkmCILThWBRtg+Jn1owTnHPnFit4OkqS+eKiGEOPIGke54DCeYGJ6r0Fx/HjfE9M9kznApCLcU0DvnPchazMQ==} engines: {node: ^14 || ^16 || >=18} @@ -6611,6 +6682,17 @@ packages: engines: {node: '>=6'} dev: true + /qrcode@1.5.3: + resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + dijkstrajs: 1.0.3 + encode-utf8: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + dev: false + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -6668,6 +6750,15 @@ packages: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} dev: false + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: false + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -7278,6 +7369,23 @@ packages: peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 + peerDependenciesMeta: + '@sinclair/typebox': + optional: true + '@vinejs/vine': + optional: true + arktype: + optional: true + joi: + optional: true + superstruct: + optional: true + valibot: + optional: true + yup: + optional: true + zod: + optional: true dependencies: '@sveltejs/kit': 2.5.4(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.2.6) devalue: 4.3.2 @@ -7287,7 +7395,7 @@ packages: ts-deepmerge: 7.0.0 optionalDependencies: '@gcornut/valibot-json-schema': 0.0.26(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(valibot@0.30.0) - '@sinclair/typebox': 0.32.19 + '@sinclair/typebox': 0.32.20 '@sodaru/yup-to-json-schema': 2.0.1 '@vinejs/vine': 1.8.0 arktype: 1.0.29-alpha @@ -7781,6 +7889,10 @@ packages: webidl-conversions: 3.0.1 dev: false + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: false + /which-typed-array@1.1.13: resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} engines: {node: '>= 0.4'} @@ -7818,6 +7930,15 @@ packages: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} dev: true + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -7826,6 +7947,10 @@ packages: engines: {node: '>=0.4'} dev: false + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: false + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -7838,6 +7963,31 @@ packages: resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} engines: {node: '>= 14'} + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: false + + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: false + /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} diff --git a/src/lib/validations/account.ts b/src/lib/validations/account.ts index b9366bf..19e8692 100644 --- a/src/lib/validations/account.ts +++ b/src/lib/validations/account.ts @@ -23,6 +23,13 @@ export const changeUserPasswordSchema = z export type ChangeUserPasswordSchema = typeof changeUserPasswordSchema; +export const addTwoFactorSchema = z.object({ + current_password: z.string({ required_error: 'Current Password is required' }), + two_factor_code: z.string({ required_error: 'Two Factor Code is required' }).trim() +}); + +export type AddTwoFactorSchema = typeof addTwoFactorSchema; + export const updateUserPasswordSchema = userSchema .pick({ password: true, confirm_password: true }) .superRefine(({ confirm_password, password }, ctx) => { diff --git a/src/routes/(app)/(protected)/profile/+page.svelte b/src/routes/(app)/(protected)/profile/+page.svelte index 8f2ce97..a2b7f39 100644 --- a/src/routes/(app)/(protected)/profile/+page.svelte +++ b/src/routes/(app)/(protected)/profile/+page.svelte @@ -94,19 +94,19 @@
{#if !hasSetupTwoFactor} - {:else} - {/if}
- diff --git a/src/routes/(app)/(protected)/password/change/+page.server.ts b/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts similarity index 79% rename from src/routes/(app)/(protected)/password/change/+page.server.ts rename to src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts index 90afba4..1e1d7dc 100644 --- a/src/routes/(app)/(protected)/password/change/+page.server.ts +++ b/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts @@ -1,16 +1,16 @@ -import { fail, type Actions } from "@sveltejs/kit"; -import { eq } from "drizzle-orm"; +import { fail, type Actions } from '@sveltejs/kit'; +import { eq } from 'drizzle-orm'; import { zod } from 'sveltekit-superforms/adapters'; import { setError, superValidate } from 'sveltekit-superforms/server'; -import { redirect } from 'sveltekit-flash-message/server' -import { Argon2id } from "oslo/password"; -import db from "$lib/drizzle"; +import { redirect } from 'sveltekit-flash-message/server'; +import { Argon2id } from 'oslo/password'; +import type { PageServerLoad } from '../../../$types'; +import db from '$lib/drizzle'; import { changeUserPasswordSchema } from '$lib/validations/account'; import { lucia } from '$lib/server/auth.js'; -import type { PageServerLoad } from "./$types"; -import { users } from "../../../../../schema"; -import { notSignedInMessage } from "$lib/flashMessages"; -import type { Cookie } from "lucia"; +import { users } from '../../../../../../../schema'; +import { notSignedInMessage } from '$lib/flashMessages'; +import type { Cookie } from 'lucia'; export const load: PageServerLoad = async (event) => { const form = await superValidate(event, zod(changeUserPasswordSchema)); @@ -42,7 +42,7 @@ export const actions: Actions = { console.log('updating profile'); if (!event.locals.user) { - redirect(302, '/login', notSignedInMessage, event); + redirect(302, '/login', notSignedInMessage, event); } if (!event.locals.session) { @@ -65,7 +65,10 @@ export const actions: Actions = { ); } - const currentPasswordVerified = await new Argon2id().verify(dbUser.hashed_password, form.data.current_password); + const currentPasswordVerified = await new Argon2id().verify( + dbUser.hashed_password, + form.data.current_password + ); if (!currentPasswordVerified) { return setError(form, 'current_password', 'Your password is incorrect'); @@ -78,11 +81,12 @@ export const actions: Actions = { } const hashedPassword = await new Argon2id().hash(form.data.password); await lucia.invalidateUserSessions(user.id); - await db.update(users) + await db + .update(users) .set({ hashed_password: hashedPassword }) .where(eq(users.id, user.id)); await lucia.createSession(user.id, { - country: event.locals.session?.ipCountry ?? 'unknown', + country: event.locals.session?.ipCountry ?? 'unknown' }); sessionCookie = lucia.createBlankSessionCookie(); } catch (e) { @@ -93,7 +97,7 @@ export const actions: Actions = { return setError(form, 'current_password', 'Your password is incorrect.'); } event.cookies.set(sessionCookie.name, sessionCookie.value, { - path: ".", + path: '.', ...sessionCookie.attributes }); diff --git a/src/routes/(app)/(protected)/password/change/+page.svelte b/src/routes/(app)/(protected)/profile/security/password/change/+page.svelte similarity index 94% rename from src/routes/(app)/(protected)/password/change/+page.svelte rename to src/routes/(app)/(protected)/profile/security/password/change/+page.svelte index a23c724..e5c7422 100644 --- a/src/routes/(app)/(protected)/password/change/+page.svelte +++ b/src/routes/(app)/(protected)/profile/security/password/change/+page.svelte @@ -2,8 +2,8 @@ import { zodClient } from 'sveltekit-superforms/adapters'; import { superForm } from 'sveltekit-superforms/client'; import { AlertTriangle } from 'lucide-svelte'; - import * as Alert from "$lib/components/ui/alert"; - import * as Form from '$lib/components/ui/form'; + import * as Alert from "$components/ui/alert"; + import * as Form from '$components/ui/form'; import { Input } from '$components/ui/input'; import { changeUserPasswordSchema } from '$lib/validations/account'; diff --git a/src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts b/src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts new file mode 100644 index 0000000..140a542 --- /dev/null +++ b/src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts @@ -0,0 +1,121 @@ +import { encodeHex } from 'oslo/encoding'; +import { Argon2id } from 'oslo/password'; +import { createTOTPKeyURI } from 'oslo/otp'; +import { HMAC } from 'oslo/crypto'; +import { zod } from 'sveltekit-superforms/adapters'; +import { setError, superValidate } from 'sveltekit-superforms/server'; +import { redirect } from 'sveltekit-flash-message/server'; +import type { Cookie } from 'lucia'; +import type { PageServerLoad } from '../../$types'; +import { addTwoFactorSchema } from '$lib/validations/account'; +import { notSignedInMessage } from '$lib/flashMessages'; +import { type Actions, fail } from '@sveltejs/kit'; +import db from '$lib/drizzle'; +import { eq } from 'drizzle-orm'; +import { users } from '../../../../../../schema'; +import QRCode from 'qrcode'; + +export const load: PageServerLoad = async (event) => { + const form = await superValidate(event, zod(addTwoFactorSchema)); + const user = event.locals.user; + + if (!user) { + redirect(302, '/login', notSignedInMessage, event); + } + + const twoFactorSecret = await new HMAC('SHA-1').generateKey(); + await db + .update(users) + .set({ two_factor_secret: encodeHex(twoFactorSecret) }) + .where(eq(users.id, user.id)); + + const issuer = 'bored-game'; + const accountName = user.email || user.username; + // pass the website's name and the user identifier (e.g. email, username) + const uri = createTOTPKeyURI(issuer, accountName, twoFactorSecret); + const qrCode = await QRCode.toDataURL(uri); + + form.data = { + current_password: '', + two_factor_code: '' + }; + return { + form, + qrCode + }; +}; + +export const actions: Actions = { + default: async (event) => { + const form = await superValidate(event, zod(addTwoFactorSchema)); + + if (!form.valid) { + return fail(400, { + form + }); + } + + console.log('updating profile'); + if (!event.locals.user) { + redirect(302, '/login', notSignedInMessage, event); + } + + if (!event.locals.session) { + return fail(401); + } + + const user = event.locals.user; + + const dbUser = await db.query.users.findFirst({ + where: eq(users.id, user.id) + }); + + if (!dbUser?.hashed_password) { + form.data.current_password = ''; + form.data.two_factor_code = ''; + return setError( + form, + 'Error occurred. Please try again or contact support if you need further help.' + ); + } + + const currentPasswordVerified = await new Argon2id().verify( + dbUser.hashed_password, + form.data.current_password + ); + + if (!currentPasswordVerified) { + return setError(form, 'current_password', 'Your password is incorrect'); + } + if (user?.username) { + let sessionCookie: Cookie; + try { + } catch (e) { + console.error(e); + form.data.password = ''; + form.data.confirm_password = ''; + form.data.current_password = ''; + return setError(form, 'current_password', 'Your password is incorrect.'); + } + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: '.', + ...sessionCookie.attributes + }); + + const message = { + type: 'success', + message: 'Password Updated. Please sign in.' + } as const; + redirect(302, '/login', message, event); + } + return setError( + form, + 'Error occurred. Please try again or contact support if you need further help.' + ); + // TODO: Add toast instead? + // form.data.password = ''; + // form.data.confirm_password = ''; + // form.data.current_password = ''; + // return message(form, 'Profile updated successfully.'); + } +}; diff --git a/src/routes/(app)/(protected)/profile/security/two-factor/+page.svelte b/src/routes/(app)/(protected)/profile/security/two-factor/+page.svelte new file mode 100644 index 0000000..15915ae --- /dev/null +++ b/src/routes/(app)/(protected)/profile/security/two-factor/+page.svelte @@ -0,0 +1,29 @@ + + +

Two-Factor Authentication

+ +QR Code + diff --git a/src/routes/(app)/(protected)/password/reset/+page.server.ts b/src/routes/(auth)/password/reset/+page.server.ts similarity index 100% rename from src/routes/(app)/(protected)/password/reset/+page.server.ts rename to src/routes/(auth)/password/reset/+page.server.ts diff --git a/src/routes/(app)/(protected)/password/reset/+page.svelte b/src/routes/(auth)/password/reset/+page.svelte similarity index 100% rename from src/routes/(app)/(protected)/password/reset/+page.svelte rename to src/routes/(auth)/password/reset/+page.svelte diff --git a/vite.config.ts.timestamp-1711754490936-95fcefbe88e73.mjs b/vite.config.ts.timestamp-1711754490936-95fcefbe88e73.mjs new file mode 100644 index 0000000..5958611 --- /dev/null +++ b/vite.config.ts.timestamp-1711754490936-95fcefbe88e73.mjs @@ -0,0 +1,44 @@ +// vite.config.ts +import { sveltekit } from "file:///home/bshellnu/projects/websites/boredgame/node_modules/.pnpm/@sveltejs+kit@2.5.4_@sveltejs+vite-plugin-svelte@3.0.2_svelte@4.2.12_vite@5.2.6/node_modules/@sveltejs/kit/src/exports/vite/index.js"; +import { defineConfig } from "file:///home/bshellnu/projects/websites/boredgame/node_modules/.pnpm/vite@5.2.6_@types+node@20.11.30_sass@1.72.0/node_modules/vite/dist/node/index.js"; +var vite_config_default = defineConfig({ + plugins: [ + // sentrySvelteKit({ + // sourceMapsUploadOptions: { + // org: process.env.SENTRY_ORG, + // project: process.env.SENTRY_PROJECT, + // authToken: process.env.SENTRY_AUTH_TOKEN, + // cleanArtifacts: true, + // } + // }), + sveltekit() + ], + test: { + include: ["src/**/*.{test,spec}.{js,ts}"] + }, + define: { + SUPERFORMS_LEGACY: true + }, + css: { + devSourcemap: true, + preprocessorOptions: { + postcss: { + additionalData: ` + @custom-media --below_small (width < 400px); + @custom-media --below_med (width < 700px); + @custom-media --below_large (width < 900px); + @custom-media --below_xlarge (width < 1200px); + + @custom-media --above_small (width > 400px); + @custom-media --above_med (width > 700px); + @custom-media --above_large (width > 900px); + @custom-media --above_xlarge (width > 1200px); + ` + } + } + } +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvaG9tZS9ic2hlbGxudS9wcm9qZWN0cy93ZWJzaXRlcy9ib3JlZGdhbWVcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2JzaGVsbG51L3Byb2plY3RzL3dlYnNpdGVzL2JvcmVkZ2FtZS92aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9ic2hlbGxudS9wcm9qZWN0cy93ZWJzaXRlcy9ib3JlZGdhbWUvdml0ZS5jb25maWcudHNcIjsvLyBpbXBvcnQgeyBzZW50cnlTdmVsdGVLaXQgfSBmcm9tIFwiQHNlbnRyeS9zdmVsdGVraXRcIjtcbmltcG9ydCB7IHN2ZWx0ZWtpdCB9IGZyb20gJ0BzdmVsdGVqcy9raXQvdml0ZSc7XG5pbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tICd2aXRlJztcblxuLy8gVE9ETzogRml4IFNlbnRyeVxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcblx0cGx1Z2luczogW1xuXHRcdC8vIHNlbnRyeVN2ZWx0ZUtpdCh7XG5cdFx0Ly8gXHRzb3VyY2VNYXBzVXBsb2FkT3B0aW9uczoge1xuXHRcdC8vIFx0XHRvcmc6IHByb2Nlc3MuZW52LlNFTlRSWV9PUkcsXG5cdFx0Ly8gXHRcdHByb2plY3Q6IHByb2Nlc3MuZW52LlNFTlRSWV9QUk9KRUNULFxuXHRcdC8vIFx0XHRhdXRoVG9rZW46IHByb2Nlc3MuZW52LlNFTlRSWV9BVVRIX1RPS0VOLFxuXHRcdC8vIFx0XHRjbGVhbkFydGlmYWN0czogdHJ1ZSxcblx0XHQvLyBcdH1cblx0XHQvLyB9KSxcblx0XHRzdmVsdGVraXQoKVxuXHRdLFxuXHR0ZXN0OiB7XG5cdFx0aW5jbHVkZTogWydzcmMvKiovKi57dGVzdCxzcGVjfS57anMsdHN9J11cblx0fSxcblx0ZGVmaW5lOiB7XG5cdFx0U1VQRVJGT1JNU19MRUdBQ1k6IHRydWVcblx0fSxcblx0Y3NzOiB7XG5cdFx0ZGV2U291cmNlbWFwOiB0cnVlLFxuXHRcdHByZXByb2Nlc3Nvck9wdGlvbnM6IHtcblx0XHRcdHBvc3Rjc3M6IHtcblx0XHRcdFx0YWRkaXRpb25hbERhdGE6IGBcblx0XHRcdFx0QGN1c3RvbS1tZWRpYSAtLWJlbG93X3NtYWxsICh3aWR0aCA8IDQwMHB4KTtcblx0XHRcdFx0QGN1c3RvbS1tZWRpYSAtLWJlbG93X21lZCAod2lkdGggPCA3MDBweCk7XG5cdFx0XHRcdEBjdXN0b20tbWVkaWEgLS1iZWxvd19sYXJnZSAod2lkdGggPCA5MDBweCk7XG5cdFx0XHRcdEBjdXN0b20tbWVkaWEgLS1iZWxvd194bGFyZ2UgKHdpZHRoIDwgMTIwMHB4KTtcblxuXHRcdFx0XHRAY3VzdG9tLW1lZGlhIC0tYWJvdmVfc21hbGwgKHdpZHRoID4gNDAwcHgpO1xuXHRcdFx0XHRAY3VzdG9tLW1lZGlhIC0tYWJvdmVfbWVkICh3aWR0aCA+IDcwMHB4KTtcblx0XHRcdFx0QGN1c3RvbS1tZWRpYSAtLWFib3ZlX2xhcmdlICh3aWR0aCA+IDkwMHB4KTtcblx0XHRcdFx0QGN1c3RvbS1tZWRpYSAtLWFib3ZlX3hsYXJnZSAod2lkdGggPiAxMjAwcHgpO1xuXHRcdFx0XHRgXG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQ0EsU0FBUyxpQkFBaUI7QUFDMUIsU0FBUyxvQkFBb0I7QUFHN0IsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDM0IsU0FBUztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQVNSLFVBQVU7QUFBQSxFQUNYO0FBQUEsRUFDQSxNQUFNO0FBQUEsSUFDTCxTQUFTLENBQUMsOEJBQThCO0FBQUEsRUFDekM7QUFBQSxFQUNBLFFBQVE7QUFBQSxJQUNQLG1CQUFtQjtBQUFBLEVBQ3BCO0FBQUEsRUFDQSxLQUFLO0FBQUEsSUFDSixjQUFjO0FBQUEsSUFDZCxxQkFBcUI7QUFBQSxNQUNwQixTQUFTO0FBQUEsUUFDUixnQkFBZ0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BV2pCO0FBQUEsSUFDRDtBQUFBLEVBQ0Q7QUFDRCxDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=