orhun / rustypaste

A minimal file upload/pastebin service.
https://blog.orhun.dev/blazingly-fast-file-sharing
MIT License
791 stars 47 forks source link

landing page form with authentication #183

Closed classabbyamp closed 11 months ago

classabbyamp commented 11 months ago

I'd like to add a landing page like the example, but I run rustypaste as a personal pastebin that only I should be able to upload to, and it seems the web form bypasses that restriction. Is there a way to restrict this kind of upload?

If it helps, I'm already running rustypaste behind a reverse proxy (traefik).

orhun commented 11 months ago

You can set authentication tokens for upload either in the config file or as an environment variable. For example:

[server]
address = "127.0.0.1:8000"
auth_tokens = ["super_secret_token1", "super_secret_token2"]

[landing_page]
file = "landing_page.html"
content_type = "text/html; charset=utf-8"

Then the browser will return an error:

cap

Now you only need to send the token through the form somehow. I did a quick google search and it seems to be not possible to use headers in form.

But we can use fetch as follows:

    <h2>share file with auth token</h2>
    <div id="shareForm">
      <input type="file" id="file" name="file" /><br>
      <input type="text" id="authToken" placeholder="Auth Token" />
      <input type="submit" value="share" onclick="shareFileWithAuth()" />
    </form>

  <script>
    function shareFileWithAuth() {
      const fileInput = document.getElementById("file");
      const file = fileInput.files[0];

      if (!file) {
        alert("Please select a file");
        return;
      }

      const authTokenInput = document.getElementById("authToken");
      const authToken = authTokenInput.value;

      if (!authToken) {
        alert("Please provide an Auth Token");
        return;
      }

      const formData = new FormData();
      formData.append("file", file);

      fetch("/", {
        method: "POST",
        headers: {
          Authorization: authToken,
        },
        body: formData,
      })
        .then((response) => {
          if (!response.ok) {
            alert("Failed to upload");
            throw new Error("Network response was not ok");
          }
          return response.text();
        })
        .then((data) => {
          window.open(data, "_blank");
        })
        .catch((error) => {
          console.error("There was an error uploading the file:", error);
        });
    }
  </script>

I updated the landing page example in 3c3a4b58ac14013814fc6733146f66413437ca4b to demonstrate this usage:

image

Let me know if this helps! 🐻

orhun commented 11 months ago

0.14.2 is out along with this example!