Implement query for delegation

O01eg
Oct 22, 2022, 3:07 PM
JG2BQCRDWKCGVC56DCRBFCOXPHGT33LJ4FHWLIPOM64W6343D7CQC

Dependencies

  • [2] YDWTHWAI Show form to revoke delegation
  • [3] D3RL62X5 Implement revoking delegation
  • [4] LTQCLSBU Split database usage in pages
  • [5] NY766BOQ Accept form to add player
  • [6] 5RQCVFRH Start leave game form
  • [7] OJO4B4QO Add login form and empty handler
  • [8] DNFB7TNI Add new pages and links to slow games and reset game password
  • [9] WW3KRXX6 Add page for reset game password
  • [10] WVHXYKCV Add postgresql pools
  • [11] HZDCKIXQ Use constants for templates
  • [12] EVP2FSBH Split index page
  • [13] 6NYILMKI Add page for slow game
  • [*] B7PYGLH3 Show delegate bold if it's logged user itself
  • [*] 6BDGQ4VM Show player names for registered players
  • [*] TEB4R7OU Add form to join game
  • [*] 4MZ4VIR7 Initial commit
  • [*] IXY6NZLM Start to use migrations files for PostgreSQL database

Change contents

  • edit in src/templates/slow-game.html at line 80
    [15.680]
    [15.680]
    {{/if}}
    {{#if player.query_delegate_data}}
    <form id="query-delegate-{{ player.query_delegate_data.csrf }}" action="query-delegate.do" method="post">
    <fieldset>
    <label for="delegate_name">Delegate name:</label>
    <input name="delegate_name" id="delegate_name-{{ player.query_delegate_data.csrf }}" type="text" placeholder="Username" required />
    <input name="csrf" type="hidden" value="{{ player.query_delegate_data.csrf }}">
    <input name="submit" type="submit" value="Query Delegate">
    </fieldset>
    </form>
  • edit in src/pages/slow_game.rs at line 17
    [2.103]
    [16.207]
    query_delegate_data: Option<JoinLeaveData>,
  • edit in src/pages/slow_game.rs at line 22
    [4.272]
    [17.269]
    csrf: Uuid,
    }
    #[derive(serde_derive::Deserialize)]
    pub struct QueryDelegationData {
  • edit in src/pages/slow_game.rs at line 28
    [17.285]
    [17.285]
    delegate_name: String,
  • edit in src/pages/slow_game.rs at line 192
    [2.1667]
    [16.253]
    let query_delegate_data = if status.map_or(true, |x| x == "started")
    && player_itself
    && delegate_name.is_none()
    {
    let csrf = Uuid::new_v4();
    let mut cache = data.cache_query_delegation_game.lock().await;
    cache.insert(
    csrf,
    (gameuid.clone(), user.to_lowercase()),
    std::time::Duration::from_secs(data.cache_duration_sec),
    );
    Some(JoinLeaveData { csrf })
    } else {
    None
    };
  • edit in src/pages/slow_game.rs at line 213
    [2.1767]
    [16.343]
    query_delegate_data,
  • edit in src/pages/slow_game.rs at line 467
    [3.2140]
    [3.2140]
    }
    HttpResponse::Found()
    .append_header((
    header::LOCATION,
    format!("slow-game-{}.html", cached_data.0),
    ))
    .finish()
    }
    pub async fn post_query_delegate(
    request: HttpRequest,
    form: web::Form<QueryDelegationData>,
    data: web::Data<WebData<'_>>,
    data_rw: web::Data<DataBaseRw>,
    ) -> HttpResponse {
    let cached_data = {
    let mut cache = data.cache_query_delegation_game.lock().await;
    cache.remove(&form.csrf)
    };
    let cached_data = if let Some(cd) = cached_data {
    cd
    } else {
    log::warn!("Unknown data for CSRF: {}", form.csrf);
    return HttpResponse::BadRequest().body("Incorrect");
    };
    let jar = request_to_jar(request);
    if jar
    .private(&data.cookies_key)
    .get("auth")
    .map_or(true, |x| x.value().to_lowercase() != cached_data.1)
    {
    log::warn!("Incorrect user");
    return HttpResponse::BadRequest().body("Incorrect");
  • edit in src/pages/slow_game.rs at line 505
    [3.2147]
    [3.2147]
    let dbclient_rw = match data_rw.0.get().await {
    Ok(c) => c,
    Err(e) => {
    log::error!("Pool RW error {}", e);
    return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
    }
    };
    let stmt = match dbclient_rw
    .prepare("insert into games.query_delegation (game_uid, player_name, delegate_name) values ($1, $2, $3) on conflict do nothing;")
    .await
    {
    Ok(stmt) => stmt,
    Err(e) => {
    log::error!("Pool RW statement error {}", e);
    return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
    }
    };
    match dbclient_rw
    .execute(
    &stmt,
    &[&cached_data.0, &cached_data.1, &form.delegate_name],
    )
    .await
    {
    Ok(_) => (),
    Err(e) => {
    log::error!("Pool RW execute insert error {}", e);
    return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
    }
    };
  • edit in src/pages/mod.rs at line 50
    [4.1643]
    [2.1815]
    pub cache_query_delegation_game: Mutex<TtlCache<Uuid, (String, String)>>,
  • replacement in src/main.rs at line 22
    [4.1187][3.2317:2407]()
    use pages::slow_game::{post_join_game, post_leave_game, post_revoke_delegate, slow_game};
    [4.1187]
    [4.2243]
    use pages::slow_game::{
    post_join_game, post_leave_game, post_query_delegate, post_revoke_delegate, slow_game,
    };
  • edit in src/main.rs at line 222
    [4.1806]
    [2.2055]
    cache_query_delegation_game: tokio::sync::Mutex::new(ttl_cache::TtlCache::new(
    cache_capacity,
    )),
  • edit in src/main.rs at line 279
    [3.2488]
    [4.2328]
    .route("/query-delegate.do", web::post().to(post_query_delegate))
  • file addition: 20221022_0_query_delegate.sql (----------)
    [19.15]
    -- Add table to store queries to delegation
    CREATE TABLE IF NOT EXISTS games.query_delegation (
    game_uid VARCHAR(20) REFERENCES games.games(game_uid),
    player_name CITEXT REFERENCES auth.users(player_name),
    delegate_name CITEXT REFERENCES auth.users(player_name),
    CONSTRAINT pk_query_delegation PRIMARY KEY (game_uid, player_name, delegate_name)
    );
    GRANT SELECT, INSERT, DELETE ON games.query_delegation TO freeorion;