Implement delegation support

O01eg
Oct 22, 2022, 7:27 PM
V5ULHL43GPCVBOTCC4MBRG7KJ7O4QQVFAWUXLJX6E5VDMJCW6BNQC

Dependencies

  • [2] SBYGGRXY Show pending delegates
  • [3] LOFH5LIA Make bold player name
  • [4] JG2BQCRD Implement query for delegation
  • [5] 6BDGQ4VM Show player names for registered players
  • [6] DNFB7TNI Add new pages and links to slow games and reset game password
  • [7] WW3KRXX6 Add page for reset game password
  • [8] B7PYGLH3 Show delegate bold if it's logged user itself
  • [9] YDWTHWAI Show form to revoke delegation
  • [*] 6NYILMKI Add page for slow game
  • [*] H7NQUYI6 Record join to the game
  • [*] TEB4R7OU Add form to join game
  • [*] D3RL62X5 Implement revoking delegation
  • [*] EVP2FSBH Split index page
  • [*] 3HT5CE6S Manage TTL duration in config
  • [*] 4MZ4VIR7 Initial commit
  • [*] HZDCKIXQ Use constants for templates

Change contents

  • replacement in src/templates/slow-game.html at line 89
    [3.645][3.645:672]()
    </form>
    [3.645]
    [3.680]
    </form>
  • replacement in src/templates/slow-game.html at line 93
    [2.92][2.92:146]()
    <span class="pending">{{delegate}}</span>
    [2.92]
    [2.146]
    <form id="delegate-{{ delegate.csrf }}" action="delegate.do" method="post">
    <fieldset>
    <label for="submit">{{delegate.name}}</label>
    <input name="csrf" type="hidden" value="{{ delegate.csrf }}">
    {{#if delegate.accept}}
    <input name="submit" type="submit" value="Accept Delegate">
    {{/if}}
    <input name="submit" type="submit" value="Reject Delegate">
    </fieldset>
    </form>
  • edit in src/pages/slow_game.rs at line 9
    [12.46]
    [3.126]
    #[derive(serde_derive::Serialize)]
    struct PendingDelegateInfo {
    csrf: Uuid,
    name: String,
    accept: bool,
    }
  • replacement in src/pages/slow_game.rs at line 25
    [3.721][2.189:233]()
    pending_delegates: Option<Vec<String>>,
    [3.721]
    [3.207]
    pending_delegates: Option<Vec<PendingDelegateInfo>>,
  • edit in src/pages/slow_game.rs at line 37
    [3.839]
    [13.285]
    }
    #[derive(serde_derive::Deserialize)]
    pub struct DelegationData {
    csrf: Uuid,
    submit: String,
  • edit in src/pages/slow_game.rs at line 198
    [2.1935]
    [2.1935]
    let mut cache = data.cache_delegation_game.lock().await;
  • replacement in src/pages/slow_game.rs at line 202
    [2.2026][2.2026:2083]()
    .map(std::string::String::clone)
    [2.2026]
    [2.2083]
    .map(|x| {
    let csrf = Uuid::new_v4();
    cache.insert(
    csrf,
    (gameuid.clone(), user.to_lowercase(), x.to_lowercase()),
    std::time::Duration::from_secs(data.cache_duration_sec),
    );
    PendingDelegateInfo {
    csrf,
    name: x.clone(),
    accept: false,
    }
    })
  • replacement in src/pages/slow_game.rs at line 218
    [2.2214][2.2214:2297]()
    Some([user].into_iter().map(std::string::String::clone).collect())
    [2.2214]
    [2.2297]
    let csrf = Uuid::new_v4();
    let mut cache = data.cache_delegation_game.lock().await;
    cache.insert(
    csrf,
    (
    gameuid.clone(),
    player_name.to_lowercase(),
    user.to_lowercase(),
    ),
    std::time::Duration::from_secs(data.cache_duration_sec),
    );
    Some(
    [PendingDelegateInfo {
    csrf,
    name: user.clone(),
    accept: true,
    }]
    .into_iter()
    .collect(),
    )
  • edit in src/pages/slow_game.rs at line 628
    [14.2316]
    pub async fn post_delegate(
    request: HttpRequest,
    form: web::Form<DelegationData>,
    data: web::Data<WebData<'_>>,
    data_rw: web::Data<DataBaseRw>,
    ) -> HttpResponse {
    let cached_data = {
    let mut cache = data.cache_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);
    let user = if let Some(u) = jar
    .private(&data.cookies_key)
    .get("auth")
    .map(|x| x.value().to_lowercase())
    {
    u
    } else {
    log::warn!("Incorrect user");
    return HttpResponse::BadRequest().body("Incorrect");
    };
    if form.submit == "Accept Delegate" && user == cached_data.2 {
    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());
    }
    };
    match dbclient_rw
    .execute(
    "delete from games.query_delegation where game_uid = $1 and player_name = $2;",
    &[&cached_data.0, &cached_data.1],
    )
    .await
    {
    Ok(_) => (),
    Err(e) => {
    log::error!("Pool RW statement error {}", e);
    return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
    }
    };
    match dbclient_rw
    .execute("update games.players set delegate_name = $3 where game_uid = $1 and player_name = $2;", &[&cached_data.0, &cached_data.1, &cached_data.2])
    .await
    {
    Ok(_) => (),
    Err(e) => {
    log::error!("Pool RW statement error {}", e);
    return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
    }
    };
    } else if form.submit == "Reject Delegate" && (user == cached_data.1 || user == cached_data.2) {
    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("delete from games.query_delegation where game_uid = $1 and player_name = $2 and delegate_name = $3;")
    .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, &cached_data.2])
    .await
    {
    Ok(_) => (),
    Err(e) => {
    log::error!("Pool RW execute insert error {}", e);
    return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
    }
    };
    } else {
    log::warn!("Incorrect user submit {}", form.submit);
    return HttpResponse::BadRequest().body("Incorrect");
    }
    HttpResponse::Found()
    .append_header((
    header::LOCATION,
    format!("slow-game-{}.html", cached_data.0),
    ))
    .finish()
    }
  • edit in src/pages/mod.rs at line 53
    [3.1974]
    [16.140]
    pub cache_delegation_game: Mutex<TtlCache<Uuid, (String, String, String)>>,
  • replacement in src/main.rs at line 23
    [3.3604][3.3604:3695]()
    post_join_game, post_leave_game, post_query_delegate, post_revoke_delegate, slow_game,
    [3.3604]
    [3.3695]
    post_delegate, post_join_game, post_leave_game, post_query_delegate, post_revoke_delegate,
    slow_game,
  • edit in src/main.rs at line 229
    [3.2183]
    [16.203]
    cache_delegation_game: tokio::sync::Mutex::new(ttl_cache::TtlCache::new(cache_capacity)),
  • edit in src/main.rs at line 282
    [3.3905]
    [18.2328]
    .route("/delegate.do", web::post().to(post_delegate))