fix(auth): stop the users limit card silently blocking Update - #3184
Merged
Conversation
The user-limit policy reserves `total: 0` for "no limit", but the card treated 0 as a value you could type. On a project with no limit, selecting Limited and entering 0 left `policy.total === newLimit`, so Update stayed disabled with nothing explaining why. The same check had three more holes: entering 0 on an already-limited project saved `total: 0` and silently turned the limit off while the UI still read "Limited 0"; clearing the field bound `undefined` and made the SDK throw `Missing required parameter: "total"`; and with no `min` on the input a negative value reached the API as a 400. Move the range and changed-vs-saved checks into usersLimit.ts, put min/max/step on the input, and surface a rejected value as an inline error instead of a dead button. 0 can no longer be submitted as a limit, so the card cannot drift out of sync with the saved policy. Also drop `maxUsersInputField` and its focus effect: nothing ever bound it, so it was always null and never ran. Wiring it up would have auto-focused and scrolled to the card on every page load.
Console (appwrite/console)Project ID: Tip Every Git commit and branch gets its own deployment URL automatically |
Contributor
Greptile SummaryThe PR prevents invalid user-limit values from silently disabling or misusing the Update action.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Reviews (2): Last reviewed commit: "test(auth): assert users limit button st..." | Re-trigger Greptile |
The button-state cases reimplemented the card's `btnDisabled` expression inside the test file, so they asserted against a copy of the logic. The guard could be dropped from the component and every test naming the reported bug would still pass. Fold the derivation into `usersLimitState()`, render the card from it, and drive the tests through it. Verified by mutation: dropping the error guard, dropping the limited-mode guard, and ignoring mode in the changed-check now fail 1, 1 and 2 cases; against the old tests all three passed clean.
ChiragAgg5k
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What
Auth > Security > Users limitleaves Update disabled with nothing explaining why whenever the entered value is one the API cannot accept.Reported on Discord: on a project with no limit, selecting Limited and entering
0does nothing — the button never enables, so the change cannot be saved.Why
The user-limit policy reserves
total: 0for "no limit" — from the SDK: "Value can be between 0 and 10000. Use 0 or null to disable the limit." The card let you type0as though it were a limit, and the disabled check conflated the two states:With
policy.total === 0andnewLimit === 0, that is0 === 0— Update disabled. The button looks broken; it is actually refusing a state the API cannot represent, without saying so.The same check had three more holes:
0, project already limited to 100total: 0, silently turning the limit off while the UI still read "Limited 0"undefined→ Update enabled → SDK throwsMissing required parameter: "total"as an error toastminon the input → Update enabled → 400 from the APIChanges
usersLimit.ts.min/max/stepon the input.0can no longer be submitted as a limit, so the card cannot drift out of sync with the saved policy.maxUsersInputFieldand its focus effect — nothing ever bound it, so it was alwaysnulland never ran. Wiring it up would have auto-focused and scrolled to the card on every page load.Tests
usersLimit.test.tscovers the reported repro, the silent0-saves-as-unlimited path, cleared / decimal / out-of-range input, and the valid transitions. Colocated plain-vitest, same pattern asrows/store.test.ts— no jsdom or component-test scaffolding needed.format,check(0 errors),lint(0 errors),test:unit(275 passed) andbuildare clean.Note for the original question
Setting the users limit to
0to block client-side signups cannot work by design —0disables the policy. Verified against the server:APP_LIMIT_USERS = 10_000(app/init/constants.php), matching the range this card now enforces.app/controllers/api/account.phponly — six call sites covering email/password, magic URL, OAuth, phone and anonymous, so "regardless of authentication method" holds for the client Account API.Platform/Modules/Users/Http/Users/Create.phphas no such check, so an API key can still create users past the limit.So the workaround suggested in the thread does hold: set the limit to
1, create one user yourself, and an Appwrite Function using an API key keeps creating users through the Users API while client-side signup returnsuser_count_exceeded.