Use a base URI instead of a domain.

- Previously, Hagrid assumed https.  Using a base URI allows us to
    specify both protocol and port.  This helps with testing.

  - Fixes #79.
This commit is contained in:
Justus Winter 2019-03-13 10:32:21 +01:00
parent 2a9e691e79
commit c0e2a732fd
No known key found for this signature in database
GPG Key ID: 686F55B4AB2B3386
6 changed files with 52 additions and 38 deletions

View File

@ -5,16 +5,16 @@ template_dir = "dist/templates"
state_dir = "dist"
[development]
domain = "localhost"
base-URI = "http://localhost:8080"
from = "noreply@localhost"
x-accel-redirect = false
[staging]
domain = "keys.openpgp.org"
base-URI = "https://keys.openpgp.org"
from = "noreply@keys.openpgp.org"
x-accel-redirect = true
[production]
domain = "keys.openpgp.org"
base-URI = "https://keys.openpgp.org"
from = "noreply@keys.openpgp.org"
x-accel-redirect = true

View File

@ -8,13 +8,14 @@
<p>
Someone, presumably you, requested that your key will no longer
be available when searching for you email addresses on
<a href="https://{{domain}}">{{domain}}</a>.
<a href="{{base_uri}}">{{domain}}</a>.
</p>
<p>
If it was not you, please ignore this email.
</p>
<p>
To de-list your key on {{domain}}, follow this link:
To de-list your key on <a href="{{base_uri}}">{{domain}}</a>,
follow this link:
</p>
<p>
<a href="{{uri}}">{{uri}}</a>

View File

@ -5,6 +5,6 @@
</p>
<p>You can get it with GnuPG using the following snippet:</p>
<pre><code class="snippet">gpg {{ gpg_options }}--fetch-keys <a href="https://{{ domain }}/vks/v1/by-fingerprint/{{ fpr }}">https://{{ domain }}/vks/v1/by-fingerprint/{{ fpr }}</a></code></pre>
<pre><code class="snippet">gpg {{ gpg_options }}--fetch-keys <a href="{{base_uri}}/vks/v1/by-fingerprint/{{ fpr }}">{{base_uri}}/vks/v1/by-fingerprint/{{ fpr }}</a></code></pre>
</div>
{{/layout}}

View File

@ -7,7 +7,7 @@
<body>
<p>
Someone, presumably you, has uploaded a key
to <a href="https://{{domain}}">{{domain}}</a>. The key has the
to <a href="{{base_uri}}">{{domain}}</a>. The key has the
following fingerprint:
</p>
<p>
@ -19,7 +19,7 @@
</p>
<p>
To make your key available when searching for "{{userid}}" on
{{domain}}, follow this link:
<a href="{{base_uri}}">{{domain}}</a>, follow this link:
</p>
<p>
<a href="{{uri}}">{{uri}}</a>

View File

@ -1,9 +1,10 @@
use std::path::PathBuf;
use failure;
use handlebars::Handlebars;
use lettre::{EmailTransport, SendmailTransport, FileEmailTransport};
use lettre_email::EmailBuilder;
use url;
use serde::Serialize;
use sequoia_openpgp as openpgp;
@ -17,18 +18,21 @@ mod context {
pub primary_fp: String,
pub uri: String,
pub userid: String,
pub base_uri: String,
pub domain: String,
}
#[derive(Serialize, Clone)]
pub struct Deletion {
pub uri: String,
pub base_uri: String,
pub domain: String,
}
}
pub struct Service {
from: String,
base_uri: String,
domain: String,
templates: Handlebars,
transport: Transport,
@ -41,26 +45,32 @@ enum Transport {
impl Service {
/// Sends mail via sendmail.
pub fn sendmail(from: String, domain: String, templates: Handlebars) -> Self {
Self {
from: from,
domain: domain,
templates: templates,
transport: Transport::Sendmail,
}
pub fn sendmail(from: String, base_uri: String, templates: Handlebars)
-> Result<Self> {
Self::new(from, base_uri, templates, Transport::Sendmail)
}
/// Sends mail by storing it in the given directory.
pub fn filemail(from: String, domain: String, templates: Handlebars,
pub fn filemail(from: String, base_uri: String, templates: Handlebars,
path: PathBuf)
-> Self
{
Self {
-> Result<Self> {
Self::new(from, base_uri, templates, Transport::Filemail(path))
}
fn new(from: String, base_uri: String, templates: Handlebars,
transport: Transport)
-> Result<Self> {
let domain =
url::Url::parse(&base_uri)
?.host_str().ok_or_else(|| failure::err_msg("No host in base-URI"))
?.to_string();
Ok(Self {
from: from,
base_uri: base_uri,
domain: domain,
templates: templates,
transport: Transport::Filemail(path),
}
transport: transport,
})
}
pub fn send_verification(&self, tpk: &openpgp::TPK, userid: &Email,
@ -68,8 +78,9 @@ impl Service {
-> Result<()> {
let ctx = context::Verification {
primary_fp: tpk.fingerprint().to_string(),
uri: format!("https://{}/publish/{}", self.domain, token),
uri: format!("{}/publish/{}", self.base_uri, token),
userid: userid.to_string(),
base_uri: self.base_uri.clone(),
domain: self.domain.clone(),
};
@ -84,7 +95,8 @@ impl Service {
pub fn send_confirmation(&self, userids: &[Email], token: &str)
-> Result<()> {
let ctx = context::Deletion {
uri: format!("https://{}/delete/{}", self.domain, token),
uri: format!("{}/delete/{}", self.base_uri, token),
base_uri: self.base_uri.clone(),
domain: self.domain.clone(),
};

View File

@ -141,7 +141,7 @@ mod templates {
pub query: String,
pub gpg_options: Option<&'static str>,
pub fpr: String,
pub domain: String,
pub base_uri: String,
pub commit: String,
pub version: String,
}
@ -194,7 +194,7 @@ pub struct State {
public_dir: PathBuf,
/// XXX
domain: String,
base_uri: String,
/// Controls the use of NGINX'es XAccelRedirect feature.
x_accel_redirect: bool,
@ -237,7 +237,7 @@ fn key_to_response<'a>(state: rocket::State<State>,
} else {
Some("--keyserver-options import-drop-uids ")
},
domain: state.domain.clone(),
base_uri: state.base_uri.clone(),
fpr: fp.to_string(),
version: env!("VERGEN_SEMVER").to_string(),
commit: env!("VERGEN_SHA_SHORT").to_string(),
@ -448,11 +448,11 @@ fn rocket_factory(rocket: rocket::Rocket) -> Result<rocket::Rocket> {
// State
let state_dir: PathBuf = rocket.config().get_str("state_dir")?.into();
let public_dir = state_dir.join("public");
let domain = rocket.config().get_str("domain")?.to_string();
let base_uri = rocket.config().get_str("base-URI")?.to_string();
let state = State {
state_dir: state_dir,
public_dir: public_dir,
domain: domain.clone(),
base_uri: base_uri.clone(),
x_accel_redirect: rocket.config().get_bool("x-accel-redirect")?,
};
@ -473,9 +473,9 @@ fn rocket_factory(rocket: rocket::Rocket) -> Result<rocket::Rocket> {
let filemail_into = rocket.config().get_str("filemail_into")
.ok().map(|p| PathBuf::from(p));
let mail_service = if let Some(path) = filemail_into {
mail::Service::filemail(from, domain, handlebars, path)
mail::Service::filemail(from, base_uri, handlebars, path)?
} else {
mail::Service::sendmail(from, domain, handlebars)
mail::Service::sendmail(from, base_uri, handlebars)?
};
Ok(rocket
@ -507,6 +507,9 @@ pub mod tests {
use database::*;
use super::*;
/// Fake base URI to use in tests.
const BASE_URI: &'static str = "http://local.connection";
/// Creates a configuration and empty state dir for testing purposes.
///
/// Note that you need to keep the returned TempDir alive for the
@ -533,7 +536,7 @@ pub mod tests {
root.path().to_str()
.ok_or(failure::err_msg("Static path invalid"))?,
)
.extra("domain", "domain")
.extra("base-URI", BASE_URI)
.extra("from", "from")
.extra("filemail_into", filemail.into_os_string().into_string()
.expect("path is valid UTF8"))
@ -834,9 +837,8 @@ pub mod tests {
}
fn check_mails_and_verify_email(client: &Client, filemail_path: &Path) {
let confirm_re =
regex::bytes::Regex::new("https://domain(/publish/[^ \t\n]*)")
.unwrap();
let confirm_re = regex::bytes::Regex::new(
&format!("{}(/publish/[^ \t\n]*)", BASE_URI)).unwrap();
let confirm_mail = pop_mail(filemail_path).unwrap().unwrap();
let confirm_bytes = confirm_mail.message();
// eprintln!("{}", String::from_utf8_lossy(&confirm_bytes));
@ -849,9 +851,8 @@ pub mod tests {
}
fn check_mails_and_confirm_deletion(client: &Client, filemail_path: &Path) {
let confirm_re =
regex::bytes::Regex::new("https://domain(/delete/[^ \t\n]*)")
.unwrap();
let confirm_re = regex::bytes::Regex::new(
&format!("{}(/delete/[^ \t\n]*)", BASE_URI)).unwrap();
let confirm_mail = pop_mail(filemail_path).unwrap().unwrap();
let confirm_bytes = confirm_mail.message();
// eprintln!("{}", String::from_utf8_lossy(&confirm_bytes));