mirror of
https://codeberg.org/tyy/aspm
synced 2024-12-22 14:49:28 -07:00
Rename to naja
This commit is contained in:
parent
29c940c623
commit
76d0dbc41d
46 changed files with 217 additions and 233 deletions
41
.vscode/aspm.code-snippets
vendored
41
.vscode/aspm.code-snippets
vendored
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
// Place your aspm workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
|
||||
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
|
||||
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||
// Placeholders with the same ids are connected.
|
||||
// Example:
|
||||
// "Print to console": {
|
||||
// "scope": "javascript,typescript",
|
||||
// "prefix": "log",
|
||||
// "body": [
|
||||
// "console.log('$1');",
|
||||
// "$2"
|
||||
// ],
|
||||
// "description": "Log output to console"
|
||||
// }
|
||||
"Create aspm subcommand": {
|
||||
"scope": "rust",
|
||||
"prefix": "subcommand",
|
||||
"body": [
|
||||
"use clap::Parser;",
|
||||
"",
|
||||
"use crate::commands::AspmSubcommand;",
|
||||
"",
|
||||
"/// $2",
|
||||
"#[derive(Parser, Debug)]",
|
||||
"pub struct $1Command { }",
|
||||
"",
|
||||
"#[async_trait::async_trait]",
|
||||
"impl AspmSubcommand for $1Command {",
|
||||
"\tasync fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {",
|
||||
"\t\t",
|
||||
"\t\t",
|
||||
"\t\tOk(())",
|
||||
"\t}",
|
||||
"}",
|
||||
],
|
||||
"description": "Create a template for an aspm subcommand"
|
||||
}
|
||||
}
|
25
.vscode/naja.code-snippets
vendored
Normal file
25
.vscode/naja.code-snippets
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"Create naja subcommand": {
|
||||
"scope": "rust",
|
||||
"prefix": "subcommand",
|
||||
"body": [
|
||||
"use clap::Parser;",
|
||||
"",
|
||||
"use crate::commands::NajaSubcommand;",
|
||||
"",
|
||||
"/// $2",
|
||||
"#[derive(Parser, Debug)]",
|
||||
"pub struct $1Command { }",
|
||||
"",
|
||||
"#[async_trait::async_trait]",
|
||||
"impl NajaSubcommand for $1Command {",
|
||||
"\tasync fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {",
|
||||
"\t\t",
|
||||
"\t\t",
|
||||
"\t\tOk(())",
|
||||
"\t}",
|
||||
"}",
|
||||
],
|
||||
"description": "Create a template for an naja subcommand"
|
||||
}
|
||||
}
|
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -206,56 +206,6 @@ dependencies = [
|
|||
"term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"data-encoding",
|
||||
"hex_color",
|
||||
"josekit",
|
||||
"openssl",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde-email",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aspm-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"anstyle",
|
||||
"anyhow",
|
||||
"app_dirs2",
|
||||
"argon2",
|
||||
"asp",
|
||||
"assert_cmd",
|
||||
"async-trait",
|
||||
"clap",
|
||||
"clap-stdin",
|
||||
"data-encoding",
|
||||
"dialoguer",
|
||||
"gpgme",
|
||||
"indoc",
|
||||
"josekit",
|
||||
"migrations",
|
||||
"predicates",
|
||||
"scrypt",
|
||||
"sea-orm",
|
||||
"sequoia-openpgp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_cmd"
|
||||
version = "2.0.14"
|
||||
|
@ -691,6 +641,14 @@ version = "0.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
||||
|
||||
[[package]]
|
||||
name = "cli-migrations"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sea-orm-migration",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.1"
|
||||
|
@ -1962,14 +1920,6 @@ version = "0.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c797b9d6bb23aab2fc369c65f871be49214f5c759af65bde26ffaaa2b646b492"
|
||||
|
||||
[[package]]
|
||||
name = "migrations"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sea-orm-migration",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
|
@ -2002,6 +1952,56 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naja-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"anstyle",
|
||||
"anyhow",
|
||||
"app_dirs2",
|
||||
"argon2",
|
||||
"assert_cmd",
|
||||
"async-trait",
|
||||
"clap",
|
||||
"clap-stdin",
|
||||
"cli-migrations",
|
||||
"data-encoding",
|
||||
"dialoguer",
|
||||
"gpgme",
|
||||
"indoc",
|
||||
"josekit",
|
||||
"naja-lib",
|
||||
"predicates",
|
||||
"scrypt",
|
||||
"sea-orm",
|
||||
"sequoia-openpgp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naja-lib"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"data-encoding",
|
||||
"hex_color",
|
||||
"josekit",
|
||||
"openssl",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde-email",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.12"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[workspace]
|
||||
members = ["crates/*"]
|
||||
resolver = "2"
|
||||
default-members = ["crates/aspm"]
|
||||
default-members = ["crates/naja-cli"]
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
|
|
16
README.md
16
README.md
|
@ -1,17 +1,17 @@
|
|||
# aspm
|
||||
# Naja
|
||||
|
||||
This is the **A**riadne **S**ignature **P**rofile **M**anager, a command line program and rust library implementing the [Ariadne Signature Profile specification v0](https://ariadne.id/related/ariadne-signature-profile-0/). Currently, it is updated to the latest version of the spec as of [ariadne/ariadne-identity-specification@92f280bf83](https://codeberg.org/ariadne/ariadne-identity-specification/commit/92f280bf83e2d5957e5a53a6f1b6974bc975517d). This is setup as a cargo workspace with multiple crates, which are all explained below
|
||||
Naja is a project attempting to implement most if not all of the [Ariadne Signature Profile specification v0](https://ariadne.id/related/ariadne-signature-profile-0/) in rust. Currently, it is updated to the latest version of the spec as of [ariadne/ariadne-identity-specification@92f280bf83](https://codeberg.org/ariadne/ariadne-identity-specification/commit/92f280bf83e2d5957e5a53a6f1b6974bc975517d). This is setup as a cargo workspace with multiple crates, which are all explained below
|
||||
|
||||
# Crates
|
||||
|
||||
## aspm
|
||||
## naja-cli
|
||||
|
||||
The main binary crate, featuring all user-facing CLI code. This crate does not contain any actual ASP logic, but rather utilizes the `asp` crate for operations such as generating keys, signing profiles, etc.
|
||||
The main binary crate, featuring all user-facing CLI code. This crate does not contain any actual ASP logic, but rather utilizes the `naja-lib` crate for operations such as generating keys, signing profiles, etc.
|
||||
|
||||
## asp
|
||||
## naja-lib
|
||||
|
||||
The main libary crate, which provides APIs for interfacing with ASP keys, profiles, and exchange servers. This is mainly used by the `aspm` CLI crate, however it could hypothetically be used by other projects (or even a future GUI!)
|
||||
The main libary crate, which provides APIs for interfacing with ASP keys, profiles, and exchange servers. This is mainly used by the `naja-cli` CLI crate, however it could hypothetically be used by other projects (or even a future GUI!)
|
||||
|
||||
## migrations
|
||||
## cli-migrations
|
||||
|
||||
A crate which soley contains database migrations for the `aspm` CLI crate. It contains both a library interface and a binary which can be used to manipulate existing databases.
|
||||
A crate which soley contains database migrations for the `naja-cli` CLI crate. It contains both a library interface and a binary which can be used to manipulate existing databases.
|
|
@ -1,18 +0,0 @@
|
|||
pub mod aspe;
|
||||
pub mod keys;
|
||||
pub mod profiles;
|
||||
|
||||
use clap::Parser;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::AspmState;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait AspmSubcommand: Parser + Sync + Send {
|
||||
async fn execute(self, _state: AspmState) -> Result<(), anyhow::Error> {
|
||||
panic!("Not implemented")
|
||||
}
|
||||
fn execute_sync(self, state: AspmState, runtime: Runtime) -> Result<(), anyhow::Error> {
|
||||
runtime.block_on(self.execute(state))
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "migrations"
|
||||
name = "cli-migrations"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
|
@ -2,5 +2,5 @@ use sea_orm_migration::cli;
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
cli::run_cli(migrations::Migrator).await;
|
||||
cli::run_cli(cli_migrations::Migrator).await;
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
[package]
|
||||
name = "aspm-cli"
|
||||
name = "naja-cli"
|
||||
authors = ["Ty"]
|
||||
description = "A tool to manage ariadne signature profiles, implementing v0 of the specification"
|
||||
repository = "https://codeberg.org/tyy/aspm"
|
||||
repository = "https://codeberg.org/tyy/naja"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "aspm"
|
||||
name = "naja"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
|
@ -15,7 +15,7 @@ anyhow = "1.0.86"
|
|||
app_dirs2 = "2.5.5"
|
||||
clap = { version = "4.5.8", features = ["derive", "unstable-styles", "env"] }
|
||||
thiserror = "1.0.61"
|
||||
asp = { path = "../asp" }
|
||||
naja-lib = { path = "../naja-lib" }
|
||||
indoc = "2.0.5"
|
||||
anstyle = "1.0.7"
|
||||
dialoguer = { version = "0.11.0", features = ["password"] }
|
||||
|
@ -29,7 +29,7 @@ gpgme = { version = "0.11.0", optional = true }
|
|||
sequoia-openpgp = { version = "1.21.1", optional = true }
|
||||
josekit = { version = "0.8.6" }
|
||||
aes-gcm = "0.10.3"
|
||||
migrations = { path = "../migrations" }
|
||||
migrations = { path = "../cli-migrations", package = "cli-migrations" }
|
||||
scrypt = "0.11.0"
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
serde_json = "1.0.120"
|
|
@ -1,7 +1,7 @@
|
|||
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _};
|
||||
use anyhow::{anyhow, bail, Context};
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _};
|
||||
use asp::{
|
||||
use naja_lib::{
|
||||
aspe::{
|
||||
requests::{AspeRequest, AspeRequestType, AspeRequestVariant},
|
||||
AspeRequestFailure, AspeServer,
|
||||
|
@ -17,7 +17,7 @@ use josekit::jwk::Jwk;
|
|||
use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter};
|
||||
|
||||
use crate::{
|
||||
commands::AspmSubcommand,
|
||||
commands::NajaSubcommand,
|
||||
entities::{keys, prelude::*},
|
||||
};
|
||||
|
||||
|
@ -32,8 +32,8 @@ pub struct AspeDeleteCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for AspeDeleteCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for AspeDeleteCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let server = AspeServer::new(self.server)
|
||||
.await
|
||||
.context("Unable to parse provided server into ASPE server, please verify that it is a valid ASPE server")?;
|
|
@ -1,7 +1,7 @@
|
|||
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _};
|
||||
use anyhow::{anyhow, bail, Context};
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _};
|
||||
use asp::{
|
||||
use naja_lib::{
|
||||
aspe::{
|
||||
requests::{AspeRequest, AspeRequestType, AspeRequestVariant},
|
||||
AspeFetchFailure, AspeRequestFailure, AspeServer,
|
||||
|
@ -20,7 +20,7 @@ use josekit::jwk::Jwk;
|
|||
use sea_orm::{ColumnTrait, Condition, EntityTrait, ModelTrait, QueryFilter};
|
||||
|
||||
use crate::{
|
||||
commands::AspmSubcommand,
|
||||
commands::NajaSubcommand,
|
||||
entities::{prelude::*, profiles},
|
||||
};
|
||||
|
||||
|
@ -41,8 +41,8 @@ pub struct AspeUploadCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for AspeUploadCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for AspeUploadCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let server = AspeServer::new(self.server)
|
||||
.await
|
||||
.context("Unable to parse provided server into ASPE server, please verify that it is a valid ASPE server")?;
|
|
@ -1,6 +1,6 @@
|
|||
use anstyle::{AnsiColor, Reset, Style as Anstyle};
|
||||
use anyhow::Context;
|
||||
use asp::keys::AspKeyType;
|
||||
use naja_lib::keys::AspKeyType;
|
||||
use clap::Parser;
|
||||
use dialoguer::{console::Term, theme::ColorfulTheme, Confirm};
|
||||
use indoc::writedoc;
|
||||
|
@ -8,7 +8,7 @@ use sea_orm::ModelTrait as _;
|
|||
|
||||
use std::io::Write;
|
||||
|
||||
use crate::{commands::AspmSubcommand, utils};
|
||||
use crate::{commands::NajaSubcommand, utils};
|
||||
|
||||
/// Deletes a saved key, after asking for confirmation.
|
||||
#[derive(Parser, Debug)]
|
||||
|
@ -21,8 +21,8 @@ pub struct KeysDeleteCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for KeysDeleteCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for KeysDeleteCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
// Fetch key from db
|
||||
let key = utils::keys::query_key(&state.db, self.key).await?;
|
||||
|
|
@ -4,14 +4,14 @@ use aes_gcm::{
|
|||
};
|
||||
use anstyle::{AnsiColor, Color as AnstyleColor, Reset, Style as Anstyle};
|
||||
use anyhow::Context as _;
|
||||
use asp::keys::AspKey;
|
||||
use naja_lib::keys::AspKey;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use data_encoding::{BASE64, BASE64_NOPAD};
|
||||
use dialoguer::{theme::ColorfulTheme, Password};
|
||||
use josekit::jwk::Jwk;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{commands::AspmSubcommand, utils};
|
||||
use crate::{commands::NajaSubcommand, utils};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(tag = "alg", rename = "scrypt")]
|
||||
|
@ -39,7 +39,7 @@ pub enum KeyExportFormat {
|
|||
/// An unencrypted PKCS#8 format.
|
||||
#[clap(alias = "PKCS#8")]
|
||||
PKCS8,
|
||||
/// An scrypt-encrypted PKCS#8 key, formatted for the asp.keyoxide.org web tool. The password on the exported key is the same as the one used for ASPM.
|
||||
/// An scrypt-encrypted PKCS#8 key, formatted for the asp.keyoxide.org web tool. The password on the exported key is the same as the one used for naja.
|
||||
ASPTool,
|
||||
/// An unencrypted raw JSON Web Key (JWK) format.
|
||||
Jwk,
|
||||
|
@ -56,8 +56,8 @@ pub struct KeysExportCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for KeysExportCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for KeysExportCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
// Fetch key from db
|
||||
let key = utils::keys::query_key(&state.db, self.key).await?;
|
||||
|
|
@ -4,14 +4,14 @@ use aes_gcm::{
|
|||
};
|
||||
use anyhow::{anyhow, bail, Context};
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
|
||||
use asp::keys::{AspKey, AspKeyType};
|
||||
use naja_lib::keys::{AspKey, AspKeyType};
|
||||
use clap::{Parser, ValueEnum};
|
||||
use data_encoding::BASE64_NOPAD;
|
||||
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Password};
|
||||
use indoc::printdoc;
|
||||
use sea_orm::{ActiveValue, EntityTrait};
|
||||
|
||||
use crate::{commands::AspmSubcommand, entities::keys};
|
||||
use crate::{commands::NajaSubcommand, entities::keys};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
|
||||
pub enum KeyGenerationType {
|
||||
|
@ -19,7 +19,7 @@ pub enum KeyGenerationType {
|
|||
ES256,
|
||||
}
|
||||
|
||||
/// Allows you to generate a new key for use with ariadne signature profiles. This will be stored in the ASPM data directory, but can then be exported with the `keys export` command.
|
||||
/// Allows you to generate a new key for use with ariadne signature profiles. This will be stored in the naja data directory, but can then be exported with the `keys export` command.
|
||||
/// A password needs to be provided, so it should either be given via the KEY_PASSWORD environment variable, or omitted in order to prompt interactively.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct KeysGenerateCommand {
|
||||
|
@ -33,8 +33,8 @@ pub struct KeysGenerateCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for KeysGenerateCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for KeysGenerateCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
if self.key_type == KeyGenerationType::Ed25519 {
|
||||
let confirmation = Confirm::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt("You are creating an Ed25519 key. Before confirming, please make sure you are aware that this may not be supported in browser environments, such as being viewed on https://keyoxide.org. Are you sure you want to create an Ed25519 key?")
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::{anyhow, bail, Context};
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
|
||||
use asp::keys::AspKey;
|
||||
use naja_lib::keys::AspKey;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use data_encoding::{BASE64, BASE64URL_NOPAD, BASE64_NOPAD};
|
||||
use dialoguer::{theme::ColorfulTheme, Input, Password};
|
||||
|
@ -14,7 +14,7 @@ use josekit::jwk::Jwk;
|
|||
use sea_orm::{ActiveValue, EntityTrait};
|
||||
|
||||
use crate::{
|
||||
commands::{keys::export::ASPToolScryptExport, AspmSubcommand},
|
||||
commands::{keys::export::ASPToolScryptExport, NajaSubcommand},
|
||||
entities::keys,
|
||||
};
|
||||
|
||||
|
@ -45,8 +45,8 @@ pub struct KeysImportCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for KeysImportCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for KeysImportCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let alias = if let Some(alias) = &self.key_alias {
|
||||
alias.clone()
|
||||
} else {
|
|
@ -1,21 +1,21 @@
|
|||
use anstyle::{AnsiColor, Reset, Style as Anstyle};
|
||||
use anyhow::Context;
|
||||
use asp::keys::AspKeyType;
|
||||
use naja_lib::keys::AspKeyType;
|
||||
use clap::Parser;
|
||||
use indoc::writedoc;
|
||||
use sea_orm::EntityTrait;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use crate::{commands::AspmSubcommand, entities::prelude::*};
|
||||
use crate::{commands::NajaSubcommand, entities::prelude::*};
|
||||
|
||||
/// A command to list all saved keys, along with their fingerprints and types
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct KeysListCommand;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for KeysListCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for KeysListCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let entries = Keys::find()
|
||||
.all(&state.db)
|
||||
.await
|
18
crates/naja-cli/src/commands/mod.rs
Normal file
18
crates/naja-cli/src/commands/mod.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
pub mod aspe;
|
||||
pub mod keys;
|
||||
pub mod profiles;
|
||||
|
||||
use clap::Parser;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::CliState;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait NajaSubcommand: Parser + Sync + Send {
|
||||
async fn execute(self, _state: CliState) -> Result<(), anyhow::Error> {
|
||||
panic!("Not implemented")
|
||||
}
|
||||
fn execute_sync(self, state: CliState, runtime: Runtime) -> Result<(), anyhow::Error> {
|
||||
runtime.block_on(self.execute(state))
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Context;
|
||||
use asp::{
|
||||
use naja_lib::{
|
||||
hex_color::HexColor, keys::AspKeyType, profiles::*, serde_email::Email, url::Url,
|
||||
utils::jwt::AspJwsType,
|
||||
};
|
||||
|
@ -10,7 +10,7 @@ use dialoguer::{theme::ColorfulTheme, Input, Select};
|
|||
use sea_orm::{ActiveValue, EntityTrait};
|
||||
|
||||
use crate::{
|
||||
commands::AspmSubcommand,
|
||||
commands::NajaSubcommand,
|
||||
entities::{
|
||||
claims::{self, Entity as Claims},
|
||||
keys::Entity as Keys,
|
||||
|
@ -29,8 +29,8 @@ pub struct ProfilesCreateCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for ProfilesCreateCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for ProfilesCreateCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let theme = ColorfulTheme::default();
|
||||
|
||||
let alias = if let Some(alias) = &self.profile_alias {
|
|
@ -7,7 +7,7 @@ use sea_orm::{EntityTrait, ModelTrait};
|
|||
|
||||
use std::io::Write;
|
||||
|
||||
use crate::{commands::AspmSubcommand, entities::prelude::*};
|
||||
use crate::{commands::NajaSubcommand, entities::prelude::*};
|
||||
|
||||
/// Deletes a saved profile
|
||||
#[derive(Parser, Debug)]
|
||||
|
@ -20,8 +20,8 @@ pub struct ProfilesDeleteCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for ProfilesDeleteCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for ProfilesDeleteCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let profile = match &self.profile {
|
||||
Some(key) => Profiles::find_by_id(key)
|
||||
.one(&state.db)
|
|
@ -1,6 +1,6 @@
|
|||
use anstyle::{AnsiColor, Reset, Style as Anstyle};
|
||||
use anyhow::{bail, Context};
|
||||
use asp::{hex_color::HexColor, serde_email::Email, url::Url};
|
||||
use naja_lib::{hex_color::HexColor, serde_email::Email, url::Url};
|
||||
use clap::Parser;
|
||||
use dialoguer::{theme::ColorfulTheme, Input, Select};
|
||||
use indoc::writedoc;
|
||||
|
@ -9,7 +9,7 @@ use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait, IntoActiveModel, IntoA
|
|||
use std::{io::Write, str::FromStr};
|
||||
|
||||
use crate::{
|
||||
commands::AspmSubcommand,
|
||||
commands::NajaSubcommand,
|
||||
entities::{claims::ActiveModel as ClaimActiveModel, prelude::*},
|
||||
};
|
||||
|
||||
|
@ -21,8 +21,8 @@ pub struct ProfilesEditCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for ProfilesEditCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for ProfilesEditCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let (profile, claims) = match &self.profile {
|
||||
Some(fingerprint) => {
|
||||
let mut profiles = Profiles::find_by_id(fingerprint)
|
|
@ -1,7 +1,7 @@
|
|||
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _};
|
||||
use anyhow::{anyhow, bail, Context};
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _};
|
||||
use asp::{
|
||||
use naja_lib::{
|
||||
hex_color::HexColor,
|
||||
keys::AspKey,
|
||||
profiles::AriadneSignatureProfile,
|
||||
|
@ -16,7 +16,7 @@ use josekit::jwk::Jwk;
|
|||
use sea_orm::{ColumnTrait, Condition, EntityTrait, ModelTrait, QueryFilter};
|
||||
|
||||
use crate::{
|
||||
commands::AspmSubcommand,
|
||||
commands::NajaSubcommand,
|
||||
entities::{prelude::*, profiles},
|
||||
};
|
||||
|
||||
|
@ -31,8 +31,8 @@ pub struct ProfilesExportCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for ProfilesExportCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for ProfilesExportCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let Some(profile) = Profiles::find()
|
||||
.filter(
|
||||
Condition::any()
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Context;
|
||||
use asp::{
|
||||
use naja_lib::{
|
||||
aspe::{self, AspeFetchFailure},
|
||||
profiles::AriadneSignatureProfile,
|
||||
url::{Host, Url},
|
||||
|
@ -9,7 +9,7 @@ use clap::Parser;
|
|||
use sea_orm::{EntityTrait, IntoActiveValue, SqlErr, TransactionTrait as _};
|
||||
|
||||
use crate::{
|
||||
commands::AspmSubcommand,
|
||||
commands::NajaSubcommand,
|
||||
entities::{claims, prelude::*, profiles},
|
||||
};
|
||||
|
||||
|
@ -24,8 +24,8 @@ pub struct ProfilesImportCommand {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for ProfilesImportCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for ProfilesImportCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
let (profile, fingerprint) = match Url::parse(&self.profile).ok().and_then(|url| {
|
||||
Some({
|
||||
let (host, fingerprint) = url.path().split_once(':')?;
|
|
@ -6,15 +6,15 @@ use sea_orm::EntityTrait;
|
|||
|
||||
use std::io::Write;
|
||||
|
||||
use crate::{commands::AspmSubcommand, entities::prelude::*};
|
||||
use crate::{commands::NajaSubcommand, entities::prelude::*};
|
||||
|
||||
/// Lists all of the saved profiles, along with their stored data
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct ProfilesListCommand {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AspmSubcommand for ProfilesListCommand {
|
||||
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> {
|
||||
impl NajaSubcommand for ProfilesListCommand {
|
||||
async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
|
||||
// Fetch data
|
||||
let profiles = Profiles::find()
|
||||
.find_with_related(Claims)
|
|
@ -8,7 +8,7 @@ use anyhow::Context;
|
|||
use app_dirs2::{AppDataType, AppInfo};
|
||||
use clap::{Parser, Subcommand};
|
||||
use commands::{
|
||||
aspe::AspeSubcommands, keys::KeysSubcommands, profiles::ProfilesSubcommands, AspmSubcommand,
|
||||
aspe::AspeSubcommands, keys::KeysSubcommands, profiles::ProfilesSubcommands, NajaSubcommand,
|
||||
};
|
||||
use migrations::{Migrator, MigratorTrait, SchemaManager};
|
||||
use sea_orm::{Database, DatabaseConnection};
|
||||
|
@ -23,7 +23,7 @@ const APP_INFO: AppInfo = AppInfo {
|
|||
const DATABASE_URL: &str = "sqlite://DB_PATH?mode=rwc";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AspmState {
|
||||
pub struct CliState {
|
||||
pub data_dir: PathBuf,
|
||||
pub db: DatabaseConnection,
|
||||
pub verbose: bool,
|
||||
|
@ -34,12 +34,12 @@ pub struct AspmState {
|
|||
version,
|
||||
about,
|
||||
long_about,
|
||||
styles = AspmCommand::styles()
|
||||
styles = NajaCommand::styles()
|
||||
)]
|
||||
struct AspmCommand {
|
||||
struct NajaCommand {
|
||||
#[clap(long_about)]
|
||||
|
||||
/// The directory to use, overriding OS defaults. This can also be set with the ASPM_DATA_DIR environment variable.
|
||||
/// The directory to use, overriding OS defaults. This can also be set with the NAJA_DATA_DIR environment variable.
|
||||
/// The order of precedence is:
|
||||
/// 1. Command line flag
|
||||
/// 2. Environment variable
|
||||
|
@ -51,10 +51,10 @@ struct AspmCommand {
|
|||
verbose: bool,
|
||||
/// The subcommand to use
|
||||
#[command(subcommand)]
|
||||
subcommand: AspmSubcommands,
|
||||
subcommand: NajaSubcommands,
|
||||
}
|
||||
|
||||
impl AspmCommand {
|
||||
impl NajaCommand {
|
||||
fn styles() -> clap::builder::Styles {
|
||||
clap::builder::Styles::styled()
|
||||
.header(
|
||||
|
@ -79,14 +79,14 @@ impl AspmCommand {
|
|||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum AspmSubcommands {
|
||||
pub enum NajaSubcommands {
|
||||
Keys(commands::keys::KeysSubcommand),
|
||||
Profiles(commands::profiles::ProfilesSubcommand),
|
||||
Aspe(commands::aspe::AspeSubcommand),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let parsed = AspmCommand::parse();
|
||||
let parsed = NajaCommand::parse();
|
||||
let verbose = parsed.verbose;
|
||||
|
||||
if verbose {
|
||||
|
@ -111,7 +111,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
fn cli(parsed: AspmCommand) -> Result<(), anyhow::Error> {
|
||||
fn cli(parsed: NajaCommand) -> Result<(), anyhow::Error> {
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
|
@ -120,13 +120,13 @@ fn cli(parsed: AspmCommand) -> Result<(), anyhow::Error> {
|
|||
let state = runtime.block_on(async {
|
||||
// Check the data dir (read and write)
|
||||
let data_dir = parsed.data_dir.unwrap_or(
|
||||
std::env::var("ASPM_DATA_DIR").map(|s| s.into()).unwrap_or(
|
||||
std::env::var("NAJA_DATA_DIR").map(|s| s.into()).unwrap_or(
|
||||
app_dirs2::get_app_root(AppDataType::UserData, &APP_INFO)
|
||||
.map_err(|e| AspmError::Unknown(e.into()))?,
|
||||
.map_err(|e| NajaError::Unknown(e.into()))?,
|
||||
),
|
||||
);
|
||||
std::fs::create_dir_all(&data_dir).or(Err(AspmError::DataDirCreate))?;
|
||||
std::fs::read_dir(&data_dir).or(Err(AspmError::DataDirRead))?;
|
||||
std::fs::create_dir_all(&data_dir).or(Err(NajaError::DataDirCreate))?;
|
||||
std::fs::read_dir(&data_dir).or(Err(NajaError::DataDirRead))?;
|
||||
// Construct the database in the dir
|
||||
let db = Database::connect(DATABASE_URL.replace("DB_PATH", &{
|
||||
let mut new = data_dir.clone();
|
||||
|
@ -147,25 +147,25 @@ fn cli(parsed: AspmCommand) -> Result<(), anyhow::Error> {
|
|||
.context("Unable to check database for keys table")?);
|
||||
|
||||
// Make the state
|
||||
let state = AspmState {
|
||||
let state = CliState {
|
||||
data_dir,
|
||||
db,
|
||||
verbose: parsed.verbose,
|
||||
};
|
||||
|
||||
Ok::<AspmState, anyhow::Error>(state)
|
||||
Ok::<CliState, anyhow::Error>(state)
|
||||
})?;
|
||||
|
||||
// Call the subcommand
|
||||
match parsed.subcommand {
|
||||
AspmSubcommands::Keys(subcommand) => match subcommand.subcommand {
|
||||
NajaSubcommands::Keys(subcommand) => match subcommand.subcommand {
|
||||
KeysSubcommands::Generate(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
KeysSubcommands::List(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
KeysSubcommands::Export(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
KeysSubcommands::Delete(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
KeysSubcommands::Import(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
},
|
||||
AspmSubcommands::Profiles(subcommand) => match subcommand.subcommand {
|
||||
NajaSubcommands::Profiles(subcommand) => match subcommand.subcommand {
|
||||
ProfilesSubcommands::Create(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
ProfilesSubcommands::Export(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
ProfilesSubcommands::List(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
|
@ -173,7 +173,7 @@ fn cli(parsed: AspmCommand) -> Result<(), anyhow::Error> {
|
|||
ProfilesSubcommands::Delete(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
ProfilesSubcommands::Import(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
},
|
||||
AspmSubcommands::Aspe(subcommand) => match subcommand.subcommand {
|
||||
NajaSubcommands::Aspe(subcommand) => match subcommand.subcommand {
|
||||
AspeSubcommands::Upload(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
AspeSubcommands::Delete(subcommand) => subcommand.execute_sync(state, runtime),
|
||||
},
|
||||
|
@ -181,7 +181,7 @@ fn cli(parsed: AspmCommand) -> Result<(), anyhow::Error> {
|
|||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
enum AspmError {
|
||||
enum NajaError {
|
||||
#[error("The data directory was unable to be created, is it correct, and does the current user have permission to create it?")]
|
||||
DataDirCreate,
|
||||
#[error("The data directory was unable to be read, is it correct, and does the current user have permission to read it?")]
|
|
@ -12,8 +12,8 @@ static KEY_PASSWORD: &str = "TESTKEYPASSWORD";
|
|||
|
||||
// TODO: Also test ed25519 key generation
|
||||
fn assert_key_generated(datadir: &str) -> Result<(), anyhow::Error> {
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("generate")
|
||||
.env("KEY_PASSWORD", KEY_PASSWORD)
|
||||
|
@ -37,29 +37,29 @@ fn help_works() -> Result<(), anyhow::Error> {
|
|||
.to_str()
|
||||
.context("Tempdir path was not valid utf8")?;
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("--help")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("-h")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("help")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.assert()
|
||||
.code(2)
|
||||
.stderr(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
|
||||
|
@ -88,8 +88,8 @@ fn keys_list_works() -> Result<(), anyhow::Error> {
|
|||
|
||||
assert_key_generated(datadir)?;
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("list")
|
||||
.assert()
|
||||
|
@ -111,8 +111,8 @@ fn keys_export_works() -> Result<(), anyhow::Error> {
|
|||
assert_key_generated(datadir)?;
|
||||
|
||||
for export_format in ["pkcs8", "asp-tool", "jwk"] {
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("export")
|
||||
.env("KEY_PASSWORD", KEY_PASSWORD)
|
||||
|
@ -139,8 +139,8 @@ fn keys_import_works() -> Result<(), anyhow::Error> {
|
|||
("asp-tool", TEST_KEY_ASPTOOL),
|
||||
("jwk", TEST_KEY_JWK),
|
||||
] {
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("import")
|
||||
.env("KEY_PASSWORD", TEST_KEY_PASSWORD)
|
||||
|
@ -155,16 +155,16 @@ fn keys_import_works() -> Result<(), anyhow::Error> {
|
|||
.and(predicate::str::contains(TEST_FINGERPRINT)),
|
||||
);
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("list")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains(TEST_FINGERPRINT));
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("delete")
|
||||
.arg("--no-confirm")
|
||||
|
@ -189,8 +189,8 @@ fn keys_delete_works() -> Result<(), anyhow::Error> {
|
|||
|
||||
assert_key_generated(datadir)?;
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("delete")
|
||||
.arg("--no-confirm")
|
||||
|
@ -201,8 +201,8 @@ fn keys_delete_works() -> Result<(), anyhow::Error> {
|
|||
"Successfully deleted key with fingerprint ",
|
||||
));
|
||||
|
||||
Command::cargo_bin("aspm")?
|
||||
.env("ASPM_DATA_DIR", datadir)
|
||||
Command::cargo_bin("naja")?
|
||||
.env("NAJA_DATA_DIR", datadir)
|
||||
.arg("keys")
|
||||
.arg("list")
|
||||
.assert()
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "asp"
|
||||
name = "naja-lib"
|
||||
description = "A library implementation of the ariadne signature profile specification v0"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
|
@ -17,6 +17,7 @@ pub struct AspeVersion {
|
|||
}
|
||||
|
||||
/// An ASPE-compatible server
|
||||
#[derive(Clone)]
|
||||
pub struct AspeServer {
|
||||
pub host: Host,
|
||||
client: reqwest::Client,
|
||||
|
@ -82,7 +83,7 @@ impl AspeServer {
|
|||
host,
|
||||
client: reqwest::Client::builder()
|
||||
.user_agent(format!(
|
||||
"asp-rs/{version} ({repo})",
|
||||
"naja-lib/{version} ({repo})",
|
||||
version = env!("CARGO_PKG_VERSION"),
|
||||
repo = env!("CARGO_PKG_REPOSITORY")
|
||||
))
|
||||
|
@ -166,8 +167,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn building_aspe_server_succeeds() {
|
||||
let result = AspeServer::new(Host::Domain(String::from("keyoxide.org"))).await;
|
||||
assert!(result.is_ok(), "Constructing an AspeServer should succeed")
|
||||
AspeServer::new(Host::Domain(String::from("keyoxide.org"))).await.expect("Contructing an AspeServer should succeed");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
Loading…
Reference in a new issue