mirror of
https://github.com/HeyPuter/puter.git
synced 2026-07-08 16:21:40 +00:00
fix: phone retry limit messagin (#3358)
This commit is contained in:
@@ -54,4 +54,38 @@ describe('UserStore', () => {
|
||||
expect(typeof cachedUser?.email_confirmed).toBe('boolean');
|
||||
expect(typeof cachedUser?.requires_email_confirmation).toBe('boolean');
|
||||
});
|
||||
|
||||
it('counts other accounts holding the same phone number', async () => {
|
||||
const phone = `+1415555${Math.floor(1000 + Math.random() * 9000)}`;
|
||||
const makeUser = async () => {
|
||||
const username = `up-${Math.random().toString(36).slice(2, 10)}`;
|
||||
const user = await server.stores.user.create({
|
||||
username,
|
||||
uuid: uuidv4(),
|
||||
password: null,
|
||||
email: `${username}@test.local`,
|
||||
});
|
||||
await server.stores.user.update(user.id, { phone });
|
||||
return user;
|
||||
};
|
||||
|
||||
const first = await makeUser();
|
||||
expect(
|
||||
await server.stores.user.countOthersByPhone(phone, first.id),
|
||||
).toBe(0);
|
||||
|
||||
const second = await makeUser();
|
||||
expect(
|
||||
await server.stores.user.countOthersByPhone(phone, first.id),
|
||||
).toBe(1);
|
||||
expect(
|
||||
await server.stores.user.countOthersByPhone(phone, second.id),
|
||||
).toBe(1);
|
||||
// A caller that isn't among the holders sees both.
|
||||
expect(await server.stores.user.countOthersByPhone(phone, -1)).toBe(2);
|
||||
// Unknown number counts zero.
|
||||
expect(
|
||||
await server.stores.user.countOthersByPhone('+19995550000', -1),
|
||||
).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -257,6 +257,29 @@ export class UserStore extends PuterStore {
|
||||
return this.getById(row.id as number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count accounts other than `excludeUserId` whose confirmed `phone`
|
||||
* equals this number. Backs the cap on live accounts per phone number
|
||||
* (the row is deleted with the account, so this only counts accounts
|
||||
* that still exist — recycling velocity is rate-limited separately by
|
||||
* the abuse policy's KV log).
|
||||
*
|
||||
* Not cached — like `getByCleanEmail`, callers use this for duplicate
|
||||
* detection at write time, which needs fresh reads.
|
||||
*/
|
||||
async countOthersByPhone(
|
||||
phone: string,
|
||||
excludeUserId: number,
|
||||
): Promise<number> {
|
||||
if (!phone) return 0;
|
||||
if (!isStorableAsLatin1(phone)) return 0;
|
||||
const rows = (await this.clients.db.tryHardRead(
|
||||
'SELECT COUNT(*) AS n FROM `user` WHERE `phone` = ? AND `id` != ?',
|
||||
[phone, excludeUserId],
|
||||
)) as Array<{ n: number | string }>;
|
||||
return Number(rows[0]?.n) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic property lookup. Fast-path reads redis first (cache is
|
||||
* multi-key — every identifying property points at the same serialized
|
||||
|
||||
@@ -44,6 +44,8 @@ import {
|
||||
const SEND_REASON_MESSAGES = {
|
||||
phone_already_used:
|
||||
'This phone number has already been used to verify the maximum number of accounts. Please use a different number, or email support@puter.com for help.',
|
||||
phone_verify_limit:
|
||||
'This phone number cannot be used to verify this account. Please use a different number, or email support@puter.com for help.',
|
||||
phone_send_limit:
|
||||
'This phone number has received too many verification codes recently. Please try again later, or use a different number.',
|
||||
phone_verify_attempts_exhausted:
|
||||
|
||||
Reference in New Issue
Block a user