-
Notifications
You must be signed in to change notification settings - Fork 8.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
Added data streams privileges to better control delete actions in UI #83573
Conversation
@elasticmachine merge upstream |
Pinging @elastic/es-ui (Team:Elasticsearch UI) |
b2ab845
to
1549295
Compare
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.
Great job @yuliacech ! I reviewed the code but I haven't yet been able to test locally (do you mind adding the console commands required?) For the privileges I guess I only need to create a user without the "delete_index" privilege, or is there other privileges to take into account?
Regarding the approach taken: I wonder if it would not be better to fetch the privileges at the same time as we fetch de data streams (a single request) and enhance them. Wouldn't that simplify the client code? I was wondering what happens "in between" the 2 calls (fetch the resource, fetch its privileges). Does the button to delete the stream appear or not? If the HTTP request for the privileges fails, how do we handle it client-side? For those scenarios, it seems easier to do it all server-side and have a fallback mechanism in a single place.
We'd end up with objects like this
{
name: 'my-data-stream',
...
__meta__: {
privileges: {
delete: true, // defaults to "true" if privilege request failed
}
}
}
WDYT?
@@ -240,6 +248,9 @@ export const DataStreamList: React.FunctionComponent<RouteComponentProps<MatchPa | |||
reload(); | |||
} | |||
}} | |||
canDelete={ | |||
!deletePrivileges || deletePrivileges[attemptToURIDecode(dataStreamName)!]?.delete_index | |||
} |
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 see that there are 3 calls to attemptToURIDecode(dataStreamName)
in the file and we use the decoded name everywhere. Can we make the call once at the top of the component and used it everywhere?
const decodedName = dataStreamName !== undefined
? attemptToURIDecode(dataStreamName)
: undefined;
@@ -47,3 +47,5 @@ export interface DataStreamIndex { | |||
name: string; | |||
uuid: string; | |||
} | |||
|
|||
export type DataStreamPrivileges<K extends string> = Record<string, { [key in K]: boolean }>; |
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.
Using generic is an interesting approach but I wonder if it is worth the lack of explicitness and what exactly we gain from it.
This would be much clearer to me
export interface DataStreamPrivileges {
delete_index?: boolean;
}
Whenever we read the interface we know what privileges the data stream app (or section) relies on. What are your thoughts on this?
@@ -162,6 +165,9 @@ export const DataStreamTable: React.FunctionComponent<Props> = ({ | |||
}, | |||
isPrimary: true, | |||
'data-test-subj': 'deleteDataStream', | |||
available: ({ name }: DataStream) => { |
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.
nit: We could have a method for this and use it here and below (L168)
const hasDeletePrivilege = ({ name }: DataStream) => !deletePrivileges || deletePrivileges[name]?.delete_index;
...
available: hasDeletePrivilege
...
toolsLeft: selection.length > 0 && (!deletePrivileges || selection.every(hasDeletePrivilege)) ? ( ...
@@ -449,4 +460,78 @@ describe('Data Streams tab', () => { | |||
expect(tableCellsValues).toEqual([['', 'non-managed-data-stream', 'green', '1', 'Delete']]); | |||
}); | |||
}); | |||
|
|||
describe('delete data stream privileges', () => { |
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 title is a bit misleading as it seems that we will delete the privileges :) What about simply: "Privileges: 'delete data stream'"
Hi @sebelga , thanks a lot for your suggestions! I really like the idea of fetching privileges at the same time as data streams, let me add privileges to the data stream response instead. If you still want to check it locally in the mean time, there is a 'how to test' section in PR description, I've just made the title bigger for better visibility. |
Great, I hadn't seen the description sorry! I just tested locally and it works as expected! 👍 I also throttled the requests and indeed the delete button first appears then disappears. It is not a huge deal, if the user is quick enough to click on it before it disappears he will get a non authorized error from ES anyway. |
@elasticmachine merge upstream |
Hi @sebelga , could you please have another look? I moved the privileges request inside the call for data streams as you suggested. |
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.
Thanks for making those changes @yuliacech ! I think it is much cleaner like this on the client-side. I tested locally and works as expected 👍
I left a few comments but no blockers.
I see that the link to the ILM policy now works from inside the detail panel, I just wonder why we need a full Kibana reload to access it. If we click on ILM in the menu on the left there is no page reload. Maybe something to investigate in a separate work.
delete_index: boolean; | ||
} | ||
|
||
type PrivilegesField = PrivilegesFieldFromEs; |
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 am not sure I understand why we create an alias here. Do you mind explaining?
Also not sure why there is a "Field" in the naming :) I would have called the interface simply Privileges
instead of PrivilegesFieldFromEs
but maybe I'm missing something.
|
||
if (dataStreamsStats) { | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const { store_size, maximum_timestamp } = dataStreamsStats.find( |
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 find
can potentially return undefined
so I wonder if deconstructing the value without asserting it is defined could potentially throw. I wonder why Typescript does not complain on this 🤔
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 are right, it can be undefined
at the end of the line for TypeScript not to complain. But I was thinking that we rely too much on ES returning the same data streams in both requests, but if a data stream is deleted between the requests then this logic would fail. So I added a default empty object instead.
@elasticmachine merge upstream |
💚 Build SucceededMetrics [docs]Async chunks
Page load bundle
History
To update your PR or re-run it, just comment with: |
…lastic#83573) * Added data streams privileges to better control delete actions in UI * Fix type check issues * Change data streams privileges request * Fixed type check issue * Fixed api integration test * Cleaned up not needed code * Renamed some data streams and added a default value for stats find Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
* master: [Security Solution] Exceptions Cypress tests (elastic#81759) [ML] Fix spaces job ID check (elastic#84404) [Security Solution][Detections] Handle dupes when processing threshold rules (elastic#83062) skip flaky suite (elastic#84440) skip flaky suite (elastic#84445) [APM] Fix missing `service.node.name` (elastic#84269) Upgrade fp-ts to 2.8.6 (elastic#83866) Added data streams privileges to better control delete actions in UI (elastic#83573) Improve short-url redirect validation (elastic#84366) TSVB offsets (elastic#83051) [Discover] Fix navigating back when changing index pattern (elastic#84061) [Logs UI] Polish the UI for the log entry examples in the anomaly table (elastic#82139) [Logs UI] Limit the height of the "view in context" container (elastic#83178) [Application Usage] Update `schema` with new `fleet` rename (elastic#84327) fix identation in list (elastic#84301)
…83573) (#84428) * Added data streams privileges to better control delete actions in UI * Fix type check issues * Change data streams privileges request * Fixed type check issue * Fixed api integration test * Cleaned up not needed code * Renamed some data streams and added a default value for stats find Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Summary
This PR adds a privileges check to data streams tab in Index Management so that the user without a delete privilege wont see a delete button/action anymore.
Screenshots
How to test
Instructions
manage
privileges on cluster,view_index_metadata
,monitor
on all indices (*
) anddelete_index
privileges onmy-data-stream
index.no-delete-data-stream
Checklist
TODO
Add api integration tests in a following PR
Release note
In the Index Management app, buttons to delete a data stream are now controlled by user's privileges.