mirror of
https://git.verdigado.com/NB-Public/simple-wkd.git
synced 2024-12-05 02:52:50 +01:00
Improve error handling further
This commit is contained in:
parent
0f5b9ae1d6
commit
85b2c707b8
5 changed files with 64 additions and 40 deletions
|
@ -6,7 +6,7 @@ use crate::management::{delete_key, Action, Pending};
|
|||
use crate::pending_path;
|
||||
use crate::settings::{MAILER, ROOT_FOLDER, SETTINGS};
|
||||
use crate::utils::{get_email_from_cert, parse_pem, read_file};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use anyhow::Result;
|
||||
|
||||
use lettre::{Message, Transport};
|
||||
use std::fs;
|
||||
|
@ -26,9 +26,7 @@ pub fn confirm_action(token: &str) -> Result<(Action, String)> {
|
|||
let email = get_email_from_cert(&cert)?;
|
||||
let domain = match email.split('@').last() {
|
||||
Some(domain) => domain.to_string(),
|
||||
None => {
|
||||
Err(SpecialErrors::MalformedEmail)?
|
||||
}
|
||||
None => Err(SpecialErrors::MalformedEmail)?,
|
||||
};
|
||||
sequoia_net::wkd::insert(ROOT_FOLDER, domain, SETTINGS.variant, &cert)?;
|
||||
email
|
||||
|
@ -59,7 +57,10 @@ pub fn send_confirmation_email(address: &str, action: &Action, token: &str) -> R
|
|||
panic!("Unable to parse the email in the settings!")
|
||||
}
|
||||
})
|
||||
.to(address.parse()?)
|
||||
.to(match address.parse() {
|
||||
Ok(mbox) => mbox,
|
||||
Err(_) => Err(SpecialErrors::MalformedEmail)?,
|
||||
})
|
||||
.subject(
|
||||
SETTINGS
|
||||
.mail_settings
|
||||
|
|
|
@ -7,14 +7,18 @@ use crate::utils::return_outcome;
|
|||
|
||||
#[derive(Debug, DeriveError)]
|
||||
pub enum SpecialErrors {
|
||||
#[error("Could not find any primay user email in the keyblock!")]
|
||||
EmailMissing,
|
||||
#[error("The request had expired!")]
|
||||
ExpiredRequest,
|
||||
#[error("The key for the requested user does not exist!")]
|
||||
InexistingUser,
|
||||
#[error("The key is either expired or uses an obsolete cipher!")]
|
||||
InvalidCert,
|
||||
#[error("Could not parse keyblock")]
|
||||
MalformedCert,
|
||||
#[error("Could not parse user email: malformed email")]
|
||||
MalformedEmail,
|
||||
#[error("Could not find any primay user email in the keyblock!")]
|
||||
MalformedCert,
|
||||
#[error("The requested file does not exist!")]
|
||||
MissingFile,
|
||||
#[error("User email rejected: domain not allowed")]
|
||||
|
@ -55,20 +59,22 @@ impl From<Error> for CompatErr {
|
|||
impl ResponseError for CompatErr {
|
||||
fn status_code(&self) -> actix_web::http::StatusCode {
|
||||
match self {
|
||||
Self::AnyhowErr(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::SpecialErr(error) => match error {
|
||||
SpecialErrors::ExpiredRequest => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::InexistingUser => StatusCode::NOT_FOUND,
|
||||
SpecialErrors::MalformedCert => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::MalformedEmail => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::MissingFile => StatusCode::NOT_FOUND,
|
||||
SpecialErrors::UnallowedDomain => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
Self::AnyhowErr(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::SpecialErr(error) => match error {
|
||||
SpecialErrors::ExpiredRequest => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::InexistingUser => StatusCode::NOT_FOUND,
|
||||
SpecialErrors::InvalidCert => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::EmailMissing => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::MalformedCert => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::MalformedEmail => StatusCode::BAD_REQUEST,
|
||||
SpecialErrors::MissingFile => StatusCode::NOT_FOUND,
|
||||
SpecialErrors::UnallowedDomain => StatusCode::UNAUTHORIZED,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> actix_web::HttpResponse<actix_web::body::BoxBody> {
|
||||
match return_outcome(Err(&self.to_string())) {
|
||||
match return_outcome(Err(self)) {
|
||||
Ok(httpbuilder) => httpbuilder,
|
||||
Err(_) => HttpResponseBuilder::new(self.status_code()).body(self.to_string()),
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::errors::CompatErr;
|
|||
use crate::management::{clean_stale, store_pending_addition, store_pending_deletion, Action};
|
||||
use crate::settings::{ROOT_FOLDER, SETTINGS};
|
||||
use crate::utils::{
|
||||
gen_random_token, get_email_from_cert, is_email_allowed, parse_pem, return_outcome, read_file,
|
||||
gen_random_token, get_email_from_cert, is_email_allowed, parse_pem, read_file, return_outcome,
|
||||
};
|
||||
|
||||
use actix_files::Files;
|
||||
|
@ -18,7 +18,6 @@ use actix_web::http::StatusCode;
|
|||
use actix_web::{
|
||||
get, post, web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer, Result,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use errors::SpecialErrors;
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
|
@ -108,12 +107,8 @@ async fn submit(pem: web::Form<Key>) -> Result<HttpResponse, CompatErr> {
|
|||
async fn confirm(token: web::Query<Token>) -> Result<HttpResponse, CompatErr> {
|
||||
let (action, _email) = confirm_action(&token.token)?;
|
||||
match action {
|
||||
Action::Add => {
|
||||
Ok(return_outcome(Ok("Your key was added successfully!"))?)
|
||||
}
|
||||
Action::Delete => {
|
||||
Ok(return_outcome(Ok("Your key was deleted successfully!"))?)
|
||||
}
|
||||
Action::Add => Ok(return_outcome(Ok("Your key was added successfully!"))?),
|
||||
Action::Delete => Ok(return_outcome(Ok("Your key was deleted successfully!"))?),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,5 +117,7 @@ async fn delete(email: web::Query<Email>) -> Result<HttpResponse, CompatErr> {
|
|||
let token = gen_random_token();
|
||||
store_pending_deletion(email.email.clone(), &token)?;
|
||||
send_confirmation_email(&email.email, &Action::Delete, &token)?;
|
||||
Ok(return_outcome(Ok("You requested the deletion of your key successfully!"))?)
|
||||
Ok(return_outcome(Ok(
|
||||
"You requested the deletion of your key successfully!",
|
||||
))?)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use lettre::{transport::smtp::authentication::Credentials, SmtpTransport};
|
||||
use once_cell::sync::Lazy;
|
||||
use sequoia_net::wkd::Variant;
|
||||
use sequoia_openpgp::policy::StandardPolicy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{path::{PathBuf}};
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
|
||||
use crate::utils::read_file;
|
||||
|
@ -84,6 +85,7 @@ fn get_mailer() -> SmtpTransport {
|
|||
mailer
|
||||
}
|
||||
|
||||
pub const POLICY: &StandardPolicy = &StandardPolicy::new();
|
||||
pub const ROOT_FOLDER: &str = "data";
|
||||
pub static SETTINGS: Lazy<Settings> = Lazy::new(get_settings);
|
||||
pub static MAILER: Lazy<SmtpTransport> = Lazy::new(get_mailer);
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
use crate::errors::CompatErr;
|
||||
use crate::errors::SpecialErrors;
|
||||
use crate::settings::POLICY;
|
||||
use crate::settings::ROOT_FOLDER;
|
||||
use crate::settings::SETTINGS;
|
||||
|
||||
use actix_web::ResponseError;
|
||||
use actix_web::{
|
||||
http::{header::ContentType, StatusCode},
|
||||
HttpResponse, HttpResponseBuilder,
|
||||
};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use anyhow::Result;
|
||||
use flexi_logger::{
|
||||
detailed_format, style, DeferredNow, FileSpec, FlexiLoggerError, Logger, LoggerHandle, Record,
|
||||
};
|
||||
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
||||
use sequoia_net::wkd::Url;
|
||||
use sequoia_openpgp::{parse::Parse, policy::StandardPolicy, Cert};
|
||||
use sequoia_openpgp::{parse::Parse, Cert};
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
|
@ -32,6 +35,16 @@ macro_rules! webpage_path {
|
|||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! validate_cert {
|
||||
( $x:expr ) => {
|
||||
match $x.with_policy(POLICY, None) {
|
||||
Ok(validcert) => Ok(validcert),
|
||||
Err(_) => Err(SpecialErrors::InvalidCert),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn read_file(path: &PathBuf) -> Result<String> {
|
||||
if path.is_file() {
|
||||
Ok(fs::read_to_string(path)?)
|
||||
|
@ -52,9 +65,11 @@ pub fn is_email_allowed(email: &str) -> Result<()> {
|
|||
}
|
||||
|
||||
pub fn parse_pem(pemfile: &str) -> Result<Cert> {
|
||||
let cert = sequoia_openpgp::Cert::from_bytes(pemfile.as_bytes())?;
|
||||
let policy = StandardPolicy::new();
|
||||
cert.with_policy(&policy, None)?;
|
||||
let cert = match sequoia_openpgp::Cert::from_bytes(pemfile.as_bytes()) {
|
||||
Ok(cert) => cert,
|
||||
Err(_) => Err(SpecialErrors::MalformedCert)?,
|
||||
};
|
||||
validate_cert!(cert)?;
|
||||
Ok(cert)
|
||||
}
|
||||
|
||||
|
@ -64,13 +79,12 @@ pub fn gen_random_token() -> String {
|
|||
}
|
||||
|
||||
pub fn get_email_from_cert(cert: &Cert) -> Result<String> {
|
||||
let policy = StandardPolicy::new();
|
||||
let validcert = cert.with_policy(&policy, None)?;
|
||||
let validcert = validate_cert!(cert)?;
|
||||
let userid_opt = validcert.primary_userid()?;
|
||||
let email_opt = userid_opt.email()?;
|
||||
match email_opt {
|
||||
Some(email) => Ok(email),
|
||||
None => Err(SpecialErrors::MalformedCert)?,
|
||||
None => Err(SpecialErrors::EmailMissing)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,15 +149,19 @@ pub fn init_logger() -> Result<LoggerHandle, FlexiLoggerError> {
|
|||
.start()
|
||||
}
|
||||
|
||||
pub fn return_outcome(data: Result<&str, &str>) -> Result<HttpResponse> {
|
||||
pub fn return_outcome(data: Result<&str, &CompatErr>) -> Result<HttpResponse> {
|
||||
let path = webpage_path!().join("status").join("index.html");
|
||||
let template = read_file(&path)?;
|
||||
let (page, message) = match data {
|
||||
Ok(message) => (template.replace("((%s))", "Success!"), message),
|
||||
Err(message) => (template.replace("((%s))", "Failure!"), message),
|
||||
Ok(message) => (template.replace("((%s))", "Success!"), message.to_string()),
|
||||
Err(error) => (template.replace("((%s))", "Failure!"), error.to_string()),
|
||||
};
|
||||
let page = page.replace("((%m))", message);
|
||||
return Ok(HttpResponseBuilder::new(StatusCode::OK)
|
||||
let status_code = match data {
|
||||
Ok(_) => StatusCode::OK,
|
||||
Err(error) => error.status_code(),
|
||||
};
|
||||
let page = page.replace("((%m))", &message);
|
||||
return Ok(HttpResponseBuilder::new(status_code)
|
||||
.insert_header(ContentType::html())
|
||||
.body(page));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue