from __future__ import annotations from quart import Blueprint, make_response, request, g, abort from sqlalchemy import select, or_ from sqlalchemy.orm import selectinload from shared.browser.app.authz import require_login from shared.browser.app.utils.htmx import is_htmx_request from shared.sx.helpers import sx_response 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.before_request async def _prepare_page_data(): if "defpage_" not in (request.endpoint or ""): return snippets = await _visible_snippets(g.s) is_admin = g.rights.get("admin") from shared.sx.page import get_template_context from sx.sx_components import _snippets_main_panel_sx tctx = await get_template_context() tctx["snippets"] = snippets tctx["is_admin"] = is_admin g.snippets_content = _snippets_main_panel_sx(tctx) from shared.sx.pages import mount_pages mount_pages(bp, "blog", names=["snippets-page"]) @bp.delete("//") @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) from sx.sx_components import render_snippets_list return sx_response(render_snippets_list(snippets, is_admin)) @bp.patch("//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) from sx.sx_components import render_snippets_list return sx_response(render_snippets_list(snippets, True)) return bp