mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2026-02-11 10:05:41 +00:00
feat: migrate notifications add, mark_read and get to use db_* traits
This commit is contained in:
@@ -173,22 +173,6 @@ async fn update(
|
||||
data.dblib
|
||||
.delete_traffic_pattern(&username, &msg.key)
|
||||
.await?;
|
||||
// sqlx::query!(
|
||||
// "DELETE FROM mcaptcha_sitekey_user_provided_avg_traffic
|
||||
// WHERE config_id = (
|
||||
// SELECT config_id
|
||||
// FROM
|
||||
// mcaptcha_config
|
||||
// WHERE
|
||||
// key = ($1)
|
||||
// AND
|
||||
// user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2)
|
||||
// );",
|
||||
// &msg.key,
|
||||
// &username,
|
||||
// )
|
||||
// .execute(&data.db)
|
||||
// .await?;
|
||||
|
||||
data.dblib
|
||||
.add_traffic_pattern(&username, &msg.key, &pattern)
|
||||
|
||||
@@ -22,8 +22,10 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::errors::*;
|
||||
use crate::AppData;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AddNotification {
|
||||
use db_core::AddNotification;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
|
||||
pub struct AddNotificationRequest {
|
||||
pub to: String,
|
||||
pub heading: String,
|
||||
pub message: String,
|
||||
@@ -35,27 +37,22 @@ pub struct AddNotification {
|
||||
wrap = "crate::api::v1::get_middleware()"
|
||||
)]
|
||||
pub async fn add_notification(
|
||||
payload: web::Json<AddNotification>,
|
||||
payload: web::Json<AddNotificationRequest>,
|
||||
data: AppData,
|
||||
id: Identity,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let sender = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
sqlx::query!(
|
||||
"INSERT INTO mcaptcha_notifications (
|
||||
heading, message, tx, rx)
|
||||
VALUES (
|
||||
$1, $2,
|
||||
(SELECT ID FROM mcaptcha_users WHERE name = $3),
|
||||
(SELECT ID FROM mcaptcha_users WHERE name = $4)
|
||||
);",
|
||||
&payload.heading,
|
||||
&payload.message,
|
||||
&sender,
|
||||
&payload.to,
|
||||
)
|
||||
.execute(&data.db)
|
||||
.await?;
|
||||
|
||||
let p = AddNotification {
|
||||
from: &sender,
|
||||
to: &payload.to,
|
||||
message: &payload.message,
|
||||
heading: &payload.heading,
|
||||
};
|
||||
|
||||
data.dblib.create_notification(&p).await?;
|
||||
|
||||
Ok(HttpResponse::Ok())
|
||||
}
|
||||
|
||||
@@ -88,7 +85,7 @@ pub mod tests {
|
||||
let cookies = get_cookie!(signin_resp);
|
||||
let app = get_app!(data).await;
|
||||
|
||||
let msg = AddNotification {
|
||||
let msg = AddNotificationRequest {
|
||||
to: NAME2.into(),
|
||||
heading: "Test notification".into(),
|
||||
message: "Testeing notifications with a dummy message".into(),
|
||||
|
||||
@@ -18,20 +18,13 @@
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{HttpResponse, Responder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
|
||||
use crate::errors::*;
|
||||
use crate::AppData;
|
||||
|
||||
pub struct Notification {
|
||||
pub name: Option<String>,
|
||||
pub heading: Option<String>,
|
||||
pub message: Option<String>,
|
||||
pub received: Option<OffsetDateTime>,
|
||||
pub id: Option<i32>,
|
||||
}
|
||||
use db_core::Notification;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Default, PartialEq, Clone, Deserialize, Serialize)]
|
||||
pub struct NotificationResp {
|
||||
pub name: String,
|
||||
pub heading: String,
|
||||
@@ -45,13 +38,26 @@ impl From<Notification> for NotificationResp {
|
||||
NotificationResp {
|
||||
name: n.name.unwrap(),
|
||||
heading: n.heading.unwrap(),
|
||||
received: n.received.unwrap().unix_timestamp(),
|
||||
received: n.received.unwrap(),
|
||||
id: n.id.unwrap(),
|
||||
message: n.message.unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NotificationResp {
|
||||
pub fn from_notifications(mut n: Vec<Notification>) -> Vec<Self> {
|
||||
let mut notifications = Vec::with_capacity(n.len());
|
||||
|
||||
n.drain(0..).for_each(|x| {
|
||||
let y: NotificationResp = x.into();
|
||||
notifications.push(y)
|
||||
});
|
||||
|
||||
notifications
|
||||
}
|
||||
}
|
||||
|
||||
/// route handler that gets all unread notifications
|
||||
#[my_codegen::get(
|
||||
path = "crate::V1_API_ROUTES.notifications.get",
|
||||
@@ -64,36 +70,9 @@ pub async fn get_notification(
|
||||
let receiver = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
|
||||
let mut notifications = runner::get_notification(&data, &receiver).await?;
|
||||
let resp: Vec<NotificationResp> = notifications
|
||||
.drain(0..)
|
||||
.map(|x| {
|
||||
let y: NotificationResp = x.into();
|
||||
y
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(HttpResponse::Ok().json(resp))
|
||||
}
|
||||
|
||||
pub mod runner {
|
||||
use super::*;
|
||||
pub async fn get_notification(
|
||||
data: &AppData,
|
||||
receiver: &str,
|
||||
) -> ServiceResult<Vec<Notification>> {
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
|
||||
let notifications = sqlx::query_file_as!(
|
||||
Notification,
|
||||
"src/api/v1/notifications/get_all_unread.sql",
|
||||
&receiver
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await?;
|
||||
|
||||
Ok(notifications)
|
||||
}
|
||||
let notifications = data.dblib.get_all_unread_notifications(&receiver).await?;
|
||||
let notifications = NotificationResp::from_notifications(notifications);
|
||||
Ok(HttpResponse::Ok().json(notifications))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -102,7 +81,7 @@ pub mod tests {
|
||||
use actix_web::test;
|
||||
|
||||
use super::*;
|
||||
use crate::api::v1::notifications::add::AddNotification;
|
||||
use crate::api::v1::notifications::add::AddNotificationRequest;
|
||||
use crate::tests::*;
|
||||
use crate::*;
|
||||
|
||||
@@ -130,7 +109,7 @@ pub mod tests {
|
||||
let cookies2 = get_cookie!(signin_resp2);
|
||||
let app = get_app!(data).await;
|
||||
|
||||
let msg = AddNotification {
|
||||
let msg = AddNotificationRequest {
|
||||
to: NAME2.into(),
|
||||
heading: HEADING.into(),
|
||||
message: MESSAGE.into(),
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
-- gets all unread notifications a user has
|
||||
SELECT
|
||||
mcaptcha_notifications.id,
|
||||
mcaptcha_notifications.heading,
|
||||
mcaptcha_notifications.message,
|
||||
mcaptcha_notifications.received,
|
||||
mcaptcha_users.name
|
||||
FROM
|
||||
mcaptcha_notifications
|
||||
INNER JOIN
|
||||
mcaptcha_users
|
||||
ON
|
||||
mcaptcha_notifications.tx = mcaptcha_users.id
|
||||
WHERE
|
||||
mcaptcha_notifications.rx = (
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
mcaptcha_users
|
||||
WHERE
|
||||
name = $1
|
||||
)
|
||||
AND
|
||||
mcaptcha_notifications.read IS NULL;
|
||||
@@ -27,15 +27,6 @@ pub struct MarkReadReq {
|
||||
pub id: i32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct NotificationResp {
|
||||
pub name: String,
|
||||
pub heading: String,
|
||||
pub message: String,
|
||||
pub received: i64,
|
||||
pub id: i32,
|
||||
}
|
||||
|
||||
/// route handler that marks a notification read
|
||||
#[my_codegen::post(
|
||||
path = "crate::V1_API_ROUTES.notifications.mark_read",
|
||||
@@ -49,14 +40,10 @@ pub async fn mark_read(
|
||||
let receiver = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
|
||||
sqlx::query_file_as!(
|
||||
Notification,
|
||||
"src/api/v1/notifications/mark_read.sql",
|
||||
payload.id,
|
||||
&receiver
|
||||
)
|
||||
.execute(&data.db)
|
||||
.await?;
|
||||
// TODO get payload from path /api/v1/notifications/{id}/read"
|
||||
data.dblib
|
||||
.mark_notification_read(&receiver, payload.id)
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Ok())
|
||||
}
|
||||
@@ -67,7 +54,8 @@ pub mod tests {
|
||||
use actix_web::test;
|
||||
|
||||
use super::*;
|
||||
use crate::api::v1::notifications::add::AddNotification;
|
||||
use crate::api::v1::notifications::add::AddNotificationRequest;
|
||||
use crate::api::v1::notifications::get::NotificationResp;
|
||||
use crate::tests::*;
|
||||
use crate::*;
|
||||
|
||||
@@ -94,7 +82,7 @@ pub mod tests {
|
||||
let cookies2 = get_cookie!(signin_resp2);
|
||||
let app = get_app!(data).await;
|
||||
|
||||
let msg = AddNotification {
|
||||
let msg = AddNotificationRequest {
|
||||
to: NAME2.into(),
|
||||
heading: HEADING.into(),
|
||||
message: MESSAGE.into(),
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
-- mark a notification as read
|
||||
UPDATE mcaptcha_notifications
|
||||
SET read = TRUE
|
||||
WHERE
|
||||
mcaptcha_notifications.id = $1
|
||||
AND
|
||||
mcaptcha_notifications.rx = (
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
mcaptcha_users
|
||||
WHERE
|
||||
name = $2
|
||||
);
|
||||
@@ -20,9 +20,8 @@ use actix_web::{HttpResponse, Responder};
|
||||
use sailfish::TemplateOnce;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
|
||||
use crate::api::v1::notifications::get::{self, runner};
|
||||
use crate::date::Date;
|
||||
use crate::errors::PageResult;
|
||||
use crate::errors::{PageError, PageResult, ServiceError};
|
||||
use crate::AppData;
|
||||
|
||||
#[derive(TemplateOnce)]
|
||||
@@ -46,12 +45,12 @@ pub struct Notification {
|
||||
pub id: i32,
|
||||
}
|
||||
|
||||
impl From<get::Notification> for Notification {
|
||||
fn from(n: get::Notification) -> Self {
|
||||
impl From<db_core::Notification> for Notification {
|
||||
fn from(n: db_core::Notification) -> Self {
|
||||
Notification {
|
||||
name: n.name.unwrap(),
|
||||
heading: n.heading.unwrap(),
|
||||
received: n.received.unwrap(),
|
||||
received: OffsetDateTime::from_unix_timestamp(n.received.unwrap()),
|
||||
id: n.id.unwrap(),
|
||||
message: n.message.unwrap(),
|
||||
}
|
||||
@@ -74,7 +73,17 @@ pub async fn notifications(data: AppData, id: Identity) -> PageResult<impl Respo
|
||||
let receiver = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
|
||||
let mut notifications = runner::get_notification(&data, &receiver).await?;
|
||||
// let mut notifications = runner::get_notification(&data, &receiver).await?;
|
||||
let mut notifications = data
|
||||
.dblib
|
||||
.get_all_unread_notifications(&receiver)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
let se: ServiceError = e.into();
|
||||
let pe: PageError = se.into();
|
||||
pe
|
||||
})?;
|
||||
|
||||
let notifications = notifications.drain(0..).map(|x| x.into()).collect();
|
||||
|
||||
let body = IndexPage::new(notifications).render_once().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user