feat(permissions): support the member role in the permission picker - #3177
Conversation
…vable parsePermission only recognised user and team, so a member role fell through to the invalid branch: it rendered as a raw truncated string in the styling reserved for a deleted entity, and its hover card showed the missing-entity avatar — presenting a perfectly valid grant as broken. It also called onNotFound. Nothing passes that callback today, but d36135f wired it to auto-remove stale roles before row.svelte moved to runes turned the event into a prop and left the consumer behind. If that wiring is restored, member roles would be silently deleted from any resource a user merely opened. A membership can only be read through its team or its user, and the role string carries neither, so the ID stands in for a name. That is still an improvement on the raw role: the badge now reads Member and the hover card offers the membership ID to copy.
The member role has been in the API and the docs since 1.0, but neither console ever offered it — the only way to set one was to know the syntax and type it into the custom permission box. It keys on a membership ID, which nothing in the console surfaces, so the picker resolves it in two steps: find the user, then choose which of their team memberships to grant. It has to run in that direction — teams.listMemberships indexes only the membership ID and the user ID for search, so picking a team first would leave the member step with a search box that matches nothing. users.list indexes name, email and phone, so the first step behaves like the existing user picker.
Console (appwrite/console)Project ID: Tip Teams feature lets you group users with membership management and role permissions |
Greptile SummaryThe PR adds membership-role selection and display support to the permission editor, including user and membership lookup, pagination, loading states, and retryable failures.
Confidence Score: 4/5The PR is not yet safe to merge because a rejected membership request can update the wrong picker step after the operator navigates Back. The success path prevents stale membership data from being applied, but the rejection path lacks the same selected-user guard and can surface a membership failure as a user-list failure. Files Needing Attention: src/lib/components/permissions/member.svelte Important Files Changed
Prompt To Fix All With AI### Issue 1
src/lib/components/permissions/member.svelte:116-118
**Stale membership errors cross views**
When an operator returns to the user list while a membership request is pending and that request rejects, the rejection writes the shared `loadError` without checking the selected user, causing a stale notification and potentially displaying the membership failure as “Could not load users.”
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (3): Last reviewed commit: "fix(permissions): tell a failed membersh..." | Re-trigger Greptile |
| import { createEventDispatcher } from 'svelte'; | ||
| import Label from './label.svelte'; | ||
| import Custom from './custom.svelte'; | ||
| import Member from './member.svelte'; |
There was a problem hiding this comment.
Membership picker bypasses barrel exports
The new picker integration imports component implementations through relative file paths rather than the repository's required directory barrel exports, coupling the feature to internal filenames and bypassing the curated export surface. The same pattern appears in the new member.svelte imports.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/components/permissions/actions.svelte
Line: 5
Comment:
**Membership picker bypasses barrel exports**
The new picker integration imports component implementations through relative file paths rather than the repository's required directory barrel exports, coupling the feature to internal filenames and bypassing the curated export surface. The same pattern appears in the new `member.svelte` imports.
**Context Used:** AGENTS.md ([source](https://github.com/appwrite/console/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
…sponses Stepping back and choosing a second user, or typing another search term, leaves the earlier request in flight. Whichever resolves last was writing to the shared list, so one user's memberships could be listed under another user's name — and a row selected there would have granted the membership actually belonging to the first user. Requests now carry a sequence number and only the newest may write, with the membership step additionally confirming the selection has not moved on beneath it. A rejected request also skipped the assignment that cleared the spinner, leaving the picker loading forever with nothing said. Both requests now settle in a finally and surface the failure.
|
You're right on all three points. The imports in I won't carry that forward as a rule. |
… one A rejected request left the list undefined, which reads identically to a successful empty response, so the picker stated that the user belongs to no teams — and offered nothing to click, leaving Back and re-selecting the user as the only way to try again. The failure is now held separately from the list and rendered as its own state with a Retry, in both steps. In the user step it is checked ahead of the search branch, so a search that fails reports the failure rather than claiming the term matched nothing.
| if (requestId !== latestRequest) return; | ||
| loadError = error.message; | ||
| addNotification({ type: 'error', message: error.message }); |
There was a problem hiding this comment.
Stale membership errors cross views
When an operator returns to the user list while a membership request is pending and that request rejects, the rejection writes the shared loadError without checking the selected user, causing a stale notification and potentially displaying the membership failure as “Could not load users.”
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/components/permissions/member.svelte
Line: 116-118
Comment:
**Stale membership errors cross views**
When an operator returns to the user list while a membership request is pending and that request rejects, the rejection writes the shared `loadError` without checking the selected user, causing a stale notification and potentially displaying the membership failure as “Could not load users.”
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Role.member([MEMBERSHIP_ID])has been part of the permissions API since 1.0 and is documented, but the console has never offered it. This adds it, and fixes how existing member roles are displayed.