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

Add UI #1170

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Add UI #1170

wants to merge 6 commits into from

Conversation

soonoo
Copy link

@soonoo soonoo commented Feb 28, 2023

Related issue: #153

Hi,
I added an UI to run simple queries or check cluster status when accessed by http address.
You can check it by starting the cluster and accessing http://localhost:4001/ui.
(You don't need to run the yarn command or something, just compile and run rqlite.)

There are a lot of files that have changed, but only one Go file has changed, and all the other changes are UI related.

  • http/service.go: An endpoint to serve the resource files is added.

I'd love for you to give it a try and let me know if you see anything out of the ordinary.

@otoolep
Copy link
Member

otoolep commented Feb 28, 2023

Thank you for this -- I will take a look shortly.

@otoolep
Copy link
Member

otoolep commented Feb 28, 2023

I'm guessing the Docker file and yarn.lock file are not needed by the UI code. Want to delete? Any other files we can pull from the diff?

What is the principle here? How are the non-Go files package up into the rqlited binary? I'd like to understand better. Today rqlite is delivered as a single binary, and that must remain the case. Happy to test it out as is (it looks like you have to read files external to the binary to bring up the UI) but I wonder if there is a way to package everything together.

@soonoo
Copy link
Author

soonoo commented Feb 28, 2023

yarn.lock is required to configure the development environment.
I'll double-check that the PR doesn't include any other unnecessary files.

@soonoo
Copy link
Author

soonoo commented Feb 28, 2023

When the user accesses http://localhost:4001/ui, the files in the ui/out directory are served.
These are the files that are built from the sources in the ui directory. It is similar to the relationship between Go source files and the rqlite binary.

The ui/out directory isn't normally managed through a git repository because it can be created from source files at any time.
But as you said, the rqlite binary needs to include the ui/out directory, so it was added to the PR.

To include the ui/out directory in the rqlite binary, I used Go's embed directive.

To summarize, only the contents of the ui/out are packaged at build time. And they're included as simple text files, which the http/ui.go file just reads and serves.
So when the user interacts with the UI, no external files are read.
However, the inclusion of these files has increased the size of the rqlite binary by about 1mb, is this okay?

// Pattern should start with "all:" prefix in order to
// include files and directories beginning with "." or "_".
//go:embed all:ui/out/*
var staticAssets embed.FS
Copy link
Author

Choose a reason for hiding this comment

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

ui/out directory is embedded as virtual file system at build time.

Copy link
Member

Choose a reason for hiding this comment

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

That's cool, definitely looking forward to learning more about that.

@otoolep
Copy link
Member

otoolep commented Feb 28, 2023

1MB increase is in size is fine.

@otoolep
Copy link
Member

otoolep commented Feb 28, 2023

Just tried it -- very cool. I'm quite excited at integrating this into rqlite.

Obviously there is lots we could do to improve this, but it's very convenient to have this built in.

@otoolep
Copy link
Member

otoolep commented Feb 28, 2023

Yeah, it works quite well -- thanks again. I do have one question however. I'm not a front-end programmer. If someone asks me about security concerns with (what I call) a single-page app, how can I assure them the app is secure? That it doesn't make network connections it shouldn't, that it doesn't operate inside in the browser in a way it shouldn't etc etc.

I do not mean to imply I think this happening -- not at all. But I need to be able to provide good answers to questions such as that if I want people to use rqlite. This is one argument in favour of keeping this application separate from the rqlite code base (though I would be happy to promote it, and add an article to rqlite.io about it).

@soonoo
Copy link
Author

soonoo commented Mar 1, 2023

As you can see, the UI is just using the HTTP API provided by rqlite. So the UI can only be used in environments that have access to the API.
If security is really important, it would be best to restrict access to the HTTP API at the network level as described in the documentation. This also makes UI available only in allowed network environment.

I think there are three things that could be improved.

  1. Add a flag to turn the ui on/off.

    • Something like -enable-ui
    • Should it default to on or off?
  2. The Basic auth info that the user enters in the UI is being stored in browser storage.
    I don't think this is likely to happen, but it is possible for someone with physical access to the device (e.g. laptop) to get the credentials.
    I think this scenario could be prevented by clearing the credentials when closing the browser tab. However, it would be a bit inconvenient to have to enter the credentials again each time.

  3. By applying Content-Security-Policy, only rqlite's API can be accessed in the browser. I'll apply this.

@patdx
Copy link

patdx commented Mar 2, 2023

Hi, I'm just a regular user of rqlite, not team member or anything, but I had a few small comments:

Is the file at http/ui/public/globals.css being used? I couldn't find any reference to it in the code. Maybe it can be removed to make the output bundle a little bit smaller?

In order to embed in rqlite, it looks like you are building the static SPA bundle via next export command. Maybe it should be documented how to regenerate the output files somewhere?

@soonoo
Copy link
Author

soonoo commented Mar 2, 2023

@patdx
Thank you!

Is the file at http/ui/public/globals.css being used? I couldn't find any reference to it in the code. Maybe it can be removed to make the output bundle a little bit smaller?

I'll also exclude that file.

In order to embed in rqlite, it looks like you are building the static SPA bundle via next export command. Maybe it should be documented how to regenerate the output files somewhere?

I'll add that as I refine README.

- Replace localStorage to sessionStorage
- Apply Content-Security-Policy
@soonoo
Copy link
Author

soonoo commented Mar 18, 2023

I added some security-related code.

  1. Content security policy: network requests is restricted to the domain where the UI is running.
  2. The credentials entered by the user are kept only within the tab.

enable-ui option has a lot of work to do, so I don't think I can include it in this PR.

@jmordica
Copy link

jmordica commented Jan 1, 2024

Any recent movement on this PR?

@otoolep
Copy link
Member

otoolep commented Jan 1, 2024

No movement on my side, I'm still not sure building a UI directly into rqlite is the right thing to do. I need to think about it.

@jmordica
Copy link

jmordica commented Jan 1, 2024

Ageeed.

@jtackaberry
Copy link
Contributor

I'm still not sure building a UI directly into rqlite is the right thing to do

Perhaps @soonoo could release it as a separate project? rqlite-ui? I'm thinking about, for example, docker registry server and the various registry UIs that exist (for example). Clean separation of concerns between server and UI, clearly defined protocol in the middle.

This feature looks like a fairly nontrivial maintenance obligation.

@soonoo
Copy link
Author

soonoo commented Jan 7, 2024

@jtackaberry Hi, please check out https://github.com/soonoo/rqman if you're interested in.

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.

None yet

5 participants