attempt at fixing confirmation emails by setting email headers, link for manual confirmation email and cut next release #29

Merged
ben merged 8 commits from ben/Jobboerse:main into main 2022-06-10 15:36:51 +02:00
8 changed files with 16 additions and 52 deletions
Showing only changes of commit 46011bc8ba - Show all commits

enable the serde feature of the url dependency

- turns out the SerializableUrl wrapper was not necessary
Bennet Bleßmann 2022-06-10 15:00:13 +02:00 committed by Bennet Bleßmann
Signed by: ben
GPG key ID: 3BE1A1A3CBC3CF99

1
Cargo.lock generated
View file

@ -2523,6 +2523,7 @@ dependencies = [
"idna",
"matches",
"percent-encoding",
"serde",
]
[[package]]

View file

@ -48,7 +48,7 @@ tempfile = "3.3.0"
thiserror = "1.0.31"
toml = "0.5.9"
tokio = "1.18.2"
url = "2.2.2"
url = {version = "2.2.2", features = ["serde"]}
[build-dependencies]
cargo-bundle-licenses = { version = "0.5.0", default-features = false }

View file

@ -1,12 +1,12 @@
use crate::job_offers::error::EmailError;
use crate::server_config::EmailConfig;
use crate::template;
use crate::util::SerializableUrl;
use handlebars::Handlebars;
use lettre::message::header::{Header, HeaderName, HeaderValue, UserAgent};
use lettre::message::{Mailbox, SinglePart};
use lettre::{Address, AsyncTransport};
use log::warn;
use url::Url;
#[derive(Clone, Debug)]
struct AutoGeneratedHeader(String);
@ -37,7 +37,7 @@ fn user_agent() -> UserAgent {
#[derive(serde::Serialize)]
pub(crate) struct EmailData {
pub(crate) confirmation_link: SerializableUrl,
pub(crate) confirmation_link: Url,
}
pub(crate) async fn send_confirmation_email(

View file

@ -2,7 +2,6 @@ use crate::job_offers::{Attachment, JobOfferId, JobOfferStatus, Link};
use crate::route::{
JOBOFFER_DELETION_ROUTE, JOBOFFER_EDIT_ROUTE, JOBOFFER_PUBLISH_ROUTE, JOBOFFER_UNPUBLISH_ROUTE,
};
use crate::util::SerializableUrl;
use actix_web::error::UrlGenerationError;
use actix_web::HttpRequest;
use chrono::FixedOffset;
@ -20,7 +19,7 @@ pub(crate) struct JobOfferEditData {
pub(crate) expiry_date: Option<String>,
pub(crate) submission_date: String,
pub(crate) title: String,
pub(crate) attachments: Vec<Attachment<SerializableUrl>>,
pub(crate) attachments: Vec<Attachment<Url>>,
pub(crate) links: Vec<Option<Link>>,
}
@ -47,13 +46,9 @@ pub(crate) struct JobOfferViewData {
#[derive(serde::Serialize)]
pub struct JobOfferActions {
#[serde(serialize_with = "crate::util::url_as_string")]
publish_url: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
unpublish_url: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
delete_url: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
edit_url: Url,
}

View file

@ -29,7 +29,6 @@ pub(crate) use license::{LICENSES_ROUTE, LICENSE_BUNDLE};
use crate::error::PresentationError;
use crate::server_config::OperationMode;
use crate::server_config::ServerConfig;
use crate::util::SerializableUrl;
static HTML_CONTENT: HeaderValue = HeaderValue::from_static("text/html");
static JSON_CONTENT: HeaderValue = HeaderValue::from_static("application/json");
@ -60,7 +59,7 @@ struct BaseData<'a> {
title: Cow<'a, str>,
short_lang: Cow<'a, str>,
links: Vec<Link<'a>>,
styles: Vec<SerializableUrl>,
styles: Vec<Url>,
routes: StaticRoutes,
banner: Option<String>,
operation_mode: OperationMode,
@ -70,25 +69,15 @@ struct BaseData<'a> {
#[derive(Serialize)]
struct StaticRoutes {
#[serde(serialize_with = "crate::util::url_as_string")]
licenses: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
login: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
logout: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
sync: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
index: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
joboffer_overview: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
joboffer_create: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
joboffer_summary: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
joboffers_delete_expired: Url,
#[serde(serialize_with = "crate::util::url_as_string")]
joboffers_bulk_delete: Url,
}
@ -155,7 +144,10 @@ fn base<'a>(
.iter()
.map(|elem| {
default_links.retain(|&(title, _)| title != elem.title);
(elem.title.as_str(), elem.url.as_deref())
(
elem.title.as_str(),
elem.url.as_ref().map(|elem| elem.as_str()),
)
})
.collect::<Vec<_>>();

View file

@ -8,6 +8,7 @@ use handlebars::Handlebars;
use http::header::CONTENT_TYPE;
use serde::{Deserialize, Serialize};
use serde_json::json;
use url::Url;
pub(crate) mod confirmation;
pub(crate) mod create;
@ -24,7 +25,6 @@ use crate::route::job_offer::error::SyncResponseError;
use crate::route::{HTML_CONTENT, JSON_CONTENT};
use crate::server_config::ServerConfig;
use crate::template;
use crate::util::SerializableUrl;
pub fn configure(service: &mut ServiceConfig) {
service
@ -171,13 +171,13 @@ pub(crate) async fn summary(
struct SummaryData {
version: &'static str,
entries: Vec<JobOfferViewData>,
overview: SerializableUrl,
overview: Url,
}
let data = json!(SummaryData {
version: "1",
entries: previews,
overview: SerializableUrl(req.url_for_static(JOBOFFER_OVERVIEW_ROUTE)?)
overview: req.url_for_static(JOBOFFER_OVERVIEW_ROUTE)?
});
Ok(HttpResponse::Ok()

View file

@ -6,6 +6,7 @@ use log::{info, warn};
use serde::Deserialize;
use serde::Serialize;
use tokio::io::AsyncWriteExt;
use url::Url;
use crate::auth::LoginProviderConfig;
use crate::error::ConfigError;
@ -42,7 +43,7 @@ pub(crate) struct ProgramConfig {
pub(crate) struct Link {
pub(crate) title: String,
#[serde(default)]
pub(crate) url: Option<String>,
pub(crate) url: Option<Url>,
}
#[derive(Serialize, Deserialize, Debug)]

View file

@ -1,10 +1,9 @@
use crate::job_offers::{Attachment, Link};
use better_toml_datetime::Offset;
use chrono::{DateTime, FixedOffset, NaiveDate, Offset as _, TimeZone, Utc};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::{Deserialize, Deserializer};
use std::str::FromStr;
use tempfile::NamedTempFile;
use url::Url;
// we basically don't do any proper error handling here,
// as we mostly expect the format conversion to be infallible
@ -138,30 +137,6 @@ where
<Option<String> as Deserialize>::deserialize(des).map(|option| option.is_some())
}
pub(crate) fn url_as_string<S>(url: &Url, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(url.as_str())
}
#[derive(Serialize)]
pub(crate) struct SerializableUrl(
#[serde(serialize_with = "crate::util::url_as_string")] pub url::Url,
);
impl From<Url> for SerializableUrl {
fn from(url: Url) -> Self {
Self(url)
}
}
impl From<SerializableUrl> for Url {
fn from(SerializableUrl(url): SerializableUrl) -> Self {
url
}
}
pub(crate) fn parse_date(
input: Option<&str>,
) -> Result<Option<better_toml_datetime::Date>, <better_toml_datetime::Date as FromStr>::Err> {