mcaptcha/pages/panel/sitekey/
view.rs

1// Copyright (C) 2022  Aravinth Manivannan <realaravinth@batsense.net>
2// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6use actix_identity::Identity;
7use actix_web::{web, HttpResponse, Responder};
8use sailfish::TemplateOnce;
9
10use db_core::Captcha;
11use libmcaptcha::defense::Level;
12
13use crate::errors::*;
14use crate::stats::CaptchaStats;
15use crate::AppData;
16
17const PAGE: &str = "SiteKeys";
18
19#[derive(TemplateOnce, Clone)]
20#[template(path = "panel/sitekey/view/index.html")]
21struct IndexPage {
22    duration: u32,
23    name: String,
24    key: String,
25    levels: Vec<Level>,
26    stats: CaptchaStats,
27    publish_benchmarks: bool,
28}
29
30impl IndexPage {
31    fn new(
32        stats: CaptchaStats,
33        config: Captcha,
34        levels: Vec<Level>,
35        key: String,
36        publish_benchmarks: bool,
37    ) -> Self {
38        IndexPage {
39            duration: config.duration as u32,
40            name: config.description,
41            levels,
42            key,
43            stats,
44            publish_benchmarks,
45        }
46    }
47}
48
49/// route handler that renders individual views for sitekeys
50#[my_codegen::get(
51    path = "crate::PAGES.panel.sitekey.view",
52    wrap = "crate::pages::get_middleware()"
53)]
54pub async fn view_sitekey(
55    path: web::Path<String>,
56    data: AppData,
57    id: Identity,
58) -> PageResult<impl Responder> {
59    let username = id.identity().unwrap();
60    let key = path.into_inner();
61    let config = data.db.get_captcha_config(&username, &key).await?;
62    let levels = data.db.get_captcha_levels(Some(&username), &key).await?;
63    let stats = data.stats.fetch(&data, &username, &key).await?;
64    let publish_benchmarks = data.db.analytics_captcha_is_published(&key).await?;
65
66    let body = IndexPage::new(stats, config, levels, key, publish_benchmarks)
67        .render_once()
68        .unwrap();
69    Ok(HttpResponse::Ok()
70        .content_type("text/html; charset=utf-8")
71        .body(body))
72}
73
74#[cfg(test)]
75mod test {
76    use actix_web::http::StatusCode;
77    use actix_web::test;
78    use actix_web::web::Bytes;
79
80    use crate::tests::*;
81    use crate::*;
82
83    #[actix_rt::test]
84    async fn view_sitekey_work_pg_test() {
85        let data = pg::get_data().await;
86        view_sitekey_work(data).await;
87    }
88
89    #[actix_rt::test]
90    async fn view_sitekey_work_maria_test() {
91        let data = maria::get_data().await;
92        view_sitekey_work(data).await;
93    }
94
95    async fn view_sitekey_work(data: ArcData) {
96        const NAME: &str = "viewsitekeyuser";
97        const PASSWORD: &str = "longpassworddomain";
98        const EMAIL: &str = "viewsitekeyuser@a.com";
99
100        let data = &data;
101        delete_user(data, NAME).await;
102
103        register_and_signin(data, NAME, EMAIL, PASSWORD).await;
104        let (_, signin_resp, key) = add_levels_util(data, NAME, PASSWORD).await;
105        let cookies = get_cookie!(signin_resp);
106
107        let app = get_app!(data).await;
108
109        let url = format!("/sitekey/{}/", &key.key);
110
111        let list_sitekey_resp = test::call_service(
112            &app,
113            test::TestRequest::get()
114                .uri(&url)
115                .cookie(cookies.clone())
116                .to_request(),
117        )
118        .await;
119
120        assert_eq!(list_sitekey_resp.status(), StatusCode::OK);
121
122        let body: Bytes = test::read_body(list_sitekey_resp).await;
123        let body = String::from_utf8(body.to_vec()).unwrap();
124
125        assert!(body.contains(&key.name));
126
127        assert!(body.contains(&L1.visitor_threshold.to_string()));
128        assert!(body.contains(&L1.difficulty_factor.to_string()));
129        assert!(body.contains(&L2.difficulty_factor.to_string()));
130        assert!(body.contains(&L2.visitor_threshold.to_string()));
131    }
132}