//! Database read queries, projection structs and SQL. use chrono::{DateTime, Utc}; use mt_core::types::{BanType, CommunityRole, CommunityState, ModAction, SortColumn, SortOrder}; use sqlx::PgPool; use uuid::Uuid; /// A community resource loaded by id but not yet proven to belong to a caller's /// community scope (the ultra-fuzz C1 invariant). /// /// A `/p/{slug}/…/{resource_id}` handler must serve a resource whose community /// equals the one the `{slug}` names. `Unscoped` makes that the *only* way to /// obtain the resource: the inner value is private and [`Unscoped::in_community`] /// yields it only when the resource's community matches the one the caller names. /// A handler therefore cannot read a by-id resource without proving it belongs to /// the URL's community, and the seal fails closed by type: any new by-id loader /// that returns `Unscoped` is bound by the same rule with no lint to remember. pub struct Unscoped { inner: T, community_id: Uuid, } impl Unscoped { /// Wrap a freshly-loaded resource together with the community it lives in. pub fn new(inner: T, community_id: Uuid) -> Self { Self { inner, community_id, } } /// Yield the resource only if it belongs to `expected_community`; `None` /// otherwise (the id names a resource in a different community, which to a /// scoped URL is indistinguishable from "not found"). pub fn in_community(self, expected_community: Uuid) -> Option { (self.community_id == expected_community).then_some(self.inner) } /// Unwrap without a community check. This is the deliberate escape hatch for /// callers that have no URL slug to scope against, the trusted internal /// server-to-server API. It is on `clippy.toml`'s `disallowed-methods` so a /// normal handler cannot reach for it by accident; the few sanctioned call /// sites carry a local `#[allow]`. Anything reached via `/p/{slug}/…` must use /// [`Unscoped::in_community`] instead. pub fn into_inner_unchecked(self) -> T { self.inner } } mod admin; mod category; mod community; mod endorsement; mod footnote; mod image; mod link_preview; mod member; mod mention; mod moderation; mod post; mod search; mod tag; mod thread; mod tracked_thread; mod user; pub use admin::*; pub use category::*; pub use community::*; pub use endorsement::*; pub use footnote::*; pub use image::*; pub use link_preview::*; pub use member::*; pub use mention::*; pub use moderation::*; pub use post::*; pub use search::*; pub use tag::*; pub use thread::*; pub use tracked_thread::*; pub use user::*; // Explicit re-exports so clippy.toml disallowed-methods paths resolve // (path-based lints do not follow glob re-exports). pub use post::get_post_for_edit; pub use thread::get_thread_with_breadcrumb;