feat(admin): show contestants and winners
cargo devel CI / cargo CI (push) Successful in 1m49s Details

This commit is contained in:
Christoph J. Scherr 2024-09-07 19:49:41 +02:00
parent 80b9d213c3
commit e0f33897a1
3 changed files with 29 additions and 11 deletions

View File

@ -169,42 +169,46 @@
<div class="col-md-6"> <div class="col-md-6">
<h2 class="text-body-emphasis">Contestants</h2> <h2 class="text-body-emphasis">Contestants</h2>
<p> <p>
There are cuttently {{ contestants_amount }} contestants.
These contestants currently have had at least one connection to These contestants currently have had at least one connection to
the challenge. the challenge:
</p> </p>
<ul class="list-unstyled ps-0"> <ul class="list-unstyled ps-0">
{% for contestant in contestants %}
<li> <li>
<a class="icon-link mb-1" href="https://github.com/twbs/examples/tree/main/icons-font" rel="noopener" <a class="icon-link mb-1" href="https://whatismyipaddress.com/ip/{{ contestant.ip }}">
target="_blank">
<svg class="bi" width="16" height="16"> <svg class="bi" width="16" height="16">
<use xlink:href="#arrow-right-circle" /> <use xlink:href="#arrow-right-circle" />
</svg> </svg>
Bootstrap npm starter {{ contestant.ip }}
</a> </a>
</li> </li>
{% endfor %}
</ul> </ul>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<h2 class="text-body-emphasis">Winners</h2> <h2 class="text-body-emphasis">Winners</h2>
<p> <p>
These contestants currently have been sent the secret. There are cuttently {{ winners_amount }} winners. These contestants currently have been sent the secret:
</p> </p>
<ul class="list-unstyled ps-0"> <ul class="list-unstyled ps-0">
{% for winner in winners %}
<li> <li>
<a class="icon-link mb-1" href="/docs/5.3/getting-started/introduction/"> <a class="icon-link mb-1" href="https://whatismyipaddress.com/ip/{{ winner.ip }}">
<svg class="bi" width="16" height="16"> <svg class="bi" width="16" height="16">
<use xlink:href="#arrow-right-circle" /> <use xlink:href="#arrow-right-circle" />
</svg> </svg>
Bootstrap quick start guide {{ winner.ip }}
</a> </a>
</li> </li>
{% endfor %}
</ul> </ul>
</div> </div>
</div> </div>
</main> </main>
<footer class="pt-5 my-5 text-body-secondary border-top"> <footer class="pt-5 my-5 text-body-secondary border-top">
Created by {{ author }} &middot; &copy; {{year}} Created by {{ author }} &copy; {{year}}
</footer> </footer>
</div> </div>
<script src="https://getbootstrap.com/docs/5.3/dist/js/bootstrap.bundle.min.js" <script src="https://getbootstrap.com/docs/5.3/dist/js/bootstrap.bundle.min.js"

View File

@ -74,6 +74,13 @@ impl Display for TemplateError {
} }
async fn overview(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::Rejection> { async fn overview(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
let contestants = serv
.vault
.contestants()
.await
.into_iter()
.collect::<Vec<_>>();
let winners = serv.vault.winners().await.into_iter().collect::<Vec<_>>();
let r = Response::new( let r = Response::new(
serv.env serv.env
.get_template("index") .get_template("index")
@ -87,6 +94,12 @@ async fn overview(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::
challenge_description => serv.text.description(), challenge_description => serv.text.description(),
challenge_hints => serv.text.hints(), challenge_hints => serv.text.hints(),
challenge_solution => serv.text.solution(), challenge_solution => serv.text.solution(),
contestants => serv.vault.contestants().await.iter().collect::<Vec<_>>(),
winners => serv.vault.winners().await.iter().collect::<Vec<_>>(),
contestants => contestants,
winners => winners,
contestants_amount => contestants.len(),
winners_amount => winners.len(),
)) ))
.map_err(TemplateError::from)? .map_err(TemplateError::from)?
.into(), .into(),

View File

@ -9,6 +9,7 @@ use std::net::{IpAddr, SocketAddr};
use std::sync::Arc; use std::sync::Arc;
use libpt::log::info; use libpt::log::info;
use serde::{Deserialize, Serialize};
use tokio::sync::Mutex; use tokio::sync::Mutex;
/// A type alias for an [`Arc`] pointer to a [`Vault`] instance. /// A type alias for an [`Arc`] pointer to a [`Vault`] instance.
@ -16,7 +17,7 @@ use tokio::sync::Mutex;
/// This type is used to share a [`Vault`] instance across multiple parts of the application. /// This type is used to share a [`Vault`] instance across multiple parts of the application.
pub type VaultRef = Arc<Vault>; pub type VaultRef = Arc<Vault>;
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Contestant { pub struct Contestant {
ip: IpAddr, ip: IpAddr,
} }
@ -52,7 +53,7 @@ impl From<&SocketAddr> for Contestant {
impl Display for Contestant { impl Display for Contestant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}") write!(f, "{}", self.ip)
} }
} }
@ -97,6 +98,6 @@ impl Vault {
} }
pub async fn winners(&self) -> HashSet<Contestant> { pub async fn winners(&self) -> HashSet<Contestant> {
self.contestants.lock().await.clone() self.winners.lock().await.clone()
} }
} }