diff --git a/package-lock.json b/package-lock.json index 9d1117a5e..ed65668b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1516,18 +1516,6 @@ "sisteransi": "^1.0.5" } }, - "node_modules/@clack/prompts/node_modules/is-unicode-supported": { - "version": "1.3.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@cloudflare/kv-asset-handler": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", diff --git a/src/backend/clients/database/SqliteDatabaseClient.ts b/src/backend/clients/database/SqliteDatabaseClient.ts index d6108b447..753351a0e 100644 --- a/src/backend/clients/database/SqliteDatabaseClient.ts +++ b/src/backend/clients/database/SqliteDatabaseClient.ts @@ -88,6 +88,8 @@ const AVAILABLE_MIGRATIONS: [number, string[]][] = [ [52, ['0057_add_user_reputation.sql']], [53, ['0058_add_phone_verification.sql']], [54, ['0059_add_card_verification.sql']], + [55, ['0060_add_card_fingerprint.sql']], + [56, ['0061_add_suspended_at.sql']], ]; export class SqliteDatabaseClient extends AbstractDatabaseClient { diff --git a/src/backend/clients/database/migrations/mysql/mysql_mig_16.sql b/src/backend/clients/database/migrations/mysql/mysql_mig_16.sql new file mode 100644 index 000000000..6ef9d8261 --- /dev/null +++ b/src/backend/clients/database/migrations/mysql/mysql_mig_16.sql @@ -0,0 +1,46 @@ +-- Copyright (C) 2024-present Puter Technologies Inc. +-- +-- This file is part of Puter. +-- +-- Puter is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero General Public License as published +-- by the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +-- Suspended-at column. Mirrors SQLite migration 0061. `suspended_at` is when +-- the account was suspended, as unix seconds (NULL while not suspended) — the +-- timestamp sibling of the boolean `suspended` flag, indexed so the +-- signup-abuse harness can count an IP's recently-suspended accounts. +-- +-- Idempotent: the column add uses _puter_add_col (defined in mig_1, which +-- leaves it resident for later migrations); the index add is guarded against +-- INFORMATION_SCHEMA.STATISTICS so the directory replays safely. + +CALL _puter_add_col('user', 'suspended_at', '`suspended_at` bigint DEFAULT NULL'); + +DROP PROCEDURE IF EXISTS _puter_add_user_suspended_at_index; +DELIMITER // +CREATE PROCEDURE _puter_add_user_suspended_at_index() +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'user' + AND INDEX_NAME = 'idx_user_suspended_at' + ) THEN + ALTER TABLE `user` ADD INDEX `idx_user_suspended_at` (`suspended_at`); + END IF; +END// +DELIMITER ; + +CALL _puter_add_user_suspended_at_index(); + +DROP PROCEDURE IF EXISTS _puter_add_user_suspended_at_index; diff --git a/src/backend/clients/database/migrations/postgres/postgres_mig_5.sql b/src/backend/clients/database/migrations/postgres/postgres_mig_5.sql new file mode 100644 index 000000000..f5c5b4c4c --- /dev/null +++ b/src/backend/clients/database/migrations/postgres/postgres_mig_5.sql @@ -0,0 +1,25 @@ +-- Copyright (C) 2024-present Puter Technologies Inc. +-- +-- This file is part of Puter. +-- +-- Puter is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero General Public License as published +-- by the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +-- Suspended-at column. Mirrors SQLite migration 0061. `suspended_at` is when +-- the account was suspended, as unix seconds (NULL while not suspended) — the +-- timestamp sibling of the boolean `suspended` flag, indexed so the +-- signup-abuse harness can count an IP's recently-suspended accounts. +-- Idempotent via IF NOT EXISTS. + +ALTER TABLE "user" ADD COLUMN IF NOT EXISTS suspended_at bigint; +CREATE INDEX IF NOT EXISTS idx_user_suspended_at ON "user" (suspended_at); diff --git a/src/backend/clients/database/migrations/sqlite/0061_add_suspended_at.sql b/src/backend/clients/database/migrations/sqlite/0061_add_suspended_at.sql new file mode 100644 index 000000000..135bbfc2d --- /dev/null +++ b/src/backend/clients/database/migrations/sqlite/0061_add_suspended_at.sql @@ -0,0 +1,23 @@ +-- Copyright (C) 2024-present Puter Technologies Inc. +-- +-- This file is part of Puter. +-- +-- Puter is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero General Public License as published +-- by the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +-- When the account was suspended, as unix seconds; NULL while not suspended. +-- The timestamp sibling of the existing boolean `suspended` flag, stamped by +-- every suspension site. Indexed so the signup-abuse harness can count an IP's +-- recently-suspended accounts (see extensions/abuse/v2 suspendedAccountsByIp). +ALTER TABLE `user` ADD COLUMN `suspended_at` INTEGER DEFAULT NULL; +CREATE INDEX IF NOT EXISTS idx_user_suspended_at ON `user` (`suspended_at`); diff --git a/src/backend/stores/user/UserStore.ts b/src/backend/stores/user/UserStore.ts index 7e66760d5..535189996 100644 --- a/src/backend/stores/user/UserStore.ts +++ b/src/backend/stores/user/UserStore.ts @@ -37,6 +37,8 @@ export interface UserRow { email?: string | null; /** True when an admin has suspended the account. */ suspended?: boolean; + /** When the account was suspended, as unix seconds; null while not suspended. */ + suspended_at?: number | null; /** True when the user has confirmed the email currently on file. */ email_confirmed?: boolean; /** True for accounts that must confirm email before taking most actions. */