[Draft] Implement Early deletion by Submitter #37 #38

Merged
ben merged 15 commits from ben/Jobboerse:main into main 2023-01-28 18:00:00 +01:00
18 changed files with 422 additions and 324 deletions
Showing only changes of commit 0b92710d3c - Show all commits

large dependencies update

Bennet Bleßmann 2022-10-08 01:04:36 +02:00 committed by Bennet Bleßmann
Signed by: ben
GPG key ID: 3BE1A1A3CBC3CF99

485
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,36 +1,28 @@
[workspace]
members = [".", "packages/*"]
[package]
name = "jobboerse"
version = "0.2.4"
[workspace.package]
version = "0.2.5"
edition = "2021"
rust-version = "1.60"
license = "MIT OR Apache-2.0"
include = ["APACHE-2.0.LICENSE","MIT.LICENSE"]
repository = "https://www.fs-infmath.uni-kiel.de/git/FS-InfMath/Jobboerse"
homepage = "https://www.fs-infmath.uni-kiel.de/wiki/Hauptseite"
license = "MIT OR Apache-2.0"
readme = "README.md"
categories = ["command-line-utilities", "web-programming::http-server"] # https://crates.io/category_slugs max. 5
keywords = ["jobbörse", "webserver", "application"] # max 5. matching [a-zA-Z][a-zA-Z0-9-_]{,19}
description = "This package provides a webserver for joboffser postings"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
dev_mode = []
[dependencies]
[workspace.dependencies]
actix-files = "0.6.2"
actix-web = "4.1.0"
actix-session = { version = "0.7.1", features = ["cookie-session"] }
actix-web = "4.2.1"
actix-session = { version = "0.7.2", features = ["cookie-session"] }
actix-multipart = "0.4.0"
better_toml_datetime = { path = "packages/better_toml_datetime" }
cargo-bundle-licenses = { version = "0.5.0", default-features = false }
chrono = { version = "0.4.20", default-features = false, features = ["std","clock"] }
cargo-bundle-licenses = { version = "1.0.1", default-features = false }
chrono = { version = "0.4.22", default-features = false, features = ["std","clock"] }
chrono-tz = "0.6.3"
clap = { version = "3.2.16", features = ["derive", "env"] }
futures-util = "0.3.21"
handlebars = { version = "4.3.3", features = ["dir_source"] }
clap = { version = "4.0.10", features = ["derive", "env"] }
futures-util = "0.3.24"
handlebars = { version = "4.3.5", features = ["dir_source"] }
http = "0.2.8"
lettre = { version = "0.10.1", default-features = false, features = ["sendmail-transport", "tokio1", "builder", "serde"] }
# use rustls a native tls library rather than openssl,
@ -42,18 +34,68 @@ mime_guess = "2.0.4"
multipart_helper = {path = "packages/multipart_helper"}
pretty_env_logger = "0.4.0"
rand = "0.8.5"
serde = { version = "1.0.142", features = ["derive"] } # https://doc.rust-lang.org/cargo/reference/manifest.html
serde_json = "1.0.83"
serde = { version = "1.0.145", features = ["derive"] } # https://doc.rust-lang.org/cargo/reference/manifest.html
serde_json = "1.0.85"
tempfile = "3.3.0"
thiserror = "1.0.32"
thiserror = "1.0.37"
toml = "0.5.9"
tokio = "1.20.1"
url = { version = "2.2.2", features = ["serde"] }
tokio = "1.21.2"
url = { version = "2.3.1", features = ["serde"] }
[package]
name = "jobboerse"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
repository.workspace = true
homepage.workspace = true
license.workspace = true
readme.workspace = true
categories = ["command-line-utilities", "web-programming::http-server"] # https://crates.io/category_slugs max. 5
keywords = ["jobbörse", "webserver", "application"] # max 5. matching [a-zA-Z][a-zA-Z0-9-_]{,19}
description = "This package provides a webserver for joboffser postings"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
dev_mode = []
[dependencies]
actix-files = { workspace = true }
actix-web = { workspace = true }
actix-session = { workspace = true, features = ["cookie-session"] }
actix-multipart = { workspace = true }
better_toml_datetime = { workspace = true }
cargo-bundle-licenses = { workspace = true, default-features = false }
chrono = { workspace = true, default-features = false, features = ["std","clock"] }
chrono-tz = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
futures-util = { workspace = true }
handlebars = { workspace = true, features = ["dir_source"] }
http = { workspace = true }
lettre = { workspace = true, default-features = false, features = ["sendmail-transport", "tokio1", "builder", "serde"] }
# use rustls a native tls library rather than openssl,
# as depending on c dependencies can get annoying even when vendoring
ldap3 = { workspace = true, default-features = false, features = ["tls-rustls"] }
listenfd = { workspace = true }
log = { workspace = true }
mime_guess = { workspace = true }
multipart_helper = { workspace = true }
pretty_env_logger = { workspace = true }
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] } # https://doc.rust-lang.org/cargo/reference/manifest.html
serde_json = { workspace = true }
tempfile = { workspace = true }
thiserror = { workspace = true }
toml = { workspace = true }
tokio = { workspace = true }
url = { workspace = true, features = ["serde"] }
[build-dependencies]
cargo-bundle-licenses = { version = "0.5.0", default-features = false }
pretty_env_logger = "0.4.0"
log = "0.4.17"
cargo-bundle-licenses = { workspace = true, default-features = false }
pretty_env_logger = { workspace = true }
log = { workspace = true }
# manually specify autobin here as otherwise some command freak out if we don't copy the src/ folder
[[bin]]

View file

@ -7,37 +7,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.2.4] (2022-08-04)
### Fix
- missing lines around lists and headings triggering lints in changelog
- new clippy lints
### Change
- upgrade/update dependencies
- msrv is now 1.64 as we now take advantage of packages inheriting from the workspace
### Removed
- `./scripts/adjust_thirdparty.sh` as it is no longer necessary with cargo-bundle-license version 1.0.0
## [0.2.4] (2022-08-04)
### Change
- reviewer notice now includes a link to the added job offer
- upgrade dependencies in general
### Fix
- confirmation dialog for when logged-in as a reviewer
- updated chrono dependency fixing issue FS-InfMath/Jobboerse#5
## [0.2.3] (2022-07-27)
### Change
- upgrade lettre dependency from release candidate version to actual release version
- upgrade dependencies in general
- send a publishing notice to the contact address when a submission is published by a review
- make the job offer id a link to the highlight link
- make the job offer id a link to the highlight link
## [0.2.2] (2022-06-26)
### Add
- faq page
### Change
- better highlight confirm/retract buttons
## [0.2.1] (2022-03-10)
### Add
### Add
- reviewer link for manually sending a confirmation email
### Change
- some internal cleanup
- reviewer notice email is now send when offer is not pre-approved
- instead of when confirmation is not skipped
@ -46,6 +68,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
while reviewer notice failure is not
### Fix
- confirmation emails now set the UserAgent and Auto-Submitted headers
- the error pages using the generic_error_handler now set the Content-Type header
- prevent error on missing edit action
@ -54,81 +77,96 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.2.0] (2022-06-09)
### Add
- ability to edit job offers by reviewers after submission
- ability for reviewers to filter for offer requiring review
- ability to change/remove default footer links and add new ones
- ability to highlight a single job offer
### Change
- improve error handling
- split of two small packages
- split of two small packages
- a lot of refactoring
- update/upgrade dependencies
- reviewer-only settings when not logged in are now an error rather than being silently ignored
- delete expired will now goto a preview instead of deleting directly
- change the format of the summary endpoint
- the top-level is now an object instead of a list
- the top-level is now an object instead of a list
- the top-level list is not the entries field of the top-level object
- an additional version field is added
- also an overview field is added with the url of job offer overview
## [0.1.6] (2022-05-26)
### Change
### Change
- increase some form limits
## [0.1.5] (2022-05-26)
### Change
- some display/style changes for job offer entries
- the confirmation email now uses a handlebar template instead of a compiletime format constant string
### Fix
- /summary should be accessible for anonymous visitors
## [0.1.4] (2022-05-25)
### Fix
### Fix
- replace incorrectly hardcoded path by config value
## [0.1.3] (2022-05-25)
### Add
- allow reviewers to skip confirmation of new submissions
- allow reviewers to delete all expired entries
### Change
- minimum expiry date for new submissions is now kept up-to-date
- submission form for reviewers now defaults to pre-reviewed and skip-confirmation
### Fix
- index route without base path
- simple login provider should not skip setting the session cookie
## [0.1.2] (2022-05-25)
### Add
- systemd service file
### Change
- improve distribution config
- set storage path in distribution config
- reduce default log level from Trace to Info
### Fix
- incorrect table name in distribution config
## [0.1.1] (2022-05-25)
### Added
### Added
- commented default config for distributing
### Change
- strip release build
## [0.1.0] (2022-05-21)
### Added
- Initial Version
- Overview/Landing Page of published Job Offers
- Reviewer Login with LDAP Integration

View file

@ -11,12 +11,12 @@ Instructions on how to install rustup, the standard toolchain manager for rust,
The minimum required rust-toolchain version as of writing is `1.58` see the `rust-version` entry in the `Cargo.toml` file.
A stable toolchain is recommended.
It is recommended to use cargo for building as such make sure the `cargo` component of the toolchain is installed.
It is recommended to use cargo for building as such make sure the `cargo` component of the toolchain is installed.
It may be necessary to run `./scripts/adjust_thirdparty.sh` to adjust some absolute paths in the `THIRDPARTY.toml`,
though this should only be required to run tests.
For a release build you can run `cargo build --release` this should build all dependencies and place the final binary in
For a release build you can run `cargo build --release` this should build all dependencies and place the final binary in
the `./target/release/` folder.
For a development build you may run `cargo build --features=dev-mode`.
@ -49,7 +49,7 @@ in the [`env_logger` documnentation](https://docs.rs/env_logger/0.7.1/env_logger
Note: Currently the documentation for version 0.7.1 is relevant, even if it not the newest version.
An update of `pretty_env_logger` should hopefully be available soon to change this.
See [PR 49](https://github.com/seanmonstar/pretty-env-logger/pull/49) in the pretty_env_logger repo, which updates the env_logger dependency.
Config
------
The config file uses the toml format.
@ -58,7 +58,7 @@ The expected fields are defined by the `ProgramConfig` struct in `./src/server_c
| config field | required | default |
|---------------------|----------|----------------|
| `url_base_path` | false | empty |
| `data_storage_path` | false | `./job_offers` |
| `data_storage_path` | false | `./job_offers` |
| `banner` | false | no banner |
| `login_provider` | true | N/A |
| `email` | false | no email |
@ -67,11 +67,11 @@ Note: when email is not configured, no confirmation e-mails will be sent, but co
For `login_provider` there are four types available: `Ldap`, `Simple`, `Disabled`, and `Development`.
The last of which is only available when build with the `dev-mode` feature.
Selecting a specific type is done by setting the `type` field to the name of the login provider, this is case-sensitive.
Selecting a specific type is done by setting the `type` field to the name of the login provider, this is case-sensitive.
`Disabled` and `Development` have no further options.
The `Simple` login provider requires the `file_path` to be set, which points to a toml file containing
The `Simple` login provider requires the `file_path` to be set, which points to a toml file containing
a `users` table.
The table keys are then used as usernames and the associated values are expected to be strings containing plaintext passwords.
@ -87,18 +87,14 @@ The `dap_user_filter` specifies a filter pattern for an ldap search, `%{username
This file is generated using the `cargo-bundle-licenses` tool and contains license information for all third-party dependencies.
It is manually adjusted to include all not auto-detected licenses.
When re-generating this file make sure to not lose still relevant manually inserted licenses and to add newly missing licenses.
When re-generating this file make sure to not lose still relevant manually inserted licenses and to add newly missing licenses.
Currently, `cargo-bundle-licenses` includes absolute paths for some licenses.
These will differ between machines and usual point into the current user's home directory.
Wrong paths might cause the test, which checks that the `THIRDPARTY.toml` file is up-to-date, to fail.
The `./scripts/adjust_thirdparty.sh` script should fix the paths to match the current environment.
Alternatively, the `THIRDPARTY.toml` may be regenerated as described below.
Regenerating this file usually requires some manual intervention, to fix licenses that were not automatically detected.
To regenerate this file the cargo-bundle-licenses tool needs to be available.
It can be installed via `cargo install cargo-bundle-licenses`.
At least version 0.5.0, as of writing the latest version, is required, for proper handling of complex spdx expressions.
At least version 1.0.0, is required, for normalization of license file path located under `$CARGO_HOME`.
It can then be run with `cargo bundle-licenses --format toml --output THIRDPARTY.toml` to re-generate the file.
The script `./scripts/generate_thirparty.sh` does just that.
This needs to be done when dependencies change to adjust the corresponding entries.
@ -107,7 +103,7 @@ Make sure to look for entries for which the license text is listed as `NOT FOUND
Testing
-------
General Tests: `cargo test`
General Tests: `cargo test`
Check Formatting: `cargo fmt --check`

BIN
THIRDPARTY.toml (Stored with Git LFS)

Binary file not shown.

2
dist/arch/PKGBUILD vendored
View file

@ -33,8 +33,6 @@ prepare()
git lfs pull lfs-remote
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
./scripts/adjust_thirdparty.sh
}

View file

@ -43,8 +43,6 @@ prepare()
git lfs pull lfs-remote
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
./scripts/adjust_thirdparty.sh
}

View file

@ -1,13 +1,19 @@
[package]
name = "better_toml_datetime"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
include = ["../../APACHE-2.0.LICENSE","../../MIT.LICENSE"]
description = "Small helper crate for usage in the jobboerse crate containing some helpers for working with toml date, datetime and time structs"
keywords = ["toml", "date", "time"]
categories = []
version.workspace = true
edition.workspace = true
rust-version.workspace = true
repository.workspace = true
homepage.workspace = true
license.workspace = true
readme.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = "1.0.137"
toml = "0.5.9"
thiserror = "1.0.31"
serde = { workspace = true }
toml = { workspace = true }
thiserror = { workspace = true }

View file

@ -3,7 +3,6 @@ use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::str::FromStr;
use thiserror;
use toml::value::DatetimeParseError;
#[derive(Serialize, Deserialize, Clone)]

View file

@ -1,15 +1,21 @@
[package]
name = "multipart_helper"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
include = ["../../APACHE-2.0.LICENSE", "../../MIT.LICENSE"]
description = "A helper crate for handling multipart forms in the jobbörse create"
keywords = ["multipart/form-data"]
categories = []
version.workspace = true
edition.workspace = true
rust-version.workspace = true
repository.workspace = true
homepage.workspace = true
license.workspace = true
readme.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-multipart = "0.4.0"
futures-util = "0.3.21"
tempfile = "3.3.0"
thiserror = "1.0.31"
toml = "0.5.9"
actix-multipart = { workspace = true }
futures-util = { workspace = true }
tempfile = { workspace = true }
thiserror = { workspace = true }
toml = { workspace = true }

View file

@ -1,6 +0,0 @@
#!/usr/bin/env bash
# workaround for https://github.com/sstadick/cargo-bundle-licenses/issues/8
CARGO_HOME="${CARGO_HOME:-${HOME}/.cargo}"
sed --in-place=.bak -E "\:file \(.*/\.cargo/:{s:file \(.*/\.cargo/:file \(${CARGO_HOME}/:g;}" ./THIRDPARTY.toml

View file

@ -364,7 +364,7 @@ impl JobOffer<PathBuf> {
Ok(Attachment {
title: attachment.title.clone(),
file_name: attachment.file_name.clone(),
attachment_location: attachment.generate_link(id, req, None)?.into(),
attachment_location: attachment.generate_link(id, req, None)?,
})
})
.collect::<Result<Vec<_>, UrlGenerationError>>()?;
@ -734,7 +734,7 @@ impl<'id> MutBorrowedJobOffer<'_, 'id, '_> {
}
pub(crate) fn mark_as_confirmed(&mut self, token: &str) -> Result<(), ()> {
let () = self.data.status.mark_as_confirmed(token)?;
self.data.status.mark_as_confirmed(token)?;
self.dirty = Dirty::Yes;
Ok(())
}

View file

@ -125,7 +125,7 @@ fn base<'a>(
config: &'a ServerConfig,
title: &'a str,
) -> Result<BaseData<'a>, UrlGenerationError> {
let index_css = req.url_for_static(INDEX_CSS_ROUTE)?.into();
let index_css = req.url_for_static(INDEX_CSS_ROUTE)?;
let static_routes = StaticRoutes::new(req)?;
@ -134,7 +134,7 @@ fn base<'a>(
Some("https://www.fs-infmath.uni-kiel.de/wiki/Fachschaften_Informatik_%26_Mathematik:Impressum".into()),
),
(
"Homepage",
"Homepage",
crate::PROJECT_HOMEPAGE.map(Into::into)
),
(

View file

@ -22,7 +22,6 @@ use lettre::address::AddressError;
use log::{error, warn};
use multipart_helper::MultipartFieldError;
use serde_json::json;
use thiserror::private::DisplayAsDisplay;
use url::Url;
#[derive(Debug, thiserror::Error)]
@ -274,7 +273,7 @@ pub(crate) fn unauthorized_error_handler<B>(
// for a get request we can just return the user to the originally requested page after login,
// so redirect them to the login page and set the return_to url parameter to the target of the current request
let req_uri = res.request().uri().as_display().to_string();
let req_uri = res.request().uri().to_string();
let login_url = login_url_with_return(res.request(), &req_uri)?;

View file

@ -70,4 +70,4 @@ pub(crate) const ATTACHMENT_FILENAME_EDIT_FIELD: &str = "file_name_edit[]";
pub(crate) const ATTACHMENT_TITLE_EDIT_FIELD: &str = "file_title_edit[]";
pub(crate) const ATTACHMENT_FILE_REPLACE_FIELD: &str = "file_replace[]";
pub(crate) const DELETE_ATTACHMENT_FIELD: &'static str = "delete_attachment[]";
pub(crate) const DELETE_ATTACHMENT_FIELD: &str = "delete_attachment[]";

View file

@ -252,7 +252,7 @@ pub(crate) async fn create_job_offer<'data, 'config>(
if !is_pre_approved {
match created_offer.highlight_link(req) {
Ok(highlight_url) => {
email::send_reviewer_notice(hb, &email_config, highlight_url).await;
email::send_reviewer_notice(hb, email_config, highlight_url).await;
}
Err(err) => {
error!("Failed to generate highlight link: {}", err)
@ -268,7 +268,7 @@ pub(crate) async fn create_job_offer<'data, 'config>(
job_offer_form.contact,
email_config,
&ConfirmationEmailData {
confirmation_link: confirm_url.into(),
confirmation_link: confirm_url,
},
)
.await?;

View file

@ -1,6 +1,6 @@
use std::path::{Path, PathBuf};
use clap::{ArgEnum, StructOpt};
use clap::{Parser, ValueEnum};
use lettre::message::Mailbox;
use log::{info, warn};
use serde::Deserialize;
@ -95,7 +95,7 @@ impl ProgramConfig {
}
}
#[derive(StructOpt, Debug)]
#[derive(Parser, Debug)]
#[structopt(name = "jobboerse", version)]
pub(crate) struct ProgramArguments {
#[structopt(long, env = "JOBBOERSE_CONFIG", default_value_os_t = ProgramArguments::default_config())]
@ -104,7 +104,7 @@ pub(crate) struct ProgramArguments {
#[structopt(short, long, env = "JOBBOERSE_PORT", default_value_t = 8080)]
pub(crate) port: u16,
#[structopt(long, env = "JOBBOERSE_MODE", arg_enum, default_value_t)]
#[structopt(long, env = "JOBBOERSE_MODE", value_enum, default_value_t)]
pub(crate) mode: OperationMode,
}
@ -132,7 +132,7 @@ impl ProgramArguments {
}
}
#[derive(Debug, Clone, ArgEnum, Serialize)]
#[derive(Debug, Clone, ValueEnum, Serialize)]
pub(crate) enum OperationMode {
Production,
#[cfg(feature = "dev_mode")]

View file

@ -81,16 +81,15 @@ pub fn toml_datetime_to_chrono_datetime(
.date
.as_ref()
.expect("datetime should contain a date");
let toml_time = datetime.time.to_owned().unwrap_or(
// fallback to midnight
let toml_time = datetime.time.to_owned().unwrap_or_else(|| {
toml::value::Time {
hour: 0,
minute: 0,
second: 0,
nanosecond: 0,
}
.into(),
);
.into()
});
let local_datetime = chrono::NaiveDate::from_ymd(
toml_date.year.into(),