aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2018-11-13 15:51:09 +0100
committerTeddy Wing2018-11-13 15:51:09 +0100
commit2fe4c73ed2a96bf93075aa8448d0f862f2300371 (patch)
tree5dd5e07ef805020a4c3daa41d6727ac079ac21f5
parentffdabdb4ab1be347a011211cf54ecd0d27f9cf1b (diff)
downloaddome-key-web-2fe4c73ed2a96bf93075aa8448d0f862f2300371.tar.bz2
license: Extract response logic from `/license/download`
I want to be able to use the exact same logic for the `/license` route. To do so, we move the common logic to a new `build_response()` function. For all responses we need to return from `build_response()`, make new structs `HtmlResponse` and `ZipResponse` that write the response in the desired format. The `ZipResponse` does what we're already doing in `/license/download`. The `HtmlResponse` will respond with HTML and show a thank-you page on success.
-rw-r--r--license-generator/src/bin/license.rs194
1 files changed, 123 insertions, 71 deletions
diff --git a/license-generator/src/bin/license.rs b/license-generator/src/bin/license.rs
index 859ddfa..4e3c42b 100644
--- a/license-generator/src/bin/license.rs
+++ b/license-generator/src/bin/license.rs
@@ -26,6 +26,9 @@ use license_generator::params;
use license_generator::response;
use license_generator::zip;
+const PUBLIC_KEY: &'static str = include_str!("../../private/public_key.txt");
+const PRIVATE_KEY: &'static str = include_str!("../../private/private_key.txt");
+
#[derive(Serialize)]
struct LicenseData<'a> {
#[serde(rename = "Name")]
@@ -35,6 +38,76 @@ struct LicenseData<'a> {
email: &'a str,
}
+trait LicenseValidationResponse {
+ fn success(&mut self, name: &str, email: &str);
+ fn error_400(&mut self);
+ fn error_404(&mut self);
+ fn error_500(&mut self, error: Option<Error>);
+}
+
+struct HtmlResponse<'a, W: 'a> {
+ writer: &'a mut W,
+}
+
+impl<'a, W> LicenseValidationResponse for HtmlResponse<'a, W>
+where W: 'a + Write {
+ fn success(&mut self, name: &str, email: &str) {
+ }
+
+ fn error_400(&mut self) {
+ }
+
+ fn error_404(&mut self) {
+ }
+
+ fn error_500(&mut self, error: Option<Error>) {
+ }
+}
+
+struct ZipResponse<'a, W: 'a> {
+ writer: &'a mut W,
+}
+
+impl<'a, W> LicenseValidationResponse for ZipResponse<'a, W>
+where W: 'a + Write {
+ fn success(&mut self, name: &str, email: &str) {
+ let license_data = LicenseData {
+ name: &name,
+ email: &email,
+ };
+
+ let aquatic_prime = AquaticPrime::new(&PUBLIC_KEY, &PRIVATE_KEY);
+ let license = match aquatic_prime.plist(license_data) {
+ Ok(p) => p,
+ Err(e) => return self.error_500(Some(e.into())),
+ };
+
+ let mut zip_data = Cursor::new(vec![]);
+ match zip::license(&mut zip_data, license.as_bytes()) {
+ Ok(p) => p,
+ Err(e) => return self.error_500(Some(e.into())),
+ }
+
+ write!(self.writer, "Content-Type: application/zip
+Content-Disposition: attachment; filename=\"dome-key-license.zip\"\n\n")
+ .and_then(|_|
+ self.writer.write_all(&zip_data.into_inner())
+ ).unwrap_or(());
+ }
+
+ fn error_400(&mut self) {
+ response::error_400(self.writer);
+ }
+
+ fn error_404(&mut self) {
+ response::error_404(self.writer);
+ }
+
+ fn error_500(&mut self, error: Option<Error>) {
+ response::error_500(self.writer, error)
+ }
+}
+
fn query_purchaser(
cx: &mut mysql::PooledConn,
name: &str,
@@ -62,6 +135,48 @@ fn query_purchaser(
Ok(row)
}
+fn build_response<'a, R: LicenseValidationResponse>(
+ cx: &mut mysql::PooledConn,
+ params: &str,
+ responses: &mut R,
+) {
+ let params = params::parse(&params);
+ let name = params.get("name");
+ let email = params.get("email");
+ let secret = params.get("secret");
+
+ if name.is_some() && email.is_some() && secret.is_some() {
+ let name = name.unwrap().to_string();
+ let email = email.unwrap().to_string();
+ let secret = secret.unwrap().to_string();
+
+ let purchaser = match query_purchaser(cx, &name, &email, &secret) {
+ Ok(p) => p,
+ Err(e) => return responses.error_500(Some(e.into())),
+ };
+
+ if let Some(purchaser) = purchaser {
+ match purchaser {
+ Ok(p) => p,
+ Err(e) => return responses.error_500(Some(e.into())),
+ };
+
+ return responses.success(&name, &email);
+ } else {
+ return responses.error_404();
+ }
+ } else {
+ error!(
+ "Missing request parameters: name: '{}', email: '{}', secret: '{}'",
+ name.unwrap_or(&Cow::Borrowed("")),
+ email.unwrap_or(&Cow::Borrowed("")),
+ secret.unwrap_or(&Cow::Borrowed("")),
+ );
+
+ return responses.error_400();
+ }
+}
+
fn main() -> Result<()> {
logger::init()?;
@@ -75,10 +190,6 @@ fn main() -> Result<()> {
},
};
- let public_key = include_str!("../../private/public_key.txt");
- let private_key = include_str!("../../private/private_key.txt");
- let aquatic_prime = AquaticPrime::new(&public_key, &private_key);
-
fastcgi::run(move |mut req| {
let mut params = String::new();
match req.stdin().read_to_string(&mut params) {
@@ -103,6 +214,12 @@ fn main() -> Result<()> {
"/license" => {
// Get params name, email, secret
// Render thank-you page with link to download file
+ let params = req.param("QUERY_STRING").unwrap();
+ let mut responses = HtmlResponse { writer: &mut req.stdout() };
+ return build_response(&mut cx, &params, &mut responses);
+
+ // TODO: Extract from /license/download
+ // trait for HTML vs. text/zip
},
// Respond with a zip archive of the license file
@@ -118,73 +235,8 @@ fn main() -> Result<()> {
},
};
- let ps = params::parse(&params);
- let name = ps.get("name");
- let email = ps.get("email");
- let secret = ps.get("secret");
-
- if name.is_some() && email.is_some() && secret.is_some() {
- let name = name.unwrap().to_string();
- let email = email.unwrap().to_string();
- let secret = secret.unwrap().to_string();
-
- let purchaser = match query_purchaser(&mut cx, &name, &email, &secret) {
- Ok(p) => p,
- Err(e) => return response::error_500(
- &mut req.stdout(),
- Some(e.into())
- ),
- };
-
- if let Some(purchaser) = purchaser {
- match purchaser {
- Ok(p) => p,
- Err(e) => return response::error_500(
- &mut req.stdout(),
- Some(e.into())
- ),
- };
-
- let license_data = LicenseData {
- name: &name,
- email: &email,
- };
-
- let license = match aquatic_prime.plist(license_data) {
- Ok(p) => p,
- Err(e) => return response::error_500(
- &mut req.stdout(),
- Some(e.into())
- ),
- };
-
- let mut zip_data = Cursor::new(vec![]);
- match zip::license(&mut zip_data, license.as_bytes()) {
- Ok(p) => p,
- Err(e) => return response::error_500(
- &mut req.stdout(),
- Some(e.into())
- ),
- }
-
- write!(&mut req.stdout(), "Content-Type: application/zip
-Content-Disposition: attachment; filename=\"dome-key-license.zip\"\n\n")
- .and_then(|_|
- req.stdout().write_all(&zip_data.into_inner())
- ).unwrap_or(());
- } else {
- return response::error_404(&mut req.stdout());
- }
- } else {
- error!(
- "Missing request parameters: name: '{}', email: '{}', secret: '{}'",
- name.unwrap_or(&Cow::Borrowed("")),
- email.unwrap_or(&Cow::Borrowed("")),
- secret.unwrap_or(&Cow::Borrowed("")),
- );
-
- return response::error_400(&mut req.stdout());
- }
+ let mut responses = ZipResponse { writer: &mut req.stdout() };
+ return build_response(&mut cx, &params, &mut responses);
},
_ => (),
}