use leptoskit_db::Context;
use leptoskit_db::Db;
use leptoskit_db::Id;
use super::Identity;
use super::MutationCx;
use super::OperationContext;
use super::QueryCx;
use super::sealed::Sealed;
use crate::Error;
use crate::Job;
use crate::Operation;
use crate::Result;
use crate::inbox::Notice;
use crate::server::inbox::Recipient;
use crate::server::jobs::Enqueue;
pub struct ActionCx {
db: Db,
identity: Identity,
}
impl Sealed for ActionCx {}
impl ActionCx {
pub fn new(db: Db, identity: Identity) -> Self {
Self { db, identity }
}
pub fn identity(&self) -> &Identity {
&self.identity
}
pub fn context(&self) -> &Context {
&self.identity.context
}
pub fn get<G: 'static>(&self) -> Option<&G> {
self.identity.context.get()
}
pub fn signed_in(&self) -> bool {
self.identity.context.actor().is_some()
}
pub fn user_id<U>(&self) -> Option<Id<U>> {
self.identity.context.actor().map(|actor| actor.id())
}
pub fn require_user<U>(&self) -> Result<Id<U>> {
self.user_id()
.ok_or_else(|| Error::unauthorized("sign in to do this"))
}
pub async fn query<Q: Operation<Context = QueryCx>>(&self, op: Q) -> Result<Q::Output> {
QueryCx::dispatch(&self.db, self.identity.clone(), None, op).await
}
pub async fn mutate<M: Operation<Context = MutationCx>>(&self, op: M) -> Result<M::Output> {
super::run::mutate(&self.db, self.identity.clone(), None, op).await
}
pub fn enqueue<J: Job>(&self, job: J) -> Enqueue<'static, J> {
Enqueue::on(self.db.clone(), job, self.identity.context.actor())
}
pub async fn notify(&self, account: impl Recipient, notice: Notice) -> Result<Option<String>> {
let Some(delivery) = super::inbox::insert(&self.db, &account, notice).await? else {
return Ok(None);
};
let id = delivery.id.clone();
super::inbox::deliver(delivery).await;
Ok(Some(id))
}
}
impl std::fmt::Debug for ActionCx {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ActionCx")
.field("identity", &self.identity)
.finish_non_exhaustive()
}
}
impl OperationContext for ActionCx {
async fn dispatch<O: Operation<Context = Self>>(
db: &Db,
identity: Identity,
_request_id: Option<&str>,
op: O,
) -> Result<O::Output> {
let cx = Self::new(db.clone(), identity);
op.run(&cx).await
}
}