Dramatically simplify the certificate example
This commit is contained in:
parent
f922f8c70d
commit
b265ae985c
|
@ -1,12 +1,9 @@
|
|||
use anyhow::*;
|
||||
use anyhow::Result;
|
||||
use log::LevelFilter;
|
||||
use tokio::sync::RwLock;
|
||||
use kochab::{Certificate, Request, Response, Server};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Workaround for Certificates not being hashable
|
||||
type CertBytes = Vec<u8>;
|
||||
use std::fmt::Write;
|
||||
|
||||
use kochab::{Request, Response, Server};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
|
@ -14,53 +11,23 @@ async fn main() -> Result<()> {
|
|||
.filter_module("kochab", LevelFilter::Debug)
|
||||
.init();
|
||||
|
||||
let users = Arc::<RwLock::<HashMap<CertBytes, String>>>::default();
|
||||
|
||||
Server::new()
|
||||
.add_route("/", move|req| handle_request(users.clone(), req))
|
||||
.add_route("/", handle_request)
|
||||
.serve_unix("kochab.sock")
|
||||
.await
|
||||
}
|
||||
|
||||
/// An ultra-simple demonstration of simple authentication.
|
||||
///
|
||||
/// If the user attempts to connect, they will be prompted to create a client certificate.
|
||||
/// Once they've made one, they'll be given the opportunity to create an account by
|
||||
/// selecting a username. They'll then get a message confirming their account creation.
|
||||
/// Any time this user visits the site in the future, they'll get a personalized welcome
|
||||
/// message.
|
||||
async fn handle_request(users: Arc<RwLock<HashMap<CertBytes, String>>>, request: Request) -> Result<Response> {
|
||||
if let Some(Certificate(cert_bytes)) = request.certificate() {
|
||||
// The user provided a certificate
|
||||
let users_read = users.read().await;
|
||||
if let Some(user) = users_read.get(cert_bytes) {
|
||||
// The user has already registered
|
||||
Ok(
|
||||
Response::success_gemini(format!("Welcome {}!", user))
|
||||
)
|
||||
} else {
|
||||
// The user still needs to register
|
||||
drop(users_read);
|
||||
if let Some(query_part) = request.uri().query() {
|
||||
// The user provided some input (a username request)
|
||||
let username = query_part.as_str();
|
||||
let mut users_write = users.write().await;
|
||||
users_write.insert(cert_bytes.clone(), username.to_owned());
|
||||
Ok(
|
||||
Response::success_gemini(
|
||||
format!(
|
||||
"Your account has been created {}! Welcome!",
|
||||
username
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
// The user didn't provide input, and should be prompted
|
||||
Response::input("What username would you like?")
|
||||
}
|
||||
async fn handle_request(request: Request) -> Result<Response> {
|
||||
if let Some(fingerprint) = request.certificate() {
|
||||
let mut message = String::from("You connected with a certificate with a fingerprint of:\n");
|
||||
|
||||
for byte in fingerprint {
|
||||
write!(&mut message, "{:x}", byte).unwrap();
|
||||
}
|
||||
|
||||
Ok(Response::success_plain(message))
|
||||
} else {
|
||||
// The user didn't provide a certificate
|
||||
Ok(Response::client_certificate_required())
|
||||
Ok(Response::client_certificate_required("You didn't provide a client certificate"))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue