diff --git a/sqlx-data.json b/sqlx-data.json index 493263c9..b5bd189d 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -107,6 +107,21 @@ ] } }, + "45d9e9fb6344fe3a18c2529d50c935d3837bfe25c96595beb6970d6067720578": { + "query": "insert into mcaptcha_users \n (name , password, email, secret) values ($1, $2, $3, $4)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Text", + "Varchar", + "Varchar" + ] + }, + "nullable": [] + } + }, "47fa50aecfb1499b0a18fa9299643017a1a8d69d4e9980032e0d8f745465d14f": { "query": "SELECT EXISTS (SELECT 1 from mcaptcha_users WHERE email = $1)", "describe": { @@ -506,21 +521,6 @@ "nullable": [] } }, - "d64ed8a42ff8d8ff0db5a409c9d2ea7d61ea43c90e548a29a3a5a47679dbcd4b": { - "query": "INSERT INTO mcaptcha_users \n (name , password, email, secret) VALUES ($1, $2, $3, $4)", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Varchar", - "Text", - "Varchar", - "Varchar" - ] - }, - "nullable": [] - } - }, "d9a097cba4552c17b410fcb8745dd9b2eae5146f7b710006a50ae6aa2add54fa": { "query": "SELECT difficulty_factor, visitor_threshold FROM mcaptcha_levels WHERE\n config_id = (\n SELECT config_id FROM mcaptcha_config WHERE key = ($1)\n );", "describe": { diff --git a/src/api/v1/auth.rs b/src/api/v1/auth.rs index eae1a951..42648989 100644 --- a/src/api/v1/auth.rs +++ b/src/api/v1/auth.rs @@ -154,8 +154,8 @@ pub mod runners { let res; if let Some(email) = &payload.email { res = sqlx::query!( - "INSERT INTO mcaptcha_users - (name , password, email, secret) VALUES ($1, $2, $3, $4)", + "insert into mcaptcha_users + (name , password, email, secret) values ($1, $2, $3, $4)", &username, &hash, &email, @@ -182,7 +182,7 @@ pub mod runners { if msg.contains("mcaptcha_users_name_key") { return Err(ServiceError::UsernameTaken); } else if msg.contains("mcaptcha_users_email_key") { - return Err(ServiceError::EmailTaken); + return Err(ServiceError::UsernameTaken); } else if msg.contains("mcaptcha_users_secret_key") { continue; } else { diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index c16636e3..ca928567 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -21,7 +21,7 @@ pub mod account; pub mod auth; pub mod mcaptcha; pub mod meta; -mod notifications; +pub mod notifications; pub mod pow; mod routes; diff --git a/src/api/v1/notifications/get.rs b/src/api/v1/notifications/get.rs index 69c46a8c..91ad991d 100644 --- a/src/api/v1/notifications/get.rs +++ b/src/api/v1/notifications/get.rs @@ -63,25 +63,39 @@ pub async fn get_notification( let receiver = id.identity().unwrap(); // TODO handle error where payload.to doesnt exist - let mut notifications = sqlx::query_file_as!( - Notification, - "src/api/v1/notifications/get_all_unread.sql", - &receiver - ) - .fetch_all(&data.db) - .await?; - - let resp: Vec = notifications - .drain(0..) - .map(|x| { - let y: NotificationResp = x.into(); - y - }) - .collect(); + let resp = runner::get_notification(&data, &receiver).await?; Ok(HttpResponse::Ok().json(resp)) } +pub mod runner { + use super::*; + pub async fn get_notification( + data: &AppData, + receiver: &str, + ) -> ServiceResult> { + // TODO handle error where payload.to doesnt exist + + let mut notifications = sqlx::query_file_as!( + Notification, + "src/api/v1/notifications/get_all_unread.sql", + &receiver + ) + .fetch_all(&data.db) + .await?; + + let resp = notifications + .drain(0..) + .map(|x| { + let y: NotificationResp = x.into(); + y + }) + .collect(); + + Ok(resp) + } +} + #[cfg(test)] mod tests { use actix_web::http::{header, StatusCode}; diff --git a/src/api/v1/notifications/mod.rs b/src/api/v1/notifications/mod.rs index 0d09ec48..6db29dc5 100644 --- a/src/api/v1/notifications/mod.rs +++ b/src/api/v1/notifications/mod.rs @@ -15,9 +15,9 @@ * along with this program. If not, see . */ -mod add; -mod get; -mod mark_read; +pub mod add; +pub mod get; +pub mod mark_read; pub mod routes { diff --git a/src/api/v1/tests/auth.rs b/src/api/v1/tests/auth.rs index 021a53f5..e4df6475 100644 --- a/src/api/v1/tests/auth.rs +++ b/src/api/v1/tests/auth.rs @@ -44,11 +44,9 @@ async fn auth_works() { confirm_password: PASSWORD.into(), email: None, }; - let resp = test::call_service( - &app, - post_request!(&msg, ROUTES.auth.register).to_request(), - ) - .await; + let resp = + test::call_service(&app, post_request!(&msg, ROUTES.auth.register).to_request()) + .await; assert_eq!(resp.status(), StatusCode::OK); // delete user delete_user(NAME, &data).await; diff --git a/src/data.rs b/src/data.rs index bc998d38..a73e5b33 100644 --- a/src/data.rs +++ b/src/data.rs @@ -143,17 +143,19 @@ pub struct Data { } impl Data { - #[cfg(not(tarpaulin_include))] - /// create new instance of app data - pub async fn new() -> Arc { - let creds = ConfigBuilder::default() + pub fn get_creds() -> Config { + ConfigBuilder::default() .username_case_mapped(true) .profanity(true) .blacklist(true) .password_policy(PasswordPolicy::default()) .build() - .unwrap(); - + .unwrap() + } + #[cfg(not(tarpaulin_include))] + /// create new instance of app data + pub async fn new() -> Arc { + let creds = Self::get_creds(); let c = creds.clone(); let init = thread::spawn(move || { diff --git a/src/docs.rs b/src/docs.rs index 1a621a37..8496ef95 100644 --- a/src/docs.rs +++ b/src/docs.rs @@ -123,11 +123,9 @@ mod tests { let uri = format!("{}{}", DOCS.home, FILE); - let resp = test::call_service( - &app, - test::TestRequest::get().uri(&uri).to_request(), - ) - .await; + let resp = + test::call_service(&app, test::TestRequest::get().uri(&uri).to_request()) + .await; assert_eq!(resp.status(), StatusCode::OK); } } diff --git a/src/pages/mod.rs b/src/pages/mod.rs index 149bd8b1..11dedc09 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -60,14 +60,13 @@ mod tests { PAGES.home, PAGES.panel.sitekey.add, PAGES.panel.sitekey.list, + PAGES.panel.notifications, ]; for url in urls.iter() { - let resp = test::call_service( - &app, - test::TestRequest::get().uri(url).to_request(), - ) - .await; + let resp = + test::call_service(&app, test::TestRequest::get().uri(url).to_request()) + .await; assert_eq!(resp.status(), StatusCode::FOUND); let authenticated_resp = test::call_service( @@ -91,11 +90,9 @@ mod tests { let urls = vec![PAGES.auth.login, PAGES.auth.join]; for url in urls.iter() { - let resp = test::call_service( - &app, - test::TestRequest::get().uri(url).to_request(), - ) - .await; + let resp = + test::call_service(&app, test::TestRequest::get().uri(url).to_request()) + .await; assert_eq!(resp.status(), StatusCode::OK); } diff --git a/src/pages/panel/mod.rs b/src/pages/panel/mod.rs index 28514e9b..2a74ecdb 100644 --- a/src/pages/panel/mod.rs +++ b/src/pages/panel/mod.rs @@ -19,6 +19,7 @@ use actix_identity::Identity; use actix_web::{HttpResponse, Responder}; use sailfish::TemplateOnce; +mod notifications; pub mod sitekey; use crate::errors::PageResult; @@ -51,6 +52,7 @@ async fn panel(data: AppData, id: Identity) -> PageResult { pub fn services(cfg: &mut actix_web::web::ServiceConfig) { cfg.service(panel); sitekey::services(cfg); + cfg.service(notifications::notifications); } pub mod routes { @@ -58,6 +60,7 @@ pub mod routes { pub struct Panel { pub home: &'static str, pub sitekey: Sitekey, + pub notifications: &'static str, } impl Panel { @@ -65,6 +68,7 @@ pub mod routes { Panel { home: "/", sitekey: Sitekey::new(), + notifications: "/notifications", } } } diff --git a/src/pages/panel/notifications.rs b/src/pages/panel/notifications.rs new file mode 100644 index 00000000..abeac243 --- /dev/null +++ b/src/pages/panel/notifications.rs @@ -0,0 +1,52 @@ +/* +* Copyright (C) 2021 Aravinth Manivannan +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +*/ + +use actix_identity::Identity; +use actix_web::{HttpResponse, Responder}; +use sailfish::TemplateOnce; + +use crate::api::v1::notifications::get::{runner, NotificationResp}; +use crate::errors::PageResult; +use crate::AppData; + +#[derive(TemplateOnce)] +#[template(path = "panel/notifications/index.html")] +pub struct IndexPage { + /// notifications + n: Vec, +} + +impl IndexPage { + fn new(n: Vec) -> Self { + IndexPage { n } + } +} + +const PAGE: &str = "Notifications"; + +#[my_codegen::get(path = "crate::PAGES.panel.notifications", wrap = "crate::CheckLogin")] +pub async fn notifications(data: AppData, id: Identity) -> PageResult { + let receiver = id.identity().unwrap(); + // TODO handle error where payload.to doesnt exist + + let notifications = runner::get_notification(&data, &receiver).await?; + + let body = IndexPage::new(notifications).render_once().unwrap(); + Ok(HttpResponse::Ok() + .content_type("text/html; charset=utf-8") + .body(body)) +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index b217b46e..55e5bbbc 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -51,11 +51,9 @@ macro_rules! post_request { #[macro_export] macro_rules! get_works { ($app:expr,$route:expr ) => { - let list_sitekey_resp = test::call_service( - &$app, - test::TestRequest::get().uri($route).to_request(), - ) - .await; + let list_sitekey_resp = + test::call_service(&$app, test::TestRequest::get().uri($route).to_request()) + .await; assert_eq!(list_sitekey_resp.status(), StatusCode::OK); }; } @@ -116,11 +114,9 @@ pub async fn register(name: &str, email: &str, password: &str) { confirm_password: password.into(), email: Some(email.into()), }; - let resp = test::call_service( - &app, - post_request!(&msg, ROUTES.auth.register).to_request(), - ) - .await; + let resp = + test::call_service(&app, post_request!(&msg, ROUTES.auth.register).to_request()) + .await; assert_eq!(resp.status(), StatusCode::OK); } @@ -134,11 +130,9 @@ pub async fn signin(name: &str, password: &str) -> (Arc, Login, ServiceRes login: name.into(), password: password.into(), }; - let signin_resp = test::call_service( - &app, - post_request!(&creds, ROUTES.auth.login).to_request(), - ) - .await; + let signin_resp = + test::call_service(&app, post_request!(&creds, ROUTES.auth.login).to_request()) + .await; assert_eq!(signin_resp.status(), StatusCode::OK); (data, creds, signin_resp) } diff --git a/templates/panel/header/taskbar/index.html b/templates/panel/header/taskbar/index.html index 0c377572..420002be 100644 --- a/templates/panel/header/taskbar/index.html +++ b/templates/panel/header/taskbar/index.html @@ -16,9 +16,11 @@
  • + " alt="Notifications" /> +
  • diff --git a/templates/panel/notifications/index.html b/templates/panel/notifications/index.html new file mode 100644 index 00000000..147d7958 --- /dev/null +++ b/templates/panel/notifications/index.html @@ -0,0 +1,24 @@ +<. include!("../../components/headers/index.html"); .> +<. include!("../navbar/index.html"); .> +
    +<. include!("../header/index.html"); .> + +
    + +
    + + +
      +

      Your Notifications

      + <. for notification in n.iter() { .> +
    • +

      <.= notification.heading .>

      +

      From: <.= notification.name .>

      +

      Received: <.= notification.received .>

      +

      Message: <.= notification.message .>

      + <. } .> +
    + +
    + +<. include!("../../components/footers.html"); .>