add generate vapid subcommand

This commit is contained in:
naskya 2024-06-25 11:59:42 +09:00
parent 1d38d4c4df
commit 57bcd5a312
Signed by: naskya
GPG key ID: 712D413B3A9FED5C
7 changed files with 169 additions and 2 deletions

118
Cargo.lock generated
View file

@ -139,6 +139,12 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.7" version = "0.21.7"
@ -393,6 +399,15 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.7" version = "0.10.7"
@ -495,6 +510,7 @@ dependencies = [
"toml", "toml",
"url", "url",
"validator", "validator",
"vapid",
"yaml-rust", "yaml-rust",
] ]
@ -515,6 +531,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.2.1" version = "1.2.1"
@ -895,6 +926,12 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.46" version = "0.1.46"
@ -950,6 +987,44 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "openssl"
version = "0.10.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
dependencies = [
"bitflags 2.5.0",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]]
name = "openssl-sys"
version = "0.9.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.3" version = "0.12.3"
@ -1033,6 +1108,12 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"
@ -1459,7 +1540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64", "base64 0.21.7",
"bitflags 2.5.0", "bitflags 2.5.0",
"byteorder", "byteorder",
"bytes", "bytes",
@ -1501,7 +1582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64", "base64 0.21.7",
"bitflags 2.5.0", "bitflags 2.5.0",
"byteorder", "byteorder",
"crc", "crc",
@ -1632,6 +1713,25 @@ dependencies = [
"syn 2.0.66", "syn 2.0.66",
] ]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"num-conv",
"powerfmt",
"serde",
"time-core",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.6.0" version = "1.6.0"
@ -1852,6 +1952,20 @@ dependencies = [
"syn 2.0.66", "syn 2.0.66",
] ]
[[package]]
name = "vapid"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6161e398449b97314c5d3d54b8f89a9ff5eeee696f0169b1778c36dadac7066"
dependencies = [
"backtrace",
"base64 0.13.1",
"openssl",
"serde_json",
"thiserror",
"time",
]
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"

View file

@ -21,6 +21,7 @@ sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] }
tokio = { version = "1.38", features = ["full"] } tokio = { version = "1.38", features = ["full"] }
toml = "0.8" toml = "0.8"
url = "2.5" url = "2.5"
vapid = "0.6"
validator = { version = "0.18", features = ["derive"] } validator = { version = "0.18", features = ["derive"] }
yaml-rust = "0.4" yaml-rust = "0.4"

View file

@ -89,3 +89,9 @@ fishctl config validate
``` ```
Note that this only performs a formal validation and does not check that the settings are appropriate. For example, this command does not check if the database password is correct. Note that this only performs a formal validation and does not check that the settings are appropriate. For example, this command does not check if the database password is correct.
### Generate VAPID keys for push notifications
```sh
fishctl generate vapid
```

View file

@ -467,6 +467,7 @@ fn create_new_server_config(
}, },
id, id,
file, file,
security: todo!(),
}; };
Ok(server_config) Ok(server_config)

23
src/command/generate.rs Normal file
View file

@ -0,0 +1,23 @@
mod vapid;
use clap::Subcommand;
#[derive(Subcommand)]
pub(crate) enum Commands {
/// Generate VAPID keys for push notifications
Vapid,
}
/// Errors that can happen in `generate` subcommand
#[derive(thiserror::Error, Debug)]
pub(crate) enum GenerateError {
#[error(transparent)]
Validate(#[from] vapid::VapidError),
}
pub(super) fn run(command: Commands) -> Result<(), GenerateError> {
match command {
Commands::Vapid => vapid::run()?,
}
Ok(())
}

View file

@ -0,0 +1,15 @@
#[derive(thiserror::Error, Debug)]
#[error("failed to generate a Vapid key ({0})")]
pub struct VapidError(String);
pub(super) fn run() -> Result<(), VapidError> {
let keypair = vapid::Key::generate().map_err(|err| VapidError(err.to_string()))?;
println!("----- public key -----");
println!("{}", keypair.to_public_raw());
println!("----- private key -----");
println!("{}", keypair.to_private_raw());
Ok(())
}

View file

@ -1,6 +1,7 @@
//! Subcommand implementations //! Subcommand implementations
mod config; mod config;
mod generate;
mod version; mod version;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
@ -10,6 +11,8 @@ use clap::{Parser, Subcommand};
pub(crate) enum Error { pub(crate) enum Error {
#[error(transparent)] #[error(transparent)]
Config(#[from] config::ConfigError), Config(#[from] config::ConfigError),
#[error(transparent)]
Generate(#[from] generate::GenerateError),
} }
#[derive(Parser)] #[derive(Parser)]
@ -25,6 +28,9 @@ enum Commands {
/// Modify or validate the config files /// Modify or validate the config files
#[command(subcommand)] #[command(subcommand)]
Config(config::Commands), Config(config::Commands),
/// Generate keys
#[command(subcommand)]
Generate(generate::Commands),
} }
pub(super) async fn run() -> Result<(), Error> { pub(super) async fn run() -> Result<(), Error> {
@ -33,6 +39,7 @@ pub(super) async fn run() -> Result<(), Error> {
match args.command { match args.command {
Commands::Version => version::run(), Commands::Version => version::run(),
Commands::Config(subcommand) => config::run(subcommand).await?, Commands::Config(subcommand) => config::run(subcommand).await?,
Commands::Generate(subcommand) => generate::run(subcommand)?,
} }
Ok(()) Ok(())