Merge IAM policy hierarchy#1113
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
| return ( | ||
| <Badge color={effectiveRole === cellRole ? 'default' : 'neutral'}>{cellRole}</Badge> | ||
| ) | ||
| } |
There was a problem hiding this comment.
This is all kind of ridiculous, but it lets us do the latter instead of something like the the former:
-cell: (info) => <RoleBadge effectiveRole={info.row.original.effectiveRole} role={info.getValue()} />
+cell: RoleBadgee6a713f to
22d37b1
Compare
| (row) => row.id | ||
| ), | ||
| [siloRows, orgRows] | ||
| ) |
There was a problem hiding this comment.
this logic is almost identical between org and project — however the shared row processing logic I had before was kind of terrible, so I can't bring myself to extract this.
| cell: (info) => <Badge color="neutral">{info.getValue()}</Badge>, | ||
| colHelper.accessor('siloRole', { | ||
| header: 'Silo role', | ||
| cell: RoleBadgeCell, |
There was a problem hiding this comment.
in addition to being very clean, this actually enforces that the row type has effectiveRole on it, which is pretty cool
| name: string | ||
| siloRole: SiloRole | undefined | ||
| orgRole: OrganizationRole | undefined | ||
| projectRole: ProjectRole | undefined |
There was a problem hiding this comment.
Strictly speaking there should always be at least one of the three roles. I considered using type-fest's RequireAtLeastOne to represent that, but meh. The reason not to is there's nothing in the code that depends on it, because the cells are only looking at their own value, not the whole set.
There was a problem hiding this comment.
I think it's fine. In the case where at least one role is provided that sounds like an error case we'd need to handle at runtime anyway.
| await expectRowVisible(table, { | ||
| ID: 'user-1', | ||
| Name: 'Hannah Arendt', | ||
| 'Silo role': 'admin', | ||
| 'Org role': '', | ||
| }) | ||
| await expectRowVisible(table, { | ||
| ID: 'user-2', | ||
| Name: 'Hans Jonas', | ||
| 'Silo role': '', | ||
| 'Org role': 'viewer', | ||
| }) |
There was a problem hiding this comment.
These really are so much better, ha
| import type { OrganizationRole, ProjectRole, SiloRole } from '@oxide/api' | ||
| import { Badge } from '@oxide/ui' | ||
|
|
||
| // I think there are changes in RT 8.4+ that make this less ridiculous |
| export const getOrgRole = getMainRole(orgRoleOrder) | ||
| export const getEffectiveOrgRole = ( | ||
| roles: OrganizationRole[] | ||
| ): OrganizationRole | undefined => sortBy(roles, (role) => orgRoleOrder[role])[0] |
There was a problem hiding this comment.
the changes from here up are just cleanup and renaming. I didn't like this stuff, now I feel slightly better about it
| // wouldn't be a group | ||
| roleName: getMainRole(roleOrder)(groupRoleAssignments.map((ra) => ra.roleName))!, | ||
| })) | ||
| }, [policy, usersDict, roleOrder]) |
There was a problem hiding this comment.
The main change is that we are no longer doing a groupBy here — we're doing it in the calling code instead, in the project and org access pages. useUserRows is much easier to understand now: it takes a list of role assignments and adds some info to each one with a simple map.
|
Are there any other changes pending before this PR can be merged? I know there was some discussion around design improvements, but I wasn't sure if that was in scope with this PR. |
|
Nope, this is complete. I will follow up with a look at groups, but I don’t think there is currently a way to fetch a group or a list of groups from the API, so that work will probably have to wait a week or two. |
| if (!cellRole) return null | ||
| const effectiveRole = info.row.original.effectiveRole | ||
| return ( | ||
| <Badge color={effectiveRole === cellRole ? 'default' : 'neutral'}>{cellRole}</Badge> |
There was a problem hiding this comment.
Visually secondary might be a better fit here. It definitely can wait until a design pass though.
There was a problem hiding this comment.
This might not be the right place for it, but having tooltips on the non-effective roles would be good.
There was a problem hiding this comment.
Yeah, definitely. Eugene and Ben are thinking about all that.
| apiQueryClient.prefetchQuery('policyView', {}), | ||
| apiQueryClient.prefetchQuery('organizationPolicyView', requireOrgParams(params)), |
There was a problem hiding this comment.
When you demo this, it'd be good to call out that pagination would be a challenge. As I'm thinking about this, it almost seems like these endpoints should more be policyList and organizationPolicyList with /policy/<user-id> being a valid lookup. If we did that then we could just use policy list and do a lookup (or future batch lookup) for the related endpoints. Or it's just PolicyView with a filter? Either way..
Again, nothing to do in this PR.
| const orgRows = useUserRows(orgPolicy?.roleAssignments, 'org') | ||
| const siloRows = useUserRows(siloPolicy?.roleAssignments, 'silo') | ||
| const rows = useMemo(() => { | ||
| const users = groupBy(siloRows.concat(orgRows), (u) => u.id).map(([id, ras]) => { |
There was a problem hiding this comment.
What is ras short for? Role assignments?
There was a problem hiding this comment.
yeah. it sucks, I'll fix it and then merge
just-be-dev
left a comment
There was a problem hiding this comment.
Whew, tough little piece of work. Good job though, I think this'll really be helpful in visualizing some of the challenges around our IAM model.
Good to merge when you're ready 👍
Closes #1024
This doesn't feel good exactly but it conveys the information that's currently available and will let us get a feel for the strengths and weakness of the approach so far. I will add some notes on the experience once it's completely ready.
What's in here
/policyfor current silo,/global/policyfor fleet omicron#1573 for/policyendpoint to get current silo policyFollowup work