This repository has been archived on 2026-02-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blog/bp/snippets/routes.py
giles 8f7a15186c
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
feat: initialize blog app with blueprints and templates
Extract blog-specific code from the coop monolith into a standalone
repository. Includes auth, blog, post, admin, menu_items, snippets
blueprints, associated templates, Dockerfile (APP_MODULE=app:app),
entrypoint, and Gitea CI workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:15:56 +00:00

108 lines
3.1 KiB
Python

from __future__ import annotations
from quart import Blueprint, render_template, make_response, request, g, abort
from sqlalchemy import select, or_
from sqlalchemy.orm import selectinload
from suma_browser.app.authz import require_login
from suma_browser.app.utils.htmx import is_htmx_request
from models import Snippet
VALID_VISIBILITY = frozenset({"private", "shared", "admin"})
async def _visible_snippets(session):
"""Return snippets visible to the current user (own + shared + admin-if-admin)."""
uid = g.user.id
is_admin = g.rights.get("admin")
filters = [Snippet.user_id == uid, Snippet.visibility == "shared"]
if is_admin:
filters.append(Snippet.visibility == "admin")
rows = (await session.execute(
select(Snippet).where(or_(*filters)).order_by(Snippet.name)
)).scalars().all()
return rows
def register():
bp = Blueprint("snippets", __name__, url_prefix="/settings/snippets")
@bp.get("/")
@require_login
async def list_snippets():
"""List snippets visible to the current user."""
snippets = await _visible_snippets(g.s)
is_admin = g.rights.get("admin")
if not is_htmx_request():
html = await render_template(
"_types/snippets/index.html",
snippets=snippets,
is_admin=is_admin,
)
else:
html = await render_template(
"_types/snippets/_oob_elements.html",
snippets=snippets,
is_admin=is_admin,
)
return await make_response(html)
@bp.delete("/<int:snippet_id>/")
@require_login
async def delete_snippet(snippet_id: int):
"""Delete a snippet. Owners delete their own; admins can delete any."""
snippet = await g.s.get(Snippet, snippet_id)
if not snippet:
abort(404)
is_admin = g.rights.get("admin")
if snippet.user_id != g.user.id and not is_admin:
abort(403)
await g.s.delete(snippet)
await g.s.flush()
snippets = await _visible_snippets(g.s)
html = await render_template(
"_types/snippets/_list.html",
snippets=snippets,
is_admin=is_admin,
)
return await make_response(html)
@bp.patch("/<int:snippet_id>/visibility/")
@require_login
async def patch_visibility(snippet_id: int):
"""Change snippet visibility. Admin only."""
if not g.rights.get("admin"):
abort(403)
snippet = await g.s.get(Snippet, snippet_id)
if not snippet:
abort(404)
form = await request.form
visibility = form.get("visibility", "").strip()
if visibility not in VALID_VISIBILITY:
abort(400)
snippet.visibility = visibility
await g.s.flush()
snippets = await _visible_snippets(g.s)
html = await render_template(
"_types/snippets/_list.html",
snippets=snippets,
is_admin=True,
)
return await make_response(html)
return bp