-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
feat(UI): File output preview #1770
Conversation
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 the behaviour should change: we should only supported a fixed set of extensions and if a file is not of this extension didn't show the button and generates an error in the backend. We can revisit this later but it is preferable for security, performance (some file may not be multi-line) and usability (binary may crash the browser).
Also, I think the preview may be better on a modal on the centre instead of the "coming from right" modal but it can wait for some redesign.
ui/src/translations.json
Outdated
"dependency task": "Task {taskId} is a dependency of another task" | ||
"dependency task": "Task {taskId} is a dependency of another task", | ||
"preview": "Preview", | ||
"open": "Open" |
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.
Show is better than Open
|
||
String extension = FilenameUtils.getExtension(path.toString()); | ||
|
||
if (ImageFileExtension.isImageFileExtension(extension)) { |
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 use a simple List of extensions as you didn't really use the enum
case "png": | ||
case "svg": | ||
return "image"; | ||
default: |
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 should not default to text, this should be an extension like the other and default to not preview.
This can be a security risk to allow any extension file.
And this can crash Kestra UI for example if a binary format with non-displayable characters is used.
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 don't see how it can be a security risk as I just display character. The only difference is that if I don't know the extension, there will be no syntax highlighting.
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.
Well security issues can hide in multiple way.
Anyway, as I commented somewhere else, binary format may crash the browser, and some files may also be one long line that (avro, parquet, ...) so better only display what we are sure can be displayed.
return httpResponse; | ||
} | ||
|
||
InputStream fileStream = storageInterface.get(path); |
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 should restrict the loading of files only to supported extensions and throws an error for the other.
webserver/src/main/java/io/kestra/webserver/utils/ImageFileExtension.java
Outdated
Show resolved
Hide resolved
case "svg": | ||
return "data:image/" + this.extension + ";base64," + this.content; | ||
default: | ||
return this.content; |
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.
not a good idea as some files may not be displayable.
|
||
StringBuilder contentBuilder = new StringBuilder(); | ||
|
||
while (line != null && lineCount < 100) { |
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.
Not all files are multi-line, you can have a huge file with a one-in JSON in it.
I'm not sure we can do something better than that anyway
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.
One solution would be to limit the size of the content return, limit to a size of 2mb for example so even if my file is a heavy one-line, I will return limited content
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.
Agree that we need an limit in MB or number of lines, the first that will cut of
@loicmathieu |
7b47dc3
to
5d68498
Compare
5d68498
to
9bb2f3c
Compare
} | ||
} | ||
|
||
return HttpResponse.ok(PreviewResponse.builder().extension(extension).content(truncateStringSize(contentBuilder.toString())).build()); |
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.
Truncating the file after it has been read is not a good idea as the file will still be loaded entirely in memory.
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.
agree also
|
||
public String truncateStringSize(String content) { | ||
// Equivalent to 2MB | ||
int maxSizeInBytes = 2097152; |
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.
Please use a constant.
A good practice is to declare it something like:
private int TWO_MB = 2 * 1024 * 1024;
81e4e93
to
567495f
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.
please:
- move the rendering of the data on the server side
- fix an issue where multiple drawer will be open if I have multiple output preview on the same execution
e2261fc
to
a03c61d
Compare
d71c407
to
ac78a83
Compare
ac78a83
to
8a00d5a
Compare
69ed71e
to
99eef9c
Compare
close #1767