generated from PlexSheep/rs-base
feat(meta): webinterface is now kinda useful and fancy
cargo devel CI / cargo CI (push) Successful in 1m53s
Details
cargo devel CI / cargo CI (push) Successful in 1m53s
Details
This commit is contained in:
parent
14042bc21b
commit
fb10ca1464
|
@ -122,89 +122,26 @@
|
||||||
|
|
||||||
<hr class="mb-5">
|
<hr class="mb-5">
|
||||||
|
|
||||||
<div class="row g-5 mb-5">
|
|
||||||
<h2 class="text-body-emphasis">Challenge {{ challenge_idx}} — {{ challenge_title }}</h2>
|
|
||||||
<p class="mt-1 mb-3">{{ challenge_description }}</p>
|
|
||||||
<div class="col mt-1">
|
|
||||||
<h3>Hints</h3>
|
|
||||||
<button class="btn btn-primary my-2" type="button" data-bs-toggle="collapse" data-bs-target="#hints"
|
|
||||||
aria-expanded="false" aria-controls="collapseExample">
|
|
||||||
Show hints
|
|
||||||
</button>
|
|
||||||
<div class="collapse" id="hints">
|
|
||||||
<ul class="list-unstyled ps-0">
|
|
||||||
{% for hint in challenge_hints %}
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
<svg class="bi" width="16" height="16">
|
|
||||||
<use xlink:href="#arrow-right-circle" />
|
|
||||||
</svg>
|
|
||||||
{{hint}}
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col mt-1">
|
|
||||||
<h3>Solution</h3>
|
|
||||||
<button class="btn btn-primary my-2" type="button" data-bs-toggle="collapse" data-bs-target="#solution"
|
|
||||||
aria-expanded="false" aria-controls="collapseExample">
|
|
||||||
Show solution
|
|
||||||
</button>
|
|
||||||
<div class="collapse" id="solution">
|
|
||||||
<p>
|
|
||||||
<svg class="bi" width="16" height="16">
|
|
||||||
<use xlink:href="#arrow-right-circle" />
|
|
||||||
</svg>
|
|
||||||
{{challenge_solution}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="mb-5">
|
|
||||||
|
|
||||||
<div class="row g-5">
|
<div class="row g-5">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2 class="text-body-emphasis">Contestants</h2>
|
<h2 class="text-body-emphasis">Challenges</h2>
|
||||||
<p>
|
<p>
|
||||||
There are cuttently {{ contestants_amount }} contestants.
|
There are cuttently {{ challenges_amount }} active challenges.
|
||||||
These contestants currently have had at least one connection to
|
|
||||||
the challenge:
|
|
||||||
</p>
|
</p>
|
||||||
<ul class="list-unstyled ps-0">
|
<ul class="list-unstyled ps-0">
|
||||||
{% for contestant in contestants %}
|
{% for challenge in challenges %}
|
||||||
<li>
|
<li>
|
||||||
<a class="icon-link mb-1" href="https://whatismyipaddress.com/ip/{{ contestant.ip }}">
|
<a class="icon-link mb-1" href="challenge/{{ challenge.id }}">
|
||||||
<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>
|
||||||
{{ contestant.ip }}
|
{{ challenge.id }} — {{ challenge.title }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h2 class="text-body-emphasis">Winners</h2>
|
|
||||||
<p>
|
|
||||||
There are cuttently {{ winners_amount }} winners. These contestants currently have been sent the secret:
|
|
||||||
</p>
|
|
||||||
<ul class="list-unstyled ps-0">
|
|
||||||
{% for winner in winners %}
|
|
||||||
<li>
|
|
||||||
<a class="icon-link mb-1" href="https://whatismyipaddress.com/ip/{{ winner.ip }}">
|
|
||||||
<svg class="bi" width="16" height="16">
|
|
||||||
<use xlink:href="#arrow-right-circle" />
|
|
||||||
</svg>
|
|
||||||
{{ winner.ip }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</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">
|
||||||
|
|
|
@ -112,12 +112,13 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<h1 class="text-body-emphasis">{{title}} Admin Interface</h1>
|
<h1 class="text-body-emphasis">{{title}} User Interface</h1>
|
||||||
<p class="fs-5 col-md-8">
|
<p class="fs-5 col-md-8">
|
||||||
You have reached the {{title}} Admin Interface. This site can be used by
|
You have reached the {{title}} User
|
||||||
the host of the challenge to see the challenge progress, solution, and
|
Interface. This site can be used by the
|
||||||
hints for that challenge. This site is <b>NOT</b> part of the
|
contestants see the challenges and their
|
||||||
challenge.
|
progress and hints for that challenge. This
|
||||||
|
site is <b>NOT</b> part of the challenge.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<hr class="mb-5">
|
<hr class="mb-5">
|
||||||
|
@ -146,21 +147,6 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col mt-1">
|
|
||||||
<h3>Solution</h3>
|
|
||||||
<button class="btn btn-primary my-2" type="button" data-bs-toggle="collapse"
|
|
||||||
data-bs-target="#solution" aria-expanded="false" aria-controls="collapseExample">
|
|
||||||
Show solution
|
|
||||||
</button>
|
|
||||||
<div class="collapse" id="solution">
|
|
||||||
<p>
|
|
||||||
<svg class="bi" width="16" height="16">
|
|
||||||
<use xlink:href="#arrow-right-circle" />
|
|
||||||
</svg>
|
|
||||||
{{challenge_solution}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="mb-5">
|
<hr class="mb-5">
|
||||||
|
|
|
@ -114,98 +114,35 @@
|
||||||
<main>
|
<main>
|
||||||
<h1 class="text-body-emphasis">{{title}} Admin Interface</h1>
|
<h1 class="text-body-emphasis">{{title}} Admin Interface</h1>
|
||||||
<p class="fs-5 col-md-8">
|
<p class="fs-5 col-md-8">
|
||||||
You have reached the {{title}} Admin Interface. This site can be used by
|
You have reached the {{title}} User
|
||||||
the host of the challenge to see the challenge progress, solution, and
|
Interface. This site can be used by the
|
||||||
hints for that challenge. This site is <b>NOT</b> part of the
|
contestants see the challenges and their
|
||||||
challenge.
|
progress and hints for that challenge. This
|
||||||
|
site is <b>NOT</b> part of the challenge.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<hr class="mb-5">
|
<hr class="mb-5">
|
||||||
|
|
||||||
<div class="row g-5 mb-5">
|
|
||||||
<h2 class="text-body-emphasis">Challenge {{ challenge_idx}} — {{ challenge_title }}</h2>
|
|
||||||
<p class="mt-1 mb-3">{{ challenge_description }}</p>
|
|
||||||
<div class="col mt-1">
|
|
||||||
<h3>Hints</h3>
|
|
||||||
<button class="btn btn-primary my-2" type="button" data-bs-toggle="collapse" data-bs-target="#hints"
|
|
||||||
aria-expanded="false" aria-controls="collapseExample">
|
|
||||||
Show hints
|
|
||||||
</button>
|
|
||||||
<div class="collapse" id="hints">
|
|
||||||
<ul class="list-unstyled ps-0">
|
|
||||||
{% for hint in challenge_hints %}
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
<svg class="bi" width="16" height="16">
|
|
||||||
<use xlink:href="#arrow-right-circle" />
|
|
||||||
</svg>
|
|
||||||
{{hint}}
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col mt-1">
|
|
||||||
<h3>Solution</h3>
|
|
||||||
<button class="btn btn-primary my-2" type="button" data-bs-toggle="collapse"
|
|
||||||
data-bs-target="#solution" aria-expanded="false" aria-controls="collapseExample">
|
|
||||||
Show solution
|
|
||||||
</button>
|
|
||||||
<div class="collapse" id="solution">
|
|
||||||
<p>
|
|
||||||
<svg class="bi" width="16" height="16">
|
|
||||||
<use xlink:href="#arrow-right-circle" />
|
|
||||||
</svg>
|
|
||||||
{{challenge_solution}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="mb-5">
|
|
||||||
|
|
||||||
<div class="row g-5">
|
<div class="row g-5">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2 class="text-body-emphasis">Contestants</h2>
|
<h2 class="text-body-emphasis">Challenges</h2>
|
||||||
<p>
|
<p>
|
||||||
There are cuttently {{ contestants_amount }} contestants.
|
There are cuttently {{ challenges_amount }} active challenges.
|
||||||
These contestants currently have had at least one connection to
|
|
||||||
the challenge:
|
|
||||||
</p>
|
</p>
|
||||||
<ul class="list-unstyled ps-0">
|
<ul class="list-unstyled ps-0">
|
||||||
{% for contestant in contestants %}
|
{% for challenge in challenges %}
|
||||||
<li>
|
<li>
|
||||||
<a class="icon-link mb-1" href="https://whatismyipaddress.com/ip/{{ contestant.ip }}">
|
<a class="icon-link mb-1" href="challenge/{{ challenge.id }}">
|
||||||
<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>
|
||||||
{{ contestant.ip }}
|
{{ challenge.id }} — {{ challenge.title }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h2 class="text-body-emphasis">Winners</h2>
|
|
||||||
<p>
|
|
||||||
There are cuttently {{ winners_amount }} winners. These contestants currently have been sent the
|
|
||||||
secret:
|
|
||||||
</p>
|
|
||||||
<ul class="list-unstyled ps-0">
|
|
||||||
{% for winner in winners %}
|
|
||||||
<li>
|
|
||||||
<a class="icon-link mb-1" href="https://whatismyipaddress.com/ip/{{ winner.ip }}">
|
|
||||||
<svg class="bi" width="16" height="16">
|
|
||||||
<use xlink:href="#arrow-right-circle" />
|
|
||||||
</svg>
|
|
||||||
{{ winner.ip }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</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">
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use libpt::log::{error, info};
|
use libpt::log::{error, info};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::vault::VaultRef;
|
use crate::vault::VaultRef;
|
||||||
|
@ -13,7 +14,7 @@ pub mod c1;
|
||||||
pub mod c2;
|
pub mod c2;
|
||||||
pub mod c3;
|
pub mod c3;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
|
||||||
pub struct ChallengeDesc {
|
pub struct ChallengeDesc {
|
||||||
id: usize,
|
id: usize,
|
||||||
title: String,
|
title: String,
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl<'tp> Service<'tp> {
|
||||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone + 'tp {
|
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone + 'tp {
|
||||||
let serv = this.clone();
|
let serv = this.clone();
|
||||||
warp::path!("admin" / "challenge" / usize)
|
warp::path!("admin" / "challenge" / usize)
|
||||||
.map(move |id: usize| serv.challenges[id + 1].clone())
|
.map(move |id: usize| serv.challenges[id - 1].clone())
|
||||||
.and(with_serv(this.clone()))
|
.and(with_serv(this.clone()))
|
||||||
.and_then(details)
|
.and_then(details)
|
||||||
.with(warp::trace(|info| {
|
.with(warp::trace(|info| {
|
||||||
|
@ -51,7 +51,7 @@ async fn details(
|
||||||
let winners = vault.winners().await.into_iter().collect::<Vec<_>>();
|
let winners = vault.winners().await.into_iter().collect::<Vec<_>>();
|
||||||
let r = Response::new(
|
let r = Response::new(
|
||||||
serv.env
|
serv.env
|
||||||
.get_template("admin:index")
|
.get_template("admin:details")
|
||||||
.map_err(TemplateError::from)?
|
.map_err(TemplateError::from)?
|
||||||
.render(context!(
|
.render(context!(
|
||||||
title => "Wooly-Vault",
|
title => "Wooly-Vault",
|
||||||
|
@ -77,6 +77,24 @@ async fn details(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn index(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
|
async fn index(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
|
||||||
let r = Response::new("todo".into());
|
let challenges = serv
|
||||||
|
.challenges
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.0.to_owned())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let r = Response::new(
|
||||||
|
serv.env
|
||||||
|
.get_template("admin:index")
|
||||||
|
.map_err(TemplateError::from)?
|
||||||
|
.render(context!(
|
||||||
|
title => "Wooly-Vault",
|
||||||
|
author => env!("CARGO_PKG_AUTHORS"),
|
||||||
|
year => "2024",
|
||||||
|
challenges => challenges,
|
||||||
|
challenges_amount => challenges.len(),
|
||||||
|
))
|
||||||
|
.map_err(TemplateError::from)?
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
Ok(Box::new(r))
|
Ok(Box::new(r))
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl<'tp> Service<'tp> {
|
||||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone + 'tp {
|
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone + 'tp {
|
||||||
let serv = this.clone();
|
let serv = this.clone();
|
||||||
warp::path!("challenge" / usize)
|
warp::path!("challenge" / usize)
|
||||||
.map(move |id: usize| serv.challenges[id + 1].clone())
|
.map(move |id: usize| serv.challenges[id - 1].clone())
|
||||||
.and(with_serv(this.clone()))
|
.and(with_serv(this.clone()))
|
||||||
.and_then(details)
|
.and_then(details)
|
||||||
.with(warp::trace(|info| {
|
.with(warp::trace(|info| {
|
||||||
|
@ -51,7 +51,7 @@ async fn details(
|
||||||
let winners = vault.winners().await.into_iter().collect::<Vec<_>>();
|
let winners = vault.winners().await.into_iter().collect::<Vec<_>>();
|
||||||
let r = Response::new(
|
let r = Response::new(
|
||||||
serv.env
|
serv.env
|
||||||
.get_template("index")
|
.get_template("details")
|
||||||
.map_err(TemplateError::from)?
|
.map_err(TemplateError::from)?
|
||||||
.render(context!(
|
.render(context!(
|
||||||
title => "Wooly-Vault",
|
title => "Wooly-Vault",
|
||||||
|
@ -77,6 +77,24 @@ async fn details(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn index(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
|
async fn index(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
|
||||||
let r = Response::new("todo".into());
|
let challenges = serv
|
||||||
|
.challenges
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.0.to_owned())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let r = Response::new(
|
||||||
|
serv.env
|
||||||
|
.get_template("admin:index")
|
||||||
|
.map_err(TemplateError::from)?
|
||||||
|
.render(context!(
|
||||||
|
title => "Wooly-Vault",
|
||||||
|
author => env!("CARGO_PKG_AUTHORS"),
|
||||||
|
year => "2024",
|
||||||
|
challenges => challenges,
|
||||||
|
challenges_amount => challenges.len(),
|
||||||
|
))
|
||||||
|
.map_err(TemplateError::from)?
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
Ok(Box::new(r))
|
Ok(Box::new(r))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue