magnetar/ext_calckey_model/src/notification_model.rs

163 lines
5.0 KiB
Rust

use crate::model_ext::{
AliasColumnExt, AliasSourceExt, AliasSuffixExt, CursorPaginationExt, EntityPrefixExt, MagIden,
ModelPagination, SelectColumnsExt,
};
use crate::note_model::data::NoteData;
use crate::note_model::{NoteResolveOptions, NoteResolver};
use crate::user_model::{UserData, UserResolveOptions, UserResolver};
use crate::{CalckeyDbError, CalckeyModel};
use chrono::{DateTime, Utc};
use ck::{access_token, notification, user};
use ext_calckey_model_migration::{JoinType, SelectStatement};
use magnetar_sdk::types::SpanFilter;
use sea_orm::Iden;
use sea_orm::{DbErr, EntityTrait, FromQueryResult, QueryFilter, QueryResult, QuerySelect};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotificationData {
pub notification: notification::Model,
pub access_token: Option<access_token::Model>,
pub notifier: Option<UserData>,
pub notification_note: Option<NoteData>,
}
impl FromQueryResult for NotificationData {
fn from_query_result(res: &QueryResult, prefix: &str) -> Result<Self, DbErr> {
let prefix = if prefix.is_empty() {
notification::Entity.base_prefix()
} else {
MagIden::alias(prefix)
};
Ok(NotificationData {
notification: notification::Model::from_query_result(res, &prefix.to_string())?,
access_token: access_token::Model::from_query_result_optional(
res,
&prefix.join_str_as_str(ACCESS_TOKEN),
)?,
notification_note: NoteData::from_query_result_optional(
res,
&prefix.join_str_as_str(NOTIFICATION_NOTE),
)?,
notifier: UserData::from_query_result_optional(res, &prefix.join_str_as_str(NOTIFIER))?,
})
}
}
impl ModelPagination for NotificationData {
fn id(&self) -> &str {
&self.notification.id
}
fn time(&self) -> DateTime<Utc> {
self.notification.created_at.into()
}
}
const NOTIFICATION: &str = "notification.";
const NOTIFIER: &str = "notifier.";
const NOTIFICATION_NOTE: &str = "note.";
const ACCESS_TOKEN: &str = "access_token.";
pub struct NotificationResolveOptions {}
#[derive(Clone)]
pub struct NotificationResolver {
db: CalckeyModel,
note_resolver: NoteResolver,
user_resolver: UserResolver,
}
impl NotificationResolver {
pub(crate) fn new(
db: CalckeyModel,
user_resolver: UserResolver,
note_resolver: NoteResolver,
) -> Self {
Self {
db,
note_resolver,
user_resolver,
}
}
pub fn resolve(
&self,
q: &mut SelectStatement,
notification_tbl: &MagIden,
note_options: &NoteResolveOptions,
user_options: &UserResolveOptions,
note_resolver: &NoteResolver,
user_resolver: &UserResolver,
) {
let notifier_tbl = notification_tbl.join_str(NOTIFIER);
q.add_aliased_columns::<user::Entity>(&notifier_tbl);
q.join_columns(
JoinType::LeftJoin,
notification::Relation::User2.with_from_alias(notification_tbl),
&notifier_tbl,
);
user_resolver.resolve(q, &notifier_tbl, &user_options);
let token_tbl = notification_tbl.join_str(ACCESS_TOKEN);
q.add_aliased_columns::<access_token::Entity>(&token_tbl);
q.join_columns(
JoinType::LeftJoin,
notification::Relation::AccessToken.with_from_alias(notification_tbl),
&token_tbl,
);
let note_tbl = notification_tbl.join_str(NOTIFICATION_NOTE);
q.join_columns(
JoinType::LeftJoin,
notification::Relation::Note.with_from_alias(notification_tbl),
&note_tbl,
);
note_resolver.attach_note(q, &note_tbl, 1, 1, note_options, &self.user_resolver);
}
pub async fn get(
&self,
note_options: &NoteResolveOptions,
user_options: &UserResolveOptions,
user_id: &str,
pagination: &SpanFilter,
prev: &mut Option<SpanFilter>,
next: &mut Option<SpanFilter>,
limit: u64,
) -> Result<Vec<NotificationData>, CalckeyDbError> {
let notification_tbl = notification::Entity.base_prefix();
let mut select = notification::Entity::find();
let query = QuerySelect::query(&mut select);
self.resolve(
query,
&notification_tbl,
note_options,
user_options,
&self.note_resolver,
&self.user_resolver,
);
let notifications = select
.filter(
notification_tbl
.col(notification::Column::NotifieeId)
.eq(user_id),
)
.get_paginated_model::<NotificationData, _, _>(
&self.db.0,
(notification::Column::CreatedAt, notification::Column::Id),
pagination,
prev,
next,
limit,
)
.await?;
Ok(notifications)
}
}