Repository navigation
Add groups, roles and permissions management - #130
brionmario wants to merge 10 commits into
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔀 Cross-SDK feature parityDoes this change need to ship in the other ThunderID SDKs too? This check stays red until one of these labels answers that:
Ports (DO NOT EDIT)
No sibling SDKs accounted for on this thread yet. Important Reply to this comment with this block, filled in. The boxes above tick A link can be a pull request or a tracked issue, written in full or as The contract is in the SDK development specification. |
Add group and role management to every package: list, get, create, update and delete groups and roles, group members and role assignments, plus agent groups, agent roles, agent types, user groups and user types. The new resources resolve through endpoints.groups, endpoints.roles and endpoints.agentTypes, alongside the existing management collections. Add getTokenPermissions() and hasPermission(), which read the permissions an access token grants and match them the way the server does, and useGrantedPermissions() in React, Vue and Next.js. Add admin presentation components for users, groups, roles and agents (list, create, details, members, permissions and assignments, each with a Base variant), a DataTable primitive and an Attribution component to React, Vue and Next.js, and admin routes to react-router and tanstack-router. On the server, add management() to the Node client and managementFromRequest() to Express, which bind management operations to a session without exposing its token. Next.js relays management calls through server actions and Nuxt through a /api/auth/management route, so the browser never calls the management API directly. Move createResourceInvalidator into @thunderid/javascript and translate the new admin strings in every locale. Signed-off-by: Brion <info@brionmario.com>
Every playground now covers the new management APIs: capability checks for groups, roles, role assignments, group members, agent and user types and granted permissions, explorer stories for the admin components, DataTable and Attribution with sample data and live variants, hooks and composables views, and a card showing where each management collection resolves. Each playground reads THUNDERID_ENDPOINT_<KEY>, which overrides one management collection's URL, with the framework prefix where one applies. The Express, Node, Next.js and Nuxt playgrounds also show management calls going through the server. The SDK gaps the playgrounds hit are listed in each README. Signed-off-by: Brion <info@brionmario.com>
5bb8d0d to
51f46d4
Compare
Every admin component in React and Vue can now hand its UI to the application, the same way SignIn does. In React each Base and connected component takes a children render function; in Vue, the default scoped slot. The function receives the component's data, loading and error state, and handlers: a list gets its rows, the default columns, limit, offset, totalResults, onPageChange and onSelect, so a third-party data grid can take over with server-side paging; a create form gets its values, handleInputChange, handleSubmit, isValid and isSubmitting; details, members, assignments and permissions get the record and the actions that are allowed. Connected components pass the slot or function through to their Base component, and Next.js re-exports the render props types. Signed-off-by: Brion <info@brionmario.com>
The React and Next.js explorers draw UserList as an MUI DataGrid with server-side paging, GroupCreate as an MUI form and UserDetails as an MUI card, all through the components' render props. The Vue and Nuxt explorers do the same with PrimeVue's DataTable, inputs and card through the default scoped slot. MUI and PrimeVue are playground dependencies only, and each playground README explains the pattern. Signed-off-by: Brion <info@brionmario.com>
Instead of a separate Custom rendering group, each admin component's stories now end with a Custom (MUI) story, and the source control gains a custom option. The story renders the Base component with sample data through its children render function: lists as an MUI DataGrid with server-side paging, create forms with MUI inputs, details and permissions as MUI cards, and group members and role assignments as a DataGrid with an MUI picker. The Code panel shows the render props version for each. Signed-off-by: Brion <info@brionmario.com>
The admin components' story lists now hold the sample-data stories and the Custom (MUI) story. The live connected components are still reachable through each component's source control. Signed-off-by: Brion <info@brionmario.com>
DataGrid sets each cell's line-height to the row height, which pushed the SDK's avatar and name cell out of place and clipped the avatar. Each cell the custom stories hand to the grid is now wrapped in a flex box that resets the line-height and centers the content. Signed-off-by: Brion <info@brionmario.com>
The management list endpoints accept a single exact-match filter on users (attribute eq "value") and on custom agent attributes, and an assignee type on role assignments; groups, roles and group members take no filter. The agents API now passes filter through, and a new equality filter helper builds the expression, trimming the value and rejecting blank values or invalid attribute names. UserList and AgentList show a search form that applies on submit: users by username or email, agents by name, configurable through searchAttributes and switchable with searchable. A fixed filter on UserList hides the form, since the server takes one expression. An empty page while searching says nothing matched. RoleAssignments shows an assignee type filter that narrows the request, switchable with filterable. The Base components take the search or type filter as props, and the render props carry them so a custom UI can draw its own search box or filter. Signed-off-by: Brion <info@brionmario.com>
The UserList and AgentList sample stories search their sample rows the way the server does, an exact match on the chosen attribute, and RoleAssignments narrows its sample assignments by type. The Custom (MUI) stories draw the search as MUI fields with a clearable chip, and the assignee type filter as MUI chips, from the render props. Signed-off-by: Brion <info@brionmario.com>
The React Select drew its arrow inside the right padding, which matched the left, so in a narrow select such as the admin search attribute picker the selected label ran under the arrow. The right padding now leaves room for it. Signed-off-by: Brion <info@brionmario.com>
Purpose
Adds group, role and permission management to the JavaScript SDKs.
Approach
endpoints.groups,endpoints.rolesandendpoints.agentTypesjoin the existing management keys. A collection URL resolves from the call'surl, thenendpoints.<key>, then{baseUrl}/{collection}.@thunderid/javascript:getTokenPermissions()andhasPermission(): read the permissions an access token grants and match them the way the server does (system:usercoverssystem:user:view).createResourceInvalidatormoves here from@thunderid/react.resolveManagedIdentityNameandtoManagementErrorMessageare new.@thunderid/reactand@thunderid/vue:useGrantedPermissions().Base*variant.UserListandAgentListsearch on the server (users by username or email, agents by name), andRoleAssignmentsfilters by assignee type. The server matches one attribute exactly, so the search applies on submit.getAgentsgainsfilter, andtoEqualityFilterbuilds the expression. Groups, roles and group members have no server filter, so they stay unfiltered.SignIn: achildrenfunction in React and the default scoped slot in Vue receive the data, loading and error state, and handlers, so the UI can come from any library. A list hands over its rows, defaultcolumns,limit,offset,totalResults,onPageChangeandonSelect, enough to drive a third-party data grid with server-side paging; a form hands overvalues,handleInputChange,handleSubmitandisValid.DataTableprimitive and anAttributioncomponent.@thunderid/nextjs: the admin components and hooks, with management calls relayed through server actions (managementRequestAction,getGrantedPermissionsAction), so the browser never calls the management API or holds the token.@thunderid/nuxt: amanagementmodule option that auto-imports the admin components and composables, and a/api/auth/managementroute that relays management calls.@thunderid/nodeand@thunderid/express:client.management(sessionId)andmanagementFromRequest(req)bind management operations to a session. The session's token stays on the server and is read on every call.@thunderid/react-routerand@thunderid/tanstack-router: admin routes (createAdminRoutes,AdminPage).Playgrounds
Every playground exercises the new APIs:
DataTableandAttributionstories with sample data and live variantsUserListas an MUI DataGrid,GroupCreateas an MUI form andUserDetailsas an MUI card in React and Next.js, and the same with PrimeVue in Vue and Nuxt (playground-only dependencies)They read
THUNDERID_ENDPOINT_<KEY>(withVITE_orNUXT_PUBLIC_where the framework needs it) to override one management collection's URL. The server playgrounds show management calls going through the server. The SDK gaps the playgrounds hit are listed in each README.Screenshots
From the React playground's component explorer, with sample data.
Admin components, including the server-side search and the assignee type filter:
Custom rendering through render props, drawn with MUI. Each admin component has a Custom (MUI) story; the Code tab shows the render function:
Vue, through the default scoped slot with PrimeVue:
Verified locally:
pnpm build(18/18) andpnpm testacross the packages (2,233 passed, 3 skipped).onPageChange.