mnemonic-hash-checker: add HTML form and use GET parameters
This commit is contained in:
parent
257184b2c3
commit
11f7eeb05c
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>Milk Sad Lookup</title>
|
||||
<style type="text/css" media="screen">
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 10px;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>MilkSad Lookup Service</h1>
|
||||
<p>
|
||||
Input a SHA256 hash of your mnemonic phrase. <b>DO NOT ENTER</b> your
|
||||
mnemonic phrase in cleartext.
|
||||
</p>
|
||||
|
||||
<form action="/check" method="get" enctype="multipart/form-data">
|
||||
<fieldset>
|
||||
<legend>Lookup</legend>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input type="text" value="" name="sha256" id="sha256" placeholder="put hash here" minlength="64" maxlength="64" required/>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<input type="submit" value="Check For Vulnerability" class="is-full-width" />
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -2,8 +2,9 @@ use std::net::SocketAddr;
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
extract::{Path, State},
|
||||
extract::{Query, State},
|
||||
http::{header::CONTENT_TYPE, StatusCode},
|
||||
response::{AppendHeaders, IntoResponse},
|
||||
routing::get,
|
||||
Json, Router,
|
||||
};
|
||||
|
@ -15,6 +16,8 @@ use clap::Parser;
|
|||
use deadpool_postgres::{Config, ManagerConfig, Pool, RecyclingMethod, Runtime};
|
||||
use tokio_postgres::NoTls;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use tower_http::catch_panic::CatchPanicLayer;
|
||||
use tower_http::trace::TraceLayer;
|
||||
|
||||
|
@ -68,15 +71,20 @@ fn setup_registry() {
|
|||
.init();
|
||||
}
|
||||
|
||||
async fn index() -> impl IntoResponse {
|
||||
(
|
||||
AppendHeaders([(CONTENT_TYPE, "text/html")]),
|
||||
include_str!("index.html"),
|
||||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(state))]
|
||||
async fn check_hash(hash: &str, state: &AppState) -> Result<bool> {
|
||||
let client = state.pool.get().await?;
|
||||
let column = &state.database_column;
|
||||
let table = &state.database_table;
|
||||
let formatted_query = format!("SELECT {column} FROM {table} WHERE hash = $1");
|
||||
let query = client
|
||||
.prepare_cached(formatted_query.as_str())
|
||||
.await?;
|
||||
let query = client.prepare_cached(formatted_query.as_str()).await?;
|
||||
let rows = client.query(&query, &[&hash]).await?;
|
||||
if let Some(row) = rows.get(0) {
|
||||
let retrieved_hash: String = row.try_get(0)?;
|
||||
|
@ -86,13 +94,18 @@ async fn check_hash(hash: &str, state: &AppState) -> Result<bool> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CheckQuery {
|
||||
sha256: String,
|
||||
}
|
||||
|
||||
// Note: Exposes *zero* information of potential errors to clients.
|
||||
#[tracing::instrument(skip(hash, state))]
|
||||
#[tracing::instrument(skip(query, state))]
|
||||
async fn check_hash_slug(
|
||||
Path(hash): Path<String>,
|
||||
query: Query<CheckQuery>,
|
||||
State(state): State<Arc<AppState>>,
|
||||
) -> (StatusCode, Json<Option<bool>>) {
|
||||
let result = check_hash(&hash, &state).await;
|
||||
let result = check_hash(&query.sha256, &state).await;
|
||||
let status_code = match result.as_ref() {
|
||||
Ok(true) => StatusCode::OK,
|
||||
Ok(false) => StatusCode::NOT_FOUND,
|
||||
|
@ -125,7 +138,8 @@ async fn main() -> Result<()> {
|
|||
.unwrap_or_else(|| (std::net::Ipv4Addr::new(127, 0, 0, 1), 8000).into());
|
||||
|
||||
let app = Router::new()
|
||||
.route("/check/:hash", get(check_hash_slug))
|
||||
.route("/", get(index))
|
||||
.route("/check", get(check_hash_slug))
|
||||
.with_state(Arc::new(AppState {
|
||||
pool,
|
||||
database_table: cli_config.database_table,
|
||||
|
|
Loading…
Reference in New Issue