#
mcaptcha/pages/panel/
utils.rs

    1// Copyright (C) 2024  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 crate::api::v1::stats::{percentile_bench_runner, PercentileReq, PercentileResp};
    11use crate::errors::PageResult;
    12use crate::pages::auth::sudo::SudoPage;
    13use crate::AppData;
    14
    15pub mod routes {
    16    pub struct Utils {
    17        pub percentile: &'static str,
    18    }
    19
    20    impl Utils {
    21        pub const fn new() -> Self {
    22            Utils {
    23                percentile: "/utils/percentile",
    24            }
    25        }
    26
    27        pub const fn get_sitemap() -> [&'static str; 1] {
    28            const S: Utils = Utils::new();
    29            [S.percentile]
    30        }
    31    }
    32}
    33
    34pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
    35    cfg.service(get_percentile);
    36    cfg.service(post_percentile);
    37}
    38
    39const PAGE: &str = "Difficulty factor statistics";
    40
    41#[derive(TemplateOnce, Clone)]
    42#[template(path = "panel/utils/percentile/index.html")]
    43pub struct PercentilePage {
    44    time: Option<u32>,
    45    percentile: Option<f64>,
    46    difficulty_factor: Option<u32>,
    47}
    48
    49#[my_codegen::get(
    50    path = "crate::PAGES.panel.utils.percentile",
    51    wrap = "crate::pages::get_middleware()"
    52)]
    53async fn get_percentile(id: Identity) -> PageResult<impl Responder> {
    54    let data = PercentilePage {
    55        time: None,
    56        percentile: None,
    57        difficulty_factor: None,
    58    };
    59
    60    let body = data.render_once().unwrap();
    61    Ok(HttpResponse::Ok()
    62        .content_type("text/html; charset=utf-8")
    63        .body(body))
    64}
    65
    66#[my_codegen::post(
    67    path = "crate::PAGES.panel.utils.percentile",
    68    wrap = "crate::pages::get_middleware()"
    69)]
    70async fn post_percentile(
    71    data: AppData,
    72    id: Identity,
    73    payload: web::Form<PercentileReq>,
    74) -> PageResult<impl Responder> {
    75    let resp = percentile_bench_runner(&data, &payload).await?;
    76    let page = PercentilePage {
    77        time: Some(payload.time),
    78        percentile: Some(payload.percentile),
    79        difficulty_factor: resp.difficulty_factor,
    80    };
    81
    82    let body = page.render_once().unwrap();
    83    Ok(HttpResponse::Ok()
    84        .content_type("text/html; charset=utf-8")
    85        .body(body))
    86}
    87
    88#[cfg(test)]
    89mod tests {
    90    use actix_web::{http::StatusCode, test, web::Bytes, App};
    91
    92    use super::*;
    93    use crate::api::v1::services;
    94    use crate::*;
    95
    96    #[actix_rt::test]
    97    async fn page_stats_bench_work_pg() {
    98        let data = crate::tests::pg::get_data().await;
    99        page_stats_bench_work(data).await;
    100    }
    101
    102    #[actix_rt::test]
    103    async fn page_stats_bench_work_maria() {
    104        let data = crate::tests::maria::get_data().await;
    105        page_stats_bench_work(data).await;
    106    }
    107
    108    async fn page_stats_bench_work(data: ArcData) {
    109        use crate::tests::*;
    110
    111        const NAME: &str = "pagebenchstatsuesr";
    112        const EMAIL: &str = "pagebenchstatsuesr@testadminuser.com";
    113        const PASSWORD: &str = "longpassword2";
    114
    115        const DEVICE_USER_PROVIDED: &str = "foo";
    116        const DEVICE_SOFTWARE_RECOGNISED: &str = "Foobar.v2";
    117        const THREADS: i32 = 4;
    118
    119        let data = &data;
    120        {
    121            delete_user(&data, NAME).await;
    122        }
    123
    124        register_and_signin(data, NAME, EMAIL, PASSWORD).await;
    125        // create captcha
    126        let (_, signin_resp, key) = add_levels_util(data, NAME, PASSWORD).await;
    127        let app = get_app!(data).await;
    128        let cookies = get_cookie!(signin_resp);
    129
    130        let page = 1;
    131        let tmp_id = uuid::Uuid::new_v4();
    132        let download_rotue = V1_API_ROUTES
    133            .survey
    134            .get_download_route(&tmp_id.to_string(), page);
    135
    136        let download_req = test::call_service(
    137            &app,
    138            test::TestRequest::get().uri(&download_rotue).to_request(),
    139        )
    140        .await;
    141        assert_eq!(download_req.status(), StatusCode::NOT_FOUND);
    142
    143        data.db
    144            .analytics_create_psuedo_id_if_not_exists(&key.key)
    145            .await
    146            .unwrap();
    147
    148        let psuedo_id = data
    149            .db
    150            .analytics_get_psuedo_id_from_capmaign_id(&key.key)
    151            .await
    152            .unwrap();
    153
    154        for i in 1..6 {
    155            println!("[{i}] Saving analytics");
    156            let analytics = db_core::CreatePerformanceAnalytics {
    157                time: i,
    158                difficulty_factor: i,
    159                worker_type: "wasm".into(),
    160            };
    161            data.db.analysis_save(&key.key, &analytics).await.unwrap();
    162        }
    163
    164        let msg = PercentileReq {
    165            time: 1,
    166            percentile: 99.00,
    167        };
    168        let resp = test::call_service(
    169            &app,
    170            post_request!(&msg, V1_API_ROUTES.stats.percentile_benches).to_request(),
    171        )
    172        .await;
    173        assert_eq!(resp.status(), StatusCode::OK);
    174        let resp: PercentileResp = test::read_body_json(resp).await;
    175
    176        assert!(resp.difficulty_factor.is_none());
    177
    178        let msg = PercentileReq {
    179            time: 1,
    180            percentile: 100.00,
    181        };
    182
    183        let resp = test::call_service(
    184            &app,
    185            post_request!(&msg, V1_API_ROUTES.stats.percentile_benches).to_request(),
    186        )
    187        .await;
    188        assert_eq!(resp.status(), StatusCode::OK);
    189        let resp: PercentileResp = test::read_body_json(resp).await;
    190
    191        // start
    192        let percentile_resp = test::call_service(
    193            &app,
    194            test::TestRequest::get()
    195                .uri(&crate::PAGES.panel.utils.percentile)
    196                .cookie(cookies.clone())
    197                .to_request(),
    198        )
    199        .await;
    200
    201        assert_eq!(percentile_resp.status(), StatusCode::OK);
    202
    203        let body: Bytes = test::read_body(percentile_resp).await;
    204        let body = String::from_utf8(body.to_vec()).unwrap();
    205
    206        assert!(body.contains("Maximum time taken"));
    207
    208        let percentile_resp = test::call_service(
    209            &app,
    210            test::TestRequest::get()
    211                .uri(&crate::PAGES.panel.utils.percentile)
    212                .cookie(cookies.clone())
    213                .to_request(),
    214        )
    215        .await;
    216
    217        assert_eq!(percentile_resp.status(), StatusCode::OK);
    218
    219        let body: Bytes = test::read_body(percentile_resp).await;
    220        let body = String::from_utf8(body.to_vec()).unwrap();
    221
    222        assert!(body.contains("Maximum time taken"));
    223
    224        // end
    225        // start post
    226
    227        let msg = PercentileReq {
    228            time: 1,
    229            percentile: 99.00,
    230        };
    231
    232        let percentile_resp = test::call_service(
    233            &app,
    234            test::TestRequest::post()
    235                .uri(&crate::PAGES.panel.utils.percentile)
    236                .set_form(&msg)
    237                .cookie(cookies.clone())
    238                .to_request(),
    239        )
    240        .await;
    241
    242        assert_eq!(percentile_resp.status(), StatusCode::OK);
    243
    244        let body: Bytes = test::read_body(percentile_resp).await;
    245        let body = String::from_utf8(body.to_vec()).unwrap();
    246
    247        assert!(body.contains(
    248            "Not enough inputs to compute statistics. Please try again later"
    249        ));
    250        assert!(body.contains(&1.to_string()));
    251        assert!(body.contains(&99.00.to_string()));
    252        // end post
    253
    254        // start post
    255
    256        let msg = PercentileReq {
    257            time: 2,
    258            percentile: 100.00,
    259        };
    260
    261        let percentile_resp = test::call_service(
    262            &app,
    263            test::TestRequest::post()
    264                .uri(&crate::PAGES.panel.utils.percentile)
    265                .set_form(&msg)
    266                .cookie(cookies.clone())
    267                .to_request(),
    268        )
    269        .await;
    270
    271        assert_eq!(percentile_resp.status(), StatusCode::OK);
    272
    273        let body: Bytes = test::read_body(percentile_resp).await;
    274        let body = String::from_utf8(body.to_vec()).unwrap();
    275
    276        assert!(body.contains("Difficulty factor: 2"));
    277        assert!(body.contains(&2.to_string()));
    278        assert!(body.contains(&100.00.to_string()));
    279    }
    280}