mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 22:55:24 +00:00
fix: enforce unique usernames (#1628)
* fix: enforce unique usernames Registration checked for a taken name, hashed the password, then inserted, with nothing in the schema enforcing uniqueness. Concurrent sign-ups could create two accounts with one name, after which login, password reset, proxy login and admin lookups by username picked between them arbitrarily. Add a unique index on users.username for every dialect. Existing duplicates are renamed (later rows get a -<id> suffix, the oldest keeps the name) rather than deleted. Registration and admin user creation now return the same 409 when the insert loses the race. * fix: avoid username collisions during migration
This commit is contained in:
1 parent
3941dd4ecc
commit
e610aba0e5
19 files changed
+14354
-26
No files matched your search
@@ -0,0 +1,19 @@
|
||||
-- Choose an unused prefix from N + 1 disjoint prefixes for N existing users.
|
||||
WITH ranked AS (
|
||||
SELECT id, username,
|
||||
ROW_NUMBER() OVER (ORDER BY registered_at, id) AS sequence,
|
||||
ROW_NUMBER() OVER (PARTITION BY username ORDER BY registered_at, id) AS occurrence
|
||||
FROM users
|
||||
), candidates AS (
|
||||
SELECT 0 AS candidate UNION ALL SELECT sequence FROM ranked
|
||||
), available AS (
|
||||
SELECT MIN(candidate) AS candidate FROM candidates
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM ranked WHERE username LIKE CONCAT(CONCAT('termix-recovered-', candidate, '-'), '%')
|
||||
)
|
||||
)
|
||||
UPDATE users JOIN ranked ON ranked.id = users.id CROSS JOIN available
|
||||
SET users.username = CONCAT('termix-recovered-', available.candidate, '-', ranked.sequence)
|
||||
WHERE ranked.occurrence > 1;--> statement-breakpoint
|
||||
ALTER TABLE `users` MODIFY COLUMN `username` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `users` ADD CONSTRAINT `idx_users_username` UNIQUE(`username`);
|
||||
Reference in new issue
Block a user