hagrid-keyserver--hagrid/src/web/manage.rs

161 lines
4.9 KiB
Rust
Raw Normal View History

2019-04-05 15:07:40 +00:00
use rocket;
use rocket::State;
use rocket::request::Form;
use failure::Fallible as Result;
use web::{MyResponse,templates::General};
use database::{Database, Polymorphic};
use database::types::Email;
use mail;
use tokens;
mod templates {
#[derive(Serialize)]
pub struct ManageKey {
// pub uid_unpublished: Option<String>,
pub uid_status: Vec<ManageKeyUidStatus>,
pub token: String,
pub commit: String,
pub version: String,
}
#[derive(Serialize)]
pub struct ManageLinkSent {
pub address: String,
}
#[derive(Serialize)]
pub struct ManageKeyUidStatus {
pub address: String,
pub published: bool,
}
}
pub mod forms {
#[derive(FromForm)]
pub struct ManageRequest {
pub search_term: String,
}
#[derive(FromForm)]
pub struct ManageDelete {
pub token: String,
pub address: String,
}
}
2019-04-25 18:04:20 +00:00
#[get("/manage")]
2019-04-05 15:07:40 +00:00
pub fn vks_manage() -> Result<MyResponse> {
Ok(MyResponse::ok("manage/manage", General::default()))
}
2019-04-25 18:04:20 +00:00
#[get("/manage/<token>")]
2019-04-05 15:07:40 +00:00
pub fn vks_manage_key(
db: State<Polymorphic>,
token: String,
token_service: rocket::State<tokens::Service>,
) -> MyResponse {
if let Ok(fingerprint) = token_service.check(&token) {
match db.lookup(&database::Query::ByFingerprint(fingerprint)) {
Ok(Some(tpk)) => {
let mut emails: Vec<Email> = tpk.userids()
.map(|u| u.userid().to_string().parse::<Email>())
.flatten()
.collect();
emails.sort_unstable();
emails.dedup();
let uid_status = emails.into_iter().map(|email|
templates::ManageKeyUidStatus {
address: email.to_string(),
published: true,
}
).collect();
let context = templates::ManageKey {
uid_status,
token,
version: env!("VERGEN_SEMVER").to_string(),
commit: env!("VERGEN_SHA_SHORT").to_string(),
};
MyResponse::ok("manage/manage_key", context)
},
Ok(None) => MyResponse::not_found(
Some("manage/manage"),
Some("This link is invalid or expired".to_owned())),
Err(e) => MyResponse::ise(e),
}
} else {
MyResponse::ok("manage/manage_expired", General::default())
}
}
2019-04-25 18:04:20 +00:00
#[post("/manage", data="<request>")]
2019-04-05 15:07:40 +00:00
pub fn vks_manage_post(
db: State<Polymorphic>,
request: Form<forms::ManageRequest>,
token_service: rocket::State<tokens::Service>,
mail_service: Option<rocket::State<mail::Service>>,
) -> MyResponse {
use std::convert::TryInto;
let email = match request.search_term.parse::<Email>() {
Ok(email) => email,
Err(_) => return MyResponse::not_found(
Some("manage/manage"),
Some(format!("Malformed email address: {:?}", request.search_term)))
};
let tpk = match db.lookup(&database::Query::ByEmail(email.clone())) {
Ok(Some(tpk)) => tpk,
Ok(None) => return MyResponse::not_found(
Some("manage/manage"),
Some(format!("No key for address {:?}", request.search_term))),
Err(e) => return MyResponse::ise(e),
};
let fpr = tpk.fingerprint().try_into().unwrap();
let token = token_service.create(&fpr);
let token_uri = uri!(vks_manage_key: token).to_string();
if let Some(mail_service) = mail_service {
for binding in tpk.userids() {
let email_candidate = binding.userid().to_string().parse::<Email>();
if let Ok(email_candidate) = email_candidate {
if &email_candidate != &email {
continue;
}
if let Err(e) = mail_service.send_manage_token(
&[email_candidate], &token_uri) {
return MyResponse::ise(e);
}
}
}
}
let ctx = templates::ManageLinkSent {
address: email.to_string(),
};
MyResponse::ok("manage/manage_link_sent", ctx)
}
2019-04-25 18:04:20 +00:00
#[post("/manage/unpublish", data="<request>")]
2019-04-05 15:07:40 +00:00
pub fn vks_manage_unpublish(
db: rocket::State<Polymorphic>,
token_service: rocket::State<tokens::Service>,
request: Form<forms::ManageDelete>,
) -> MyResponse {
match vks_manage_unpublish_or_fail(db, token_service, request) {
Ok(response) => response,
Err(e) => MyResponse::ise(e),
}
}
pub fn vks_manage_unpublish_or_fail(
db: rocket::State<Polymorphic>,
token_service: rocket::State<tokens::Service>,
request: Form<forms::ManageDelete>,
) -> Result<MyResponse> {
let fpr = token_service.check(&request.token)?;
let email = request.address.parse::<Email>()?;
db.delete_userids_matching(&fpr, &email)?;
Ok(vks_manage_key(db, request.token.to_owned(), token_service))
}