Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditionally render silo creation fields, depending on identity mode #2332

Merged
merged 10 commits into from
Jul 24, 2024

Conversation

charliepark
Copy link
Contributor

Fixes #2325

The issue above noted that when creating a "local only" silo (API docs here), the admin group name wasn't relevant, so we should only show it during silo creation when the identity mode is saml_jit. Looking into Omicron a bit, it turns out that the admin group name is, in turn, necessary in order to assign fleet roles. Here's that code:
https://github.com/oxidecomputer/omicron/blob/89b998c1c24e26b9e1161acbbd1b236f40470bdd/nexus/db-queries/src/db/datastore/silo.rs#L205-L227

This PR sets the silo creation form to conditionally render the admin group name and the "assign fleet role" checkboxes. It also adds logic to make sure that if the name is deleted that the checkboxes are cleared, and that if the identity mode is switched to "local", that the admin group name is cleared.

Some screenshots, to illustrate the above:

  1. Here's the form in its natural state:
Screenshot 2024-07-17 at 5 54 25 PM
  1. We've entered some data:
Screenshot 2024-07-17 at 5 54 41 PM
  1. Oh, wait, let's make this one local only:
Screenshot 2024-07-17 at 5 55 01 PM
  1. And a quick check to verify that the fields cleared:
Screenshot 2024-07-17 at 5 55 12 PM

Copy link

vercel bot commented Jul 17, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
console ✅ Ready (Inspect) Visit Preview Jul 24, 2024 8:21pm

form.setValue('siloAdminGetsFleetAdmin', false)
form.setValue('siloViewerGetsFleetViewer', false)
}
}, [fleetRolesDisabled, form])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried doing this stuff in onChange on identity mode and admin group name instead, which is vaguely to be preferred over useEffect when you can make it work, because cuts out a render or two that have to happen while each of the state values update in turn and the useEffects fire. But it didn't really work out.

The result was a bit sad in that a) I lost the ability to clear the checkboxes when the group name clears (because setValue doesn't trigger onChange), and b) it requires a change to how we handle onChange in the text field and radio field that I am very unsure about. I had to make so when you pass in onChange, it runs in addition to the field one instead of overriding it. There's a good chance we are relying on that overriding behavior, plus it would be weird to have some fields work this way and others not. I'm sure the watch and useEffect version won't cause perf problems anyway, plus it's clearer because the related logic is all together.

failed experiment diff
diff --git a/app/components/form/fields/RadioField.tsx b/app/components/form/fields/RadioField.tsx
index 1fdc9c50..f2f7ece3 100644
--- a/app/components/form/fields/RadioField.tsx
+++ b/app/components/form/fields/RadioField.tsx
@@ -71,6 +71,7 @@ export function RadioField<
   control,
   items,
   parseValue,
+  onChange,
   ...props
 }: RadioFieldProps<TFieldValues, TName>) {
   const id = useId()
@@ -92,9 +93,11 @@ export function RadioField<
           [`${id}-help-text`]: !!tooltipText,
         })}
         aria-describedby={tooltipText ? `${id}-label-tip` : undefined}
-        onChange={(e) =>
-          parseValue ? field.onChange(parseValue(e.target.value)) : field.onChange(e)
-        }
+        onChange={(e) => {
+          // if onChange is passed in, call it in addition to field one, not instead of it
+          onChange?.(e)
+          return parseValue ? field.onChange(parseValue(e.target.value)) : field.onChange(e)
+        }}
         name={field.name}
         {...props}
         // TODO: once we get rid of the other use of RadioGroup, change RadioGroup
diff --git a/app/components/form/fields/TextField.tsx b/app/components/form/fields/TextField.tsx
index 6662fa07..5dff4aac 100644
--- a/app/components/form/fields/TextField.tsx
+++ b/app/components/form/fields/TextField.tsx
@@ -114,12 +114,13 @@ export const TextFieldInner = <
   required,
   id: idProp,
   transform,
+  onChange,
   ...props
 }: TextFieldProps<TFieldValues, TName> & UITextAreaProps) => {
   const generatedId = useId()
   const id = idProp || generatedId
   const {
-    field: { onChange, ...fieldRest },
+    field: { onChange: fieldOnChange, ...fieldRest },
     fieldState: { error },
   } = useController({ name, control, rules: { required, validate } })
   return (
@@ -131,7 +132,10 @@ export const TextFieldInner = <
         error={!!error}
         aria-labelledby={cn(`${id}-label`, !!tooltipText && `${id}-help-text`)}
         aria-describedby={tooltipText ? `${id}-label-tip` : undefined}
-        onChange={(e) => onChange(transform ? transform(e.target.value) : e.target.value)}
+        onChange={(e) => {
+          onChange?.(e)
+          return fieldOnChange(transform ? transform(e.target.value) : e.target.value)
+        }}
         {...fieldRest}
         {...props}
       />
diff --git a/app/forms/silo-create.tsx b/app/forms/silo-create.tsx
index a677b2a7..5b73cae0 100644
--- a/app/forms/silo-create.tsx
+++ b/app/forms/silo-create.tsx
@@ -68,20 +68,8 @@ export function CreateSiloSideModalForm() {
   const form = useForm({ defaultValues })
   const identityMode = form.watch('identityMode')
   const adminGroupName = form.watch('adminGroupName')
-  // Clear the adminGroupName if the user selects the "local only" identity mode
-  useEffect(() => {
-    if (identityMode === 'local_only') {
-      form.setValue('adminGroupName', '')
-    }
-  }, [identityMode, form])
-  // Clear the role assignment checkboxes if the adminGroupName is deleted
   const fleetRolesDisabled = !adminGroupName
-  useEffect(() => {
-    if (fleetRolesDisabled) {
-      form.setValue('siloAdminGetsFleetAdmin', false)
-      form.setValue('siloViewerGetsFleetViewer', false)
-    }
-  }, [fleetRolesDisabled, form])
+
   return (
     <SideModalForm
       form={form}
@@ -160,6 +148,14 @@ export function CreateSiloSideModalForm() {
           { value: 'saml_jit', label: 'SAML' },
           { value: 'local_only', label: 'Local only' },
         ]}
+        onChange={(e) => {
+          // Clear SAML-specific fields when user selects "local only"
+          if (e.target.value === 'local_only') {
+            form.setValue('adminGroupName', '')
+            form.setValue('siloAdminGetsFleetAdmin', false)
+            form.setValue('siloViewerGetsFleetViewer', false)
+          }
+        }}
       />
       {identityMode === 'saml_jit' && (
         <>

@david-crespo
Copy link
Collaborator

david-crespo commented Jul 24, 2024

TL;DR: only the admin group name is conditional. Checkboxes are always relevant.


After taking another look at the backend code where we determined that we should hide the fleet role checkboxes if the user is making a local silo, I think we read it wrong. That code only concerns what is done with the admin group name. There is a reference to policy.role_assignments which I think we misread as concerning the checkbox values, but those are in mapped_fleet_roles, and that gets passed straight through to the DB record for the silo regardless of the presence of the admin group name.

This makes sense, because the fleet role mapping doesn't have anything to do with the admin group per se. It just says: if a user is an admin/viewer in this silo, make them an admin/viewer on the fleet. Where the user got that admin role from, whether, e.g., by direct assignment or by being in a designated admin group, is irrelevant. The Polar code uses a custom Rust function to look at the actor's roles on the silo and the fleet role mapping and decides whether they also have a role on the fleet.

@charliepark
Copy link
Contributor Author

After a few tweaks to general layout:
Screenshot 2024-07-24 at 3 03 20 PM
Screenshot 2024-07-24 at 3 03 26 PM

@david-crespo david-crespo enabled auto-merge (squash) July 24, 2024 20:21
@david-crespo david-crespo merged commit f278a74 into main Jul 24, 2024
8 checks passed
@david-crespo david-crespo deleted the sometimes-hide-admin-group-name branch July 24, 2024 20:30
david-crespo added a commit to oxidecomputer/omicron that referenced this pull request Aug 14, 2024
oxidecomputer/console@17ae890...29398e7

* [29398e74](oxidecomputer/console@29398e74) oxidecomputer/console#2343
* [68e2dc89](oxidecomputer/console@68e2dc89) oxidecomputer/console#2359
* [11e29ed8](oxidecomputer/console@11e29ed8) bump omicron to latest main
* [b6ed3757](oxidecomputer/console@b6ed3757) oxidecomputer/console#2370
* [af6c1f4a](oxidecomputer/console@af6c1f4a) oxidecomputer/console#2368
* [60ef745c](oxidecomputer/console@60ef745c) disallow unreachable code in ts config, fix one case of it
* [3a6f815a](oxidecomputer/console@3a6f815a) oxidecomputer/console#2364
* [80b3f2f3](oxidecomputer/console@80b3f2f3) oxidecomputer/console#2366
* [dab60d9d](oxidecomputer/console@dab60d9d) oxidecomputer/console#2358
* [8e3314f1](oxidecomputer/console@8e3314f1) oxidecomputer/console#2362
* [9b5cdfa0](oxidecomputer/console@9b5cdfa0) bump TS generator for bugfix (just adds whitespace)
* [07b6c151](oxidecomputer/console@07b6c151) oxidecomputer/console#2349
* [d32fddc2](oxidecomputer/console@d32fddc2) Revert "Focus confirm button instead of cancel in modals (oxidecomputer/console#2340)"
* [84a1501e](oxidecomputer/console@84a1501e) oxidecomputer/console#2341
* [6615cb6b](oxidecomputer/console@6615cb6b) oxidecomputer/console#2340
* [e48b0096](oxidecomputer/console@e48b0096) delete unused vscode tasks
* [22a6c50f](oxidecomputer/console@22a6c50f) tighten TypeValueCell spacing
* [4eacb3d7](oxidecomputer/console@4eacb3d7) oxidecomputer/console#2338
* [f278a747](oxidecomputer/console@f278a747) oxidecomputer/console#2332
* [016ad1b4](oxidecomputer/console@016ad1b4) oxidecomputer/console#2337
* [2d1a22a2](oxidecomputer/console@2d1a22a2) oxidecomputer/console#2336
* [be0f087f](oxidecomputer/console@be0f087f) oxidecomputer/console#2329
david-crespo added a commit to oxidecomputer/omicron that referenced this pull request Aug 16, 2024
oxidecomputer/console@17ae890...33b7a50

* [33b7a505](oxidecomputer/console@33b7a505) oxidecomputer/console#2360
* [1a2cb52d](oxidecomputer/console@1a2cb52d) oxidecomputer/console#2369
* [9e831174](oxidecomputer/console@9e831174) oxidecomputer/console#2374
* [e30f2eb8](oxidecomputer/console@e30f2eb8) oxidecomputer/console#2373
* [bb53f1b2](oxidecomputer/console@bb53f1b2) oxidecomputer/console#2371
* [29398e74](oxidecomputer/console@29398e74) oxidecomputer/console#2343
* [68e2dc89](oxidecomputer/console@68e2dc89) oxidecomputer/console#2359
* [11e29ed8](oxidecomputer/console@11e29ed8) bump omicron to latest main
* [b6ed3757](oxidecomputer/console@b6ed3757) oxidecomputer/console#2370
* [af6c1f4a](oxidecomputer/console@af6c1f4a) oxidecomputer/console#2368
* [60ef745c](oxidecomputer/console@60ef745c) disallow unreachable code in ts config, fix one case of it
* [3a6f815a](oxidecomputer/console@3a6f815a) oxidecomputer/console#2364
* [80b3f2f3](oxidecomputer/console@80b3f2f3) oxidecomputer/console#2366
* [dab60d9d](oxidecomputer/console@dab60d9d) oxidecomputer/console#2358
* [8e3314f1](oxidecomputer/console@8e3314f1) oxidecomputer/console#2362
* [9b5cdfa0](oxidecomputer/console@9b5cdfa0) bump TS generator for bugfix (just adds whitespace)
* [07b6c151](oxidecomputer/console@07b6c151) oxidecomputer/console#2349
* [d32fddc2](oxidecomputer/console@d32fddc2) Revert "Focus confirm button instead of cancel in modals (oxidecomputer/console#2340)"
* [84a1501e](oxidecomputer/console@84a1501e) oxidecomputer/console#2341
* [6615cb6b](oxidecomputer/console@6615cb6b) oxidecomputer/console#2340
* [e48b0096](oxidecomputer/console@e48b0096) delete unused vscode tasks
* [22a6c50f](oxidecomputer/console@22a6c50f) tighten TypeValueCell spacing
* [4eacb3d7](oxidecomputer/console@4eacb3d7) oxidecomputer/console#2338
* [f278a747](oxidecomputer/console@f278a747) oxidecomputer/console#2332
* [016ad1b4](oxidecomputer/console@016ad1b4) oxidecomputer/console#2337
* [2d1a22a2](oxidecomputer/console@2d1a22a2) oxidecomputer/console#2336
* [be0f087f](oxidecomputer/console@be0f087f) oxidecomputer/console#2329
david-crespo added a commit to oxidecomputer/omicron that referenced this pull request Aug 16, 2024
#6366)

oxidecomputer/console@17ae890...33b7a50

* [33b7a505](oxidecomputer/console@33b7a505)
oxidecomputer/console#2360
* [1a2cb52d](oxidecomputer/console@1a2cb52d)
oxidecomputer/console#2369
* [9e831174](oxidecomputer/console@9e831174)
oxidecomputer/console#2374
* [e30f2eb8](oxidecomputer/console@e30f2eb8)
oxidecomputer/console#2373
* [bb53f1b2](oxidecomputer/console@bb53f1b2)
oxidecomputer/console#2371
* [29398e74](oxidecomputer/console@29398e74)
oxidecomputer/console#2343
* [68e2dc89](oxidecomputer/console@68e2dc89)
oxidecomputer/console#2359
* [11e29ed8](oxidecomputer/console@11e29ed8)
bump omicron to latest main
* [b6ed3757](oxidecomputer/console@b6ed3757)
oxidecomputer/console#2370
* [af6c1f4a](oxidecomputer/console@af6c1f4a)
oxidecomputer/console#2368
* [60ef745c](oxidecomputer/console@60ef745c)
disallow unreachable code in ts config, fix one case of it
* [3a6f815a](oxidecomputer/console@3a6f815a)
oxidecomputer/console#2364
* [80b3f2f3](oxidecomputer/console@80b3f2f3)
oxidecomputer/console#2366
* [dab60d9d](oxidecomputer/console@dab60d9d)
oxidecomputer/console#2358
* [8e3314f1](oxidecomputer/console@8e3314f1)
oxidecomputer/console#2362
* [9b5cdfa0](oxidecomputer/console@9b5cdfa0)
bump TS generator for bugfix (just adds whitespace)
* [07b6c151](oxidecomputer/console@07b6c151)
oxidecomputer/console#2349
* [d32fddc2](oxidecomputer/console@d32fddc2)
Revert "Focus confirm button instead of cancel in modals
(oxidecomputer/console#2340)"
* [84a1501e](oxidecomputer/console@84a1501e)
oxidecomputer/console#2341
* [6615cb6b](oxidecomputer/console@6615cb6b)
oxidecomputer/console#2340
* [e48b0096](oxidecomputer/console@e48b0096)
delete unused vscode tasks
* [22a6c50f](oxidecomputer/console@22a6c50f)
tighten TypeValueCell spacing
* [4eacb3d7](oxidecomputer/console@4eacb3d7)
oxidecomputer/console#2338
* [f278a747](oxidecomputer/console@f278a747)
oxidecomputer/console#2332
* [016ad1b4](oxidecomputer/console@016ad1b4)
oxidecomputer/console#2337
* [2d1a22a2](oxidecomputer/console@2d1a22a2)
oxidecomputer/console#2336
* [be0f087f](oxidecomputer/console@be0f087f)
oxidecomputer/console#2329
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Silo create: hide inapplicable fields when making local silo
2 participants