-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
UI Hide Secrets Sync from nav if not on license and/or no policy permissions #27262
UI Hide Secrets Sync from nav if not on license and/or no policy permissions #27262
Conversation
CI Results: |
@@ -43,7 +43,7 @@ export default class SyncActivationModal extends Component<Args> { | |||
.adapterFor('application') | |||
.ajax('/v1/sys/activation-flags/secrets-sync/activate', 'POST', { namespace }); | |||
// must refresh and not transition because transition does not refresh the model from within a namespace | |||
yield this.router.refresh(); | |||
yield this.router.refresh('vault.cluster'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can probably take this or leave it, but i tried explicitly passing in the parent route that we want refreshed here to see if it'd help us assert that the get activated features was successfully re-fetched. i tried this based on the docs i read here:
doing this works fine in the UI, and after adding a bunch of console.log
statements i can see even in the test output that _/activation-flags
is fetched after a POST, but i can't get the assertions working how i'd like. because we have these assertions that effectively test that the UI updates once the feature is activated i think we're safe skipping the extra assertions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The list here came from me scanning through the sync API. We should test lots of policies to make sure I've gotten all the options.
Build Results: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code here looks good! coupla small comments and then i'll circle back to this to do a thorough QA. nice job!
syncHandlers(this.server); | ||
await authPage.login(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a note for other code reviewers: Angel and i moved authPage.login
out of the top-level module and into these individual ones because fetchActivatedFeatures
is called at the vault.cluster
route, which happens before the user is authenticated. as a result auth.login
was executing and calling fetchActivatedFeatures
before our mirage overrides like those on lines 74-95 had the chance to intercept the request.
// the activate endpoint is located at a different path than sys/sync. | ||
// the expected UX experience: if the feature is not activated, regardless of permissions | ||
// the user should see the landing page and a banner that tells them to either have an admin activate the feature or activate it themselves |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very helpful comment! 👏
// Response could change between user sessions. | ||
// Fire off endpoint without checking if activated features are already set. | ||
if (this.version.isCommunity) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edge case question - if a customer downgrades from enterprise, are their activated flags preserved? (Not necessary for this PR, mostly just curious)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I've asked Robert this, and more or less no. I think because there's a conditional wrapping that endpoint which is checking for enterprise, so it would return nothing. That being said I haven't tested this workflow.
if (!isEnterprise) return false; | ||
if (isHvdManaged) return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are HVD clusters enterprise? ~ til ~ I was going to suggest rearranging this order, but disregard if HVD clusters are enterprise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they sure are 🙂
@@ -63,6 +63,10 @@ export default Route.extend(ModelBoundaryRoute, ClusterRoute, { | |||
'Cannot use VAULT_CLOUD_ADMIN_NAMESPACE flag with non-enterprise Vault version', | |||
!(managedRoot && this.version.isCommunity) | |||
); | |||
|
|||
// activatedFlags are called this high in routing to return a response used to show/hide Secrets sync on sidebar nav. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this comment!
@@ -86,4 +88,21 @@ export default class flagsService extends Service { | |||
this.secretsSyncActivatePath.get('canUpdate') !== false | |||
); | |||
} | |||
|
|||
get showSecretsSync() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain your reasoning for putting this getter here? Since it's compiling logic from flags, permissions and versions services for just secret sync, it feels a little arbitrary living in the flag service, which I understood to be just for returning info about cluster flags.
Though looking at the other getter here canActivateSecretsSync
it seems like this flags service is also sort of a secrets sync permissions service 😅
I realize we're limited on time for this PR, but want to suggest that a future improvement is maybe separating or clarifying concerns here. Perhaps that means having another service (auth service?) responsible for managing user state related logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noelle and I chatted about this. Because we're using it in more than one places, and the concept is to keep access to this route consistent in both clients and sidebar nav we opted to leave it in the service.
But yes agree, flags (similar to what has happened to version service) is growing past it's original scope.
await runCmd(`write sys/namespaces/admin -f`, false); | ||
await authPage.loginNs('admin'); | ||
await runCmd(`write sys/namespaces/foo -f`, false); | ||
await authPage.loginNs('admin/foo'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the full test suite passing locally? Typically with namespace tests we have to manually clear the auth form namespace query params otherwise they stick for subsequent (unrelated) test runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really struggling with replication and oidc tests running enterprise locally, but chunking it out between these two suites everything passes.
Also these tests were not changed/added just moved because we deleted things
@@ -84,31 +84,6 @@ module('Integration | Component | sidebar-nav-cluster', function (hooks) { | |||
}); | |||
}); | |||
|
|||
test('it should render badge for promotional links on community version', async function (assert) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a test that it renders the HVD plus
badge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It still does, just farther down https://github.com/hashicorp/vault/blob/main/ui/app/services/permissions.js#L254
ui/tests/unit/services/flags-test.js
Outdated
this.version.type = 'community'; | ||
|
||
this.server.get('sys/activation-flags', () => { | ||
assert.true(false, 'activation-flags is not called'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't want this called, could we have this endpoint throw an error? This can make it a little clearer that the assertion inside that mirage request should not actually be hit
vault/ui/tests/integration/components/dashboard/overview-test.js
Lines 105 to 108 in 1e8eefa
this.server.get( | |
'sys/internal/counters/activity', | |
() => new Error('uh oh! a request was made to sys/internal/counters/activity') | |
); |
this.server.get(
'sys/activation-flags',
() => new Error('uh oh! a request was made to sys/activation-flags, this should not happen for community versions')
);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👆 love that idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@noelledaley You gave it to me on one of my recent PRs! 🎉 😄
@@ -49,6 +49,12 @@ const API_PATHS = { | |||
settings: { | |||
customMessages: 'sys/config/ui/custom-messages', | |||
}, | |||
sync: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still learning out this service works...but do you know why just having
sync: 'sys/sync/',
which ends in a /
isn't sufficient here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope! 🙃 This is what I pinged Chelsea about in the dev channel. The logic of comparison is backwards from what you'd think they be comparing. I'll ping you on that thread which has links, etc. But it's also something that I can more easily clarify in standup.
* routes: add redirect if user does not have access to sync * tests: verify redirect on sync overview page happens * tests: organize tests modules to ensure enterprise is explicitly set up
@@ -13,13 +13,8 @@ export default class SyncSecretsRoute extends Route { | |||
@service declare readonly router: RouterService; | |||
@service declare readonly flags: FlagService; | |||
|
|||
beforeModel() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commented in slack about refresh ramifications removing this fetch to only happen in the cluster.js route
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! Just the question about fetching the activation flags
Adding Do not merge label so this is target for 1.17.1 and does not get into GA.
This PR hides Secrets Sync from the sidebar navigation under the following circumstances. The decisions was made to remove the upsell badges because showing Secrets Sync to users who do not have this feature or have the feature but do not have any access to the
sys/sync
endpoint is an anti-pattern to how the UI currently handles showing/hiding features.Notes:
These changes do the following:
Hides Secrets Sync nav from all OSS users.
Displays only one upsell badge for HVD managed clusters. We cannot tell which tier they are on. In the future this will likely change.
If you're an Enterprise user without Secrets Sync on your license, you will not see it in the sidebar nav.
If you're an Enterprise user with Secrets Sync on your license and it's NOT activated, you will see the sidebar nav (regardless of your policy permissions).
Below is a user Bob with the ability to read on sys/sync/destinations only, and he can see it.
Below is a user Maria with the default policy (no access to sys/sync), she can not see it.