feat: impl traits to add, get and mark read notifications for sqlx

postgres
This commit is contained in:
realaravinth
2022-05-26 19:32:16 +05:30
parent e9921db55b
commit 44740535c2
5 changed files with 143 additions and 24 deletions

View File

@@ -0,0 +1,3 @@
-- Add migration script here
ALTER TABLE mcaptcha_notifications ALTER COLUMN heading TYPE varchar(100),
ALTER COLUMN heading SET NOT NULL;

View File

@@ -0,0 +1,24 @@
-- 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;

View File

@@ -637,30 +637,98 @@ impl MCDatabase for Database {
.map_err(|e| map_row_not_found_err(e, DBError::TrafficPatternNotFound))?; .map_err(|e| map_row_not_found_err(e, DBError::TrafficPatternNotFound))?;
Ok(()) Ok(())
} }
/// create new notification
async fn create_notification(&self, p: &AddNotification) -> DBResult<()> {
let now = now_unix_time_stamp();
sqlx::query!(
"INSERT INTO mcaptcha_notifications (
heading, message, tx, rx, received)
VALUES (
$1, $2,
(SELECT ID FROM mcaptcha_users WHERE name = $3),
(SELECT ID FROM mcaptcha_users WHERE name = $4),
$5
);",
p.heading,
p.message,
p.from,
p.to,
now
)
.execute(&self.pool)
.await
.map_err(map_register_err)?;
Ok(())
}
/// get all unread notifications
async fn get_all_unread_notifications(
&self,
username: &str,
) -> DBResult<Vec<Notification>> {
let mut inner_notifications = sqlx::query_file_as!(
InnerNotification,
"./src/get_all_unread_notifications.sql",
&username
)
.fetch_all(&self.pool)
.await
.map_err(|e| map_row_not_found_err(e, DBError::AccountNotFound))?;
let mut notifications = Vec::with_capacity(inner_notifications.len());
inner_notifications
.drain(0..)
.for_each(|n| notifications.push(n.into()));
Ok(notifications)
}
/// mark a notification read
async fn mark_notification_read(&self, username: &str, id: i32) -> DBResult<()> {
sqlx::query_file_as!(
Notification,
"./src/mark_notification_read.sql",
id,
&username
)
.execute(&self.pool)
.await
.map_err(|e| map_row_not_found_err(e, DBError::NotificationNotFound))?;
Ok(())
}
} }
fn now_unix_time_stamp() -> i64 { fn now_unix_time_stamp() -> OffsetDateTime {
OffsetDateTime::now_utc().unix_timestamp() OffsetDateTime::now_utc()
} }
// #[derive(Debug, Clone, Default, PartialEq)]
//#[allow(non_snake_case)] /// Represents notification
//struct InnerGistComment { pub struct InnerNotification {
// ID: i64, /// receiver name of the notification
// owner: String, pub name: Option<String>,
// comment: Option<String>, /// heading of the notification
// gist_public_id: String, pub heading: Option<String>,
// created: i64, /// message of the notification
//} pub message: Option<String>,
// /// when notification was received
//impl From<InnerGistComment> for GistComment { pub received: Option<OffsetDateTime>,
// fn from(g: InnerGistComment) -> Self { /// db assigned ID of the notification
// Self { pub id: Option<i32>,
// id: g.ID, }
// owner: g.owner,
// comment: g.comment.unwrap(), impl From<InnerNotification> for Notification {
// gist_public_id: g.gist_public_id, fn from(n: InnerNotification) -> Self {
// created: g.created, Notification {
// } name: n.name,
// } heading: n.heading,
//} message: n.message,
received: n.received.map(|t| t.unix_timestamp()),
id: n.id,
}
}
}

View File

@@ -0,0 +1,14 @@
-- 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
);

View File

@@ -33,6 +33,9 @@ async fn everyting_works() {
const CAPTCHA_SECRET: &str = "postgrescaptchasecret"; const CAPTCHA_SECRET: &str = "postgrescaptchasecret";
const CAPTCHA_DESCRIPTION: &str = "postgrescaptchadescription"; const CAPTCHA_DESCRIPTION: &str = "postgrescaptchadescription";
const CAPTCHA_DURATION: i32 = 30; const CAPTCHA_DURATION: i32 = 30;
// notification config
const HEADING: &str = "testing notifications get db postgres";
const MESSAGE: &str = "testing notifications get message db postgres";
// easy traffic pattern // easy traffic pattern
const TRAFFIC_PATTERN: TrafficPattern = TrafficPattern { const TRAFFIC_PATTERN: TrafficPattern = TrafficPattern {
@@ -56,6 +59,13 @@ async fn everyting_works() {
}, },
]; ];
const add_notification: AddNotification = AddNotification {
from: NAME,
to: NAME,
message: MESSAGE,
heading: HEADING,
};
let url = env::var("POSTGRES_DATABASE_URL").unwrap(); let url = env::var("POSTGRES_DATABASE_URL").unwrap();
let pool_options = PgPoolOptions::new().max_connections(2); let pool_options = PgPoolOptions::new().max_connections(2);
let connection_options = ConnectionOptions::Fresh(Fresh { pool_options, url }); let connection_options = ConnectionOptions::Fresh(Fresh { pool_options, url });
@@ -74,5 +84,5 @@ async fn everyting_works() {
key: CAPTCHA_SECRET, key: CAPTCHA_SECRET,
description: CAPTCHA_DESCRIPTION, description: CAPTCHA_DESCRIPTION,
}; };
database_works(&db, &p, &c, &LEVELS, &TRAFFIC_PATTERN).await; database_works(&db, &p, &c, &LEVELS, &TRAFFIC_PATTERN, &add_notification).await;
} }