Improve authentication recovery and mobile gameplay

This commit is contained in:
2026-10-07 11:10:29 +05:00
parent 233e4d57f0
commit ce26e6fdbc
22 changed files with 763 additions and 97 deletions

View File

@@ -36,13 +36,13 @@ export const authActionSchema = z.discriminatedUnion("action", [
})
.strict(),
z.object({ action: z.literal("recover"), email }).strict(),
z
.object({ action: z.literal("magic"), email, next: z.string().optional() })
.strict(),
]);
export const profileUpdateSchema = z
.object({ displayName: displayNameSchema })
.strict();
export const initialPasswordSchema = z
.object({ password: newPasswordSchema })
.strict();
export const passwordUpdateSchema = z
.object({
password: newPasswordSchema,

View File

@@ -540,6 +540,8 @@ export type Database = {
[_ in never]: never;
};
Functions: {
legacy_password_needed: { Args: { p_user: string }; Returns: boolean };
claim_legacy_password: { Args: { p_user: string }; Returns: boolean };
set_beta_badge: {
Args: { p_reviewer: string; p_enabled: boolean };
Returns: boolean;

View File

@@ -0,0 +1,28 @@
import { initialPasswordSchema } from "./account";
export function generateInitialPassword() {
const bytes = crypto.getRandomValues(new Uint8Array(24));
// Every byte contributes eight random bits, encoded as two hex characters.
return (
"Aa7!" +
Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("")
);
}
export async function issueInitialPassword(
userId: string,
password: string,
operations: {
claim: (id: string) => Promise<boolean>;
update: (id: string, password: string) => Promise<void>;
},
) {
initialPasswordSchema.parse({ password });
if (!(await operations.claim(userId)))
throw new Error(
"A password is already set or was already issued. Use password recovery if needed.",
);
// A claim is never released after an uncertain Auth response: the password
// may already have changed, so a retry must not overwrite it with a new one.
await operations.update(userId, password);
}

View File

@@ -587,5 +587,23 @@
"Hidden for all players": "Скрыт для всех игроков",
"Hide beta badge": "Скрыть значок BETA",
"Show beta badge": "Показать значок BETA",
"Setting saved. Open pages update within 30 seconds.": "Настройка сохранена. Открытые страницы обновятся в течение 30 секунд."
"Setting saved. Open pages update within 30 seconds.": "Настройка сохранена. Открытые страницы обновятся в течение 30 секунд.",
"Forgot your password?": "Забыл пароль?",
"Open guess map": "Открыть карту",
"Edit your guess": "Изменить метку",
"Your one-time password screen.": "Сохрани свой пароль.",
"Your account needs a password.": "Для аккаунта нужен пароль.",
"Save this password now. After you close this screen, it cannot be shown again. You can change it in account settings.": "Сохрани пароль сейчас. После закрытия этого окна его нельзя будет показать снова. Сменить пароль можно в настройках аккаунта.",
"You joined before passwords were required. Create a strong password for email-and-password login.": "Ты зарегистрировался, когда пароль ещё не требовался. Создай надёжный пароль для входа по почте и паролю.",
"Your new account password": "Твой новый пароль",
"Copy password": "Скопировать пароль",
"Copied": "Скопировано",
"I saved this password somewhere safe.": "Я сохранил пароль в надёжном месте.",
"Done — I saved it": "Готово — пароль сохранён",
"Creating password…": "Создаём пароль…",
"Create and show my password": "Создать и показать пароль",
"Not now": "Не сейчас",
"Select the password and copy it manually.": "Выдели пароль и скопируй его вручную.",
"A password is already set or was already issued. Use password recovery if needed.": "Пароль уже установлен или был выдан ранее. Если нужно, воспользуйся восстановлением пароля.",
"Password setup could not be confirmed. Use password recovery before signing out.": "Не удалось подтвердить установку пароля. Восстанови пароль перед выходом из аккаунта."
}