roundabout,
created on Sunday, 16 February 2025, 14:24:24 (1739715864),
received on Sunday, 16 February 2025, 14:24:27 (1739715867)
Author identity: vlad <vlad.muntoiu@gmail.com>
8b93dc5623bcaa578073be272e9f4844e359b8f7
app.py
@@ -64,6 +64,7 @@ def default_variables():
return { "current_user": db.session.get(User, flask.session.get("username")), "site_name": config.SITE_NAME, "config": config,}
@@ -1764,7 +1765,7 @@ def api_put_file(id):
return flask.jsonify({"error": "Provide a file"}), 400 if not file.mimetype.startswith("image/") or file.mimetype == "image/svg+xml": return flask.jsonify({"error": "Only images are supported"}), 400return flask.jsonify({"error": "Only images are supported"}), 415file_path = path.join(config.DATA_PATH, "pictures", str(resource.id)) # Since it's a hard link, we need to remove it, so it won't affect copies
@@ -2031,3 +2032,20 @@ def api_delete_gallery(id):
return flask.jsonify({"message": "Gallery deleted"}) def random_picture(): return db.session.query(PictureResource).order_by(db.func.random()).first() for code in range(400, 600): if os.path.exists(f"templates/errors/{code}.html"): app.register_error_handler(code, lambda e: error_page(e.code)) @app.route("/error/<int:code>") def error_page(code): user_agent = flask.request.headers.get("User-Agent", "") ip_address = flask.request.remote_addr return flask.render_template(f"errors/{code}.html", random_picture=random_picture(), user_agent=user_agent, ip_address=ip_address), code
config.py
@@ -10,3 +10,4 @@ ROOT_URL = "http://localhost:8080"
SITE_NAME = "Development site" THUMBNAIL_SAVE_OPTIONS = {"format": "JPEG", "quality": 90} THUMBNAIL_SIZE = (576, 576) CONTACT_LINK = "mailto:root@roundabout-host.com"
help/usage.md
@@ -247,6 +247,11 @@ status and `joined` date.
put a star rating on the picture. To delete the rating call it with a false value. `POST` to `/api/picture/<id>/delete` will delete the picture. `POST` to `/api/picture/<id>/put-file` with a form payload containing a `file` key will replace the picture's file with what was provided. `/api/gallery/<id>` will give metadata about the gallery in JSON: `id`, `title`, `description`, `owner` and `users`. To get the pictures you can use a query.
static/style.css
@@ -19,6 +19,7 @@
--reserved-height-top: 0; --color-checkerboard-dark: #CFD8DC; --color-checkerboard-light: #FFFFFF; --color-divider: var(--text-softest);} .ripple-pad {
@@ -966,3 +967,13 @@ input[type="file"] {
.thumbnail-card-small { margin: auto; } hr { border: 0.25px solid var(--color-divider); width: 100%; } body { display: flex; flex-direction: column; }
templates/default.html
@@ -14,6 +14,7 @@
} } </style> {% block extra_head %}{% endblock %}<body {% if fixed_content_area %}class="fixed-content-area"{% endif %}> <dialog id="hamburger" class="sheet-left"> <nav>
templates/error.html
@@ -0,0 +1,66 @@
{% extends "default.html" %} {% block nav_title %}{{ error }}{% endblock %} {% block title %}{{ error_code }} {{ error }} | {{ site_name }}{% endblock %} {% block extra_head %} <style> body::before { width: 100%; height: 100%; position: fixed; z-index: -1; content: ""; filter: saturate(0.875) brightness(0.875); background: radial-gradient(circle, rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.75)), url("/raw/picture/{{ random_picture.id }}") center / cover no-repeat, #000000; } main { height: 100%; width: 100%; display: flex; flex-grow: 1; flex-direction: column; justify-content: center; align-items: center; color: #ffffff; --color-background-text: #ffffff; --text-soft: #ffffffe0; --text-faint: #ffffffc0; --text-softer: #ffffff80; --text-softest: #ffffff50; --color-link-text: #ffffff; --color-link-hover-text: #ffffff; --color-link-visited-text: #ffffff; --color-link-active-text: #ffffff; --color-link-visited-hover-text: #ffffff; text-align: center; } #error-code { font-size: 1.25em; font-weight: bold; text-transform: uppercase; color: var(--color-accent-3); width: fit-content; margin: 1rem; text-shadow: 0 1px 4px #00000080, 0 0 1px #00000080, 0 0 2px #00000040; } </style> {% endblock %} {% block content %} <h1>{{ error }}</h1> {% block error_content %} {% endblock %} <p id="error-code"> HTTP error {{ error_code }} </p> <p> If you came here from the API, <a href="/help">RTFM</a> :) </p> <p> If you believe this is our fault, please <a href="{{ config.CONTACT_LINK }}">contact us</a>. </p> {% endblock %}
templates/errors/400.html
@@ -0,0 +1,17 @@
{% extends "error.html" %} {% set error = "Bad request" %} {% set error_code = 400 %} {% block error_content %} <p> The server doesn't understand your request, as it doesn't make sense, just like your obsession with hacking forms to break websites. Please just stop and get a life. </p> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/401.html
@@ -0,0 +1,32 @@
{% extends "error.html" %} {% set error = "Unauthorised" %} {% set error_code = 401 %} {% block error_content %} <p> You must be authenticated to access this. And even if you're authenticated, you need to have the right permissions, or you'll get 403 Forbidden. How did you even think you could do this anonymously?<br> <a href="/accounts/">Log in</a> and try this request again. Or just look at this random picture the server found for you. Try bribing the subject of it for access, there may be a nonzero chance it will let you in.<br> What reason do you even have not to <a href="/accounts/">have an account</a>? FYI, we already know your IP address, city, browser, OS, device, screen size, ISP (as any website does), and we've just logged your terrible attempt at breaking our server (we actually log everything), so it's not like you're losing anything by signing up. Don't believe us?<br> Aren't you using a <code>{{ user_agent }}</code>? No, we don't run analytics and we're not interested in your data. </p> <div style="padding: 1rem; display: flex; flex-direction: column; align-items: center;"> Try our bribe service, in case you've logged in but can't access the resource, putting you in depression: <a class="button" href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">Attempt to bribe the cat/dog/flower/rubbish/sun/[insert object here] for access</a> (bribe service requires JavaScript, cookies and sending your data to Google, which actually wants it, unlike us) </div> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/403.html
@@ -0,0 +1,24 @@
{% extends "error.html" %} {% set error = "Forbidden" %} {% set error_code = 403 %} {% block error_content %} <p> You're not allowed to access this resource. In fact, you shouldn't have been able to see this page at all. Our app isn't made in JS, did you think you could just bypass security by forcing the submit button to appear?<br> However, you <em>can</em> access this random and unrelated picture. Try bribing the subject of it for access, there may be a nonzero chance it will let you in. </p> <div style="padding: 1rem; display: flex; flex-direction: column; align-items: center;"> Try our bribe service, in case you've logged in but can't access the resource, putting you in depression: <a class="button" href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">Attempt to bribe the cat/dog/flower/rubbish/sun/[insert object here] for access</a> (bribe service requires JavaScript, cookies and sending your data to Google, which actually wants it, unlike us) </div> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/404.html
@@ -0,0 +1,18 @@
{% extends "error.html" %} {% set error = "Page not found" %} {% set error_code = 404 %} {% block error_content %} <p> The server couldn't find the resource you requested. It might have previously existed, or it might have never been there. Make sure you have the correct URL.<br> Enjoy this random and unrelated picture instead. </p> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/405.html
@@ -0,0 +1,18 @@
{% extends "error.html" %} {% set error = "Method not allowed" %} {% set error_code = 405 %} {% block error_content %} <p> The server knows this URL, but it's not meant to be used with this HTTP method. You probably came here either from an API mistake, or to flex your cybersecurity skills (it won't work here).<br> While you figure out what to do, relax with this beautiful (or not, we don't know) random picture. </p> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/413.html
@@ -0,0 +1,35 @@
{% extends "error.html" %} {% set error = "Payload too large" %} {% set error_code = 413 %} {% block error_content %} <p> Your request's body is too large for the server to process. This is a free service; be considerate of the resources you use. If this is your second time seeing this error, do you want to get in trouble for vandalism?<br> <strong>Don't do it again, and <a href="/help/">read about our limits</a>.</strong><br> Hopefully, the random picture here will help you calm down and reconsider your actions (if they were intentional). </p> <p> There are better places to waste storage someone is paying for. Try <a href="https://drive.google.com/">Google Drive</a>, <a href="https://www.dropbox.com/">Dropbox</a>, <a href="https://onedrive.live.com/">Microsoft OneDrive</a>, <a href="https://mediafire.com/">MediaFire</a> or <a href="https://github.com">GitHub</a>. but not our server. </p> <p> There's above a 33% chance that you're obsessed with JavaScript and "modern" (i.e. overcomplicated) web development; in that case there's <a href="https://www.netlify.com/">Netlify</a> and <a href="https://aws.amazon.com/s3/">Amazon S3</a> for you. </p> <p> (disclaimer: check terms of service before abusing their services) </p> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/418.html
@@ -0,0 +1,18 @@
{% extends "error.html" %} {% set error = "I'm a teapot" %} {% set error_code = 418 %} {% block error_content %} <p> This server is a teapot, so it is unable to brew coffee. In reality, you're reaching a route that isn't yet implemented.<br> Enjoy the random picture here to compensate for our missing functionality. </p> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/500.html
@@ -0,0 +1,21 @@
{% extends "error.html" %} {% set error = "Internal server error" %} {% set error_code = 500 %} {% block error_content %} <p> The server crashed and there is no further information about what happened. Your request broke the software running the server. Now please get out of here so you don't break anything else, and report this to the server administrator, whose email can be found below, so we know there's a problem.<br> Now enjoy the random picture here. That is, if the server didn't crash whilst trying to fetch it. </p> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}
templates/errors/503.html
@@ -0,0 +1,18 @@
{% extends "error.html" %} {% set error = "Service unavailable" %} {% set error_code = 503 %} {% block error_content %} <p> A server administrator has decided that they're bored of the server running normally, so they put it in a maintenance mode. You should go touch grass while the server is down.<br> We've also served a random picture here as a compensation for the inconvenience. </p> <p> <a href="/">Home page</a> </p> <p> <a href="/picture/{{ random_picture.id }}/">Like what you see?</a> </p> {% endblock %}