diff --git a/migrations/20210224174945_notifications.sql b/migrations/20210224174945_notifications.sql index a8ea8efe..33f53540 100644 --- a/migrations/20210224174945_notifications.sql +++ b/migrations/20210224174945_notifications.sql @@ -13,5 +13,6 @@ CREATE TABLE notifications_actions ( id serial PRIMARY KEY, notification_id bigint REFERENCES notifications NOT NULL, title varchar(255) NOT NULL, - action_route varchar(2048) NOT NULL + action_route varchar(2048) NOT NULL, + action_route_method varchar(32) NOT NULL ); \ No newline at end of file diff --git a/sqlx-data.json b/sqlx-data.json index 8ae4aafc..b2874afc 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -248,62 +248,6 @@ ] } }, - "105a0184a875e7b9c5aa38527816bace9d9136ffc22627a1695ca337bf7009dd": { - "query": "\n SELECT n.user_id, n.title, n.text, n.link, n.created, n.read,\n STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route, ' ,') actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.id = $1\n GROUP BY n.id, n.user_id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "user_id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "text", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "link", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "read", - "type_info": "Bool" - }, - { - "ordinal": 6, - "name": "actions", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - null - ] - } - }, "1220d15a56dbf823eaa452fbafa17442ab0568bc81a31fa38e16e3df3278e5f9": { "query": "SELECT EXISTS(SELECT 1 FROM users WHERE id = $1)", "describe": { @@ -362,6 +306,68 @@ "nullable": [] } }, + "16c4d33d4cffa54333e0c56a1cf35ceab2596773ac5c77d42daaacc04a75f404": { + "query": "\n SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read,\n STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method, ' ,') actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.user_id = $1\n GROUP BY n.id, n.user_id;\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "user_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "text", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "link", + "type_info": "Varchar" + }, + { + "ordinal": 5, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "read", + "type_info": "Bool" + }, + { + "ordinal": 7, + "name": "actions", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + null + ] + } + }, "17e6d30c3693e9bd9f772f3dc4e2eafe75fdeecfdcf2746eac641f77ced6b8a8": { "query": "\n SELECT u.id, u.github_id, u.name, u.email,\n u.avatar_url, u.username, u.bio,\n u.created, u.role FROM users u\n WHERE u.id IN (SELECT * FROM UNNEST($1::bigint[]))\n ", "describe": { @@ -2072,68 +2078,6 @@ ] } }, - "64b2c8a208eaef033bf555c4a4962746d2c3706d24ae60e67a8b732c9a4b0edc": { - "query": "\n SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read,\n STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route, ' ,') actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.user_id = $1\n GROUP BY n.id, n.user_id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "user_id", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "text", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "link", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 6, - "name": "read", - "type_info": "Bool" - }, - { - "ordinal": 7, - "name": "actions", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - null - ] - } - }, "6612afe698ec5ad3a9a98294d12fa5b04ccfeac4b31365b3821ac8e2ae6c5768": { "query": "\n SELECT m.id id, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name,\n STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions\n FROM mods m\n LEFT OUTER JOIN mods_categories mc ON joining_mod_id = m.id\n LEFT OUTER JOIN categories c ON mc.joining_category_id = c.id\n LEFT OUTER JOIN versions v ON v.mod_id = m.id\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n WHERE m.id = $1\n GROUP BY m.id, s.id, cs.id, ss.id, l.id;\n ", "describe": { @@ -2550,6 +2494,68 @@ ] } }, + "73ab32d116e2785332f9c671a61b0173cede5db03ed40b971162283c21b0e9b9": { + "query": "\n SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read,\n STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method, ' ,') actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.id IN (SELECT * FROM UNNEST($1::bigint[]))\n GROUP BY n.id, n.user_id;\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "user_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "text", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "link", + "type_info": "Varchar" + }, + { + "ordinal": 5, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "read", + "type_info": "Bool" + }, + { + "ordinal": 7, + "name": "actions", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8Array" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + null + ] + } + }, "73bdd6c9e7cd8c1ed582261aebdee0f8fd2734e712ef288a2608564c918009cb": { "query": "\n DELETE FROM versions WHERE id = $1\n ", "describe": { @@ -2876,6 +2882,62 @@ ] } }, + "8e80037fa07a2632ea39f0bd38f04fee827c76b043b4c80391bb5c7510a8efb8": { + "query": "\n SELECT n.user_id, n.title, n.text, n.link, n.created, n.read,\n STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method, ' ,') actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.id = $1\n GROUP BY n.id, n.user_id;\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "user_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "text", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "link", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "read", + "type_info": "Bool" + }, + { + "ordinal": 6, + "name": "actions", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + null + ] + } + }, "8f02d5c2b9095c21498802f01cefdbc57a5f1c2a7aee717ba19daaffc498c5cd": { "query": "\n SELECT title, description, downloads, follows,\n icon_url, body, body_url, published,\n updated, status,\n issues_url, source_url, wiki_url, discord_url, license_url,\n team_id, client_side, server_side, license, slug\n FROM mods\n WHERE id = $1\n ", "describe": { @@ -3524,68 +3586,6 @@ "nullable": [] } }, - "b6d377746ceeb0e52ed55255fb294cfce4873739e3277a79038bcaf1e9796c68": { - "query": "\n SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read,\n STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route, ' ,') actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.id IN (SELECT * FROM UNNEST($1::bigint[]))\n GROUP BY n.id, n.user_id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "user_id", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "text", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "link", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 6, - "name": "read", - "type_info": "Bool" - }, - { - "ordinal": 7, - "name": "actions", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8Array" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - null - ] - } - }, "b7b2b5b99340c7601de53cc33dc56af054b50b2fe4d1d212901c958115a42baa": { "query": "\n UPDATE versions\n SET author_id = $1\n WHERE (author_id = $2)\n ", "describe": { diff --git a/src/database/models/notification_item.rs b/src/database/models/notification_item.rs index 3a0c7fc5..d4a0369c 100644 --- a/src/database/models/notification_item.rs +++ b/src/database/models/notification_item.rs @@ -10,7 +10,7 @@ pub struct NotificationBuilder { pub struct NotificationActionBuilder { pub title: String, - pub action_route: String, + pub action_route: (String, String), } pub struct Notification { @@ -28,6 +28,7 @@ pub struct NotificationAction { pub id: NotificationActionId, pub notification_id: NotificationId, pub title: String, + pub action_route_method: String, pub action_route: String, } @@ -55,7 +56,8 @@ impl NotificationBuilder { id: NotificationActionId(0), notification_id: id, title: action.title.clone(), - action_route: action.action_route.clone(), + action_route_method: action.action_route.0.clone(), + action_route: action.action_route.1.clone(), }) } @@ -117,7 +119,7 @@ impl Notification { let result = sqlx::query!( " SELECT n.user_id, n.title, n.text, n.link, n.created, n.read, - STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route, ' ,') actions + STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method, ' ,') actions FROM notifications n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id WHERE n.id = $1 @@ -139,6 +141,7 @@ impl Notification { id: NotificationActionId(action[0].parse().unwrap_or(0)), notification_id: id, title: action[1].to_string(), + action_route_method: action[3].to_string(), action_route: action[2].to_string(), }); } @@ -172,7 +175,7 @@ impl Notification { sqlx::query!( " SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read, - STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route, ' ,') actions + STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method, ' ,') actions FROM notifications n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id WHERE n.id IN (SELECT * FROM UNNEST($1::bigint[])) @@ -194,6 +197,7 @@ impl Notification { id: NotificationActionId(action[0].parse().unwrap_or(0)), notification_id: id, title: action[1].to_string(), + action_route_method: action[3].to_string(), action_route: action[2].to_string(), }); } @@ -227,7 +231,7 @@ impl Notification { sqlx::query!( " SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read, - STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route, ' ,') actions + STRING_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method, ' ,') actions FROM notifications n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id WHERE n.user_id = $1 @@ -249,6 +253,7 @@ impl Notification { id: NotificationActionId(action[0].parse().unwrap_or(0)), notification_id: id, title: action[1].to_string(), + action_route_method: action[3].to_string(), action_route: action[2].to_string(), }); } diff --git a/src/main.rs b/src/main.rs index d411c261..92981bf5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -307,7 +307,8 @@ async fn main() -> std::io::Result<()> { .configure(routes::teams_config) .configure(routes::users_config) .configure(routes::moderation_config) - .configure(routes::reports_config), + .configure(routes::reports_config) + .configure(routes::notifications_config), ) .default_service(web::get().to(routes::not_found)) }) diff --git a/src/models/notifications.rs b/src/models/notifications.rs index 8e5688ff..a768e8b1 100644 --- a/src/models/notifications.rs +++ b/src/models/notifications.rs @@ -23,5 +23,6 @@ pub struct Notification { #[derive(Serialize, Deserialize)] pub struct NotificationAction { pub title: String, - pub action_route: String, + /// The route to call when this notification action is called. Formatted HTTP Method, route + pub action_route: (String, String), } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index c3c89491..3b44067e 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -33,6 +33,8 @@ pub fn mods_config(cfg: &mut web::ServiceConfig) { .service(mods::mod_delete) .service(mods::mod_edit) .service(mods::mod_icon_edit) + .service(mods::mod_follow) + .service(mods::mod_unfollow) .service(web::scope("{mod_id}").service(versions::version_list)), ); } @@ -66,7 +68,8 @@ pub fn users_config(cfg: &mut web::ServiceConfig) { .service(users::mods_list) .service(users::user_delete) .service(users::user_edit) - .service(users::user_icon_edit), + .service(users::user_icon_edit) + .service(users::user_follows), ); } @@ -81,6 +84,16 @@ pub fn teams_config(cfg: &mut web::ServiceConfig) { ); } +pub fn notifications_config(cfg: &mut web::ServiceConfig) { + cfg.service(notifications::notifications_get); + + cfg.service( + web::scope("notification") + .service(notifications::notification_get) + .service(notifications::notification_delete), + ); +} + pub fn moderation_config(cfg: &mut web::ServiceConfig) { cfg.service(web::scope("moderation").service(moderation::mods)); } diff --git a/src/routes/notifications.rs b/src/routes/notifications.rs index 753dcf05..faea1e00 100644 --- a/src/routes/notifications.rs +++ b/src/routes/notifications.rs @@ -83,7 +83,7 @@ pub fn convert_notification( .into_iter() .map(|x| NotificationAction { title: x.title, - action_route: x.action_route, + action_route: (x.action_route_method, x.action_route), }) .collect(), } diff --git a/src/routes/teams.rs b/src/routes/teams.rs index 43c2d435..9c240d8c 100644 --- a/src/routes/teams.rs +++ b/src/routes/teams.rs @@ -220,11 +220,14 @@ pub async fn add_team_member( actions: vec![ NotificationActionBuilder { title: "Accept".to_string(), - action_route: format!("team/{}/join", team), + action_route: ("POST".to_string(), format!("team/{}/join", team)), }, NotificationActionBuilder { title: "Deny".to_string(), - action_route: format!("team/{}/members/{}", team, new_member.user_id), + action_route: ( + "DELETE".to_string(), + format!("team/{}/members/{}", team, new_member.user_id), + ), }, ], } diff --git a/src/routes/versions.rs b/src/routes/versions.rs index 0f217a26..416b62cd 100644 --- a/src/routes/versions.rs +++ b/src/routes/versions.rs @@ -81,6 +81,12 @@ pub async fn version_list( .map(|version| response.push(convert_version(version.clone()))) .unwrap_or(()); }); + + if response.is_empty() { + versions + .into_iter() + .for_each(|version| response.push(convert_version(version.clone()))); + } } response.sort_by(|a, b| b.date_published.cmp(&a.date_published));